Solidity – Accessing Past Values of Smart Contract Variables with Web3js

contract-developmentsolidityweb3js

I would like to know if is possible to inquiry variable values using older blocks.

For example I have

contract Simple {
    string32 message public;

    function Simple() {
        message = msg.sender;
    }
}

Is it possible to retrieve the value of the message 1 month ago? Is there a method that let me inspect such variable on particular blockheight?

Is there a method that retrieves all different values that are found on the blockchain?

Thank you very much.

Best Answer

There is no way for a contract to access a variable that is no longer located in storage. You can access these variables from web3, however.

I would recommend using Events, which you could index by timestamp to make searching easier.

With web3, there is a possible solution (probably not the fastest or the most elegant, but it is to show how it can be done). We retrieve the first variable of the contract (index 0), which is of type uint:

contract = "0x6d363cd2eb21ebd39e50c9a2f94a9724bf907d13";
maxBlocks = 1000;

startBlock = eth.blockNumber;
for (var i = 1; i < maxBlocks; i++) { /* Be careful: we go *back* in time */
    current = web3.eth.getStorageAt(contract, 0, startBlock-i);
    if (current != previous) {
        /* TODO Where to find msg.sender? We probably have to loop
         * over the transactions in the block can call
         * web3.eth.getTransaction */
        blockDate = new Date(web3.eth.getBlock(startBlock-i+1).timestamp*1000);
        console.log("Block #" + (startBlock-i+1) +  " (" + web3.eth.getBlock(startBlock-i+1).timestamp + " " + blockDate.toString()
            +  ") : " + web3.toDecimal(previous));
        /* What if there are two changes in a single block? The
         * documentation of getStorageAt seems silent about that */
        previous = current;
    }
}
blockDate = new Date(web3.eth.getBlock(startBlock-maxBlocks).timestamp*1000);
console.log("Somewhere before block #" +(startBlock-maxBlocks) +  " (block of " + blockDate.toString()
        +  ") : " + web3.toDecimal(previous));

You can try it on Testnet, where the contract with this address has been deployed.

Related Topic