[Ethereum] How time difference can be calculated by block.number and how it is different from block.timestamp

block-intervalsoliditytimestamp

I have been looking into the code recently done by some developers, they are using block.number + numbers to calculate the time difference. For example if I want to lock fund for some 6 months or 180 days developers are using block.number + (some calculated numbers 1296000 blocks) to calculate number of funds to be unlocked.

I would like to know how this calculation works with time period. And why not to use block.timestamp instead? Is block.number reliable?

Here is the code snippet. It is basically vault that hold the tokens for 180 days.

contract Vault is SafeMath {

    // flag to determine if address is for a real contract or not
    bool public isVault = false;

    Token token;
    address multisig;
    uint256 unlockedAtBlockNumber;
    // 1296000 blocks = 6 months * 30 days / month * 24 hours / day * 60 minutes / hour * 60 seconds / minute / 12 seconds per block
    //uint256 public constant numBlocksLocked = 1296000;
    // smaller lock for testing
    uint256 public constant numBlocksLocked = 12;

    /// @notice Constructor function sets the Lunyr Multisig address and
    /// total number of locked tokens to transfer
    function Vault(address _Multisig) internal {
        if (_Multisig == 0x0) throw;
        token = Token(msg.sender);
        multisig = _Multisig;
        isVault = true;
        unlockedAtBlockNumber = safeAdd(block.number, numBlocksLocked); // 180 days of blocks later
    }

    /// @notice Transfer locked tokens to multisig wallet
    function unlock() external {
        // Wait your turn!
        if (block.number < unlockedAtBlockNumber) throw;
        // Will fail if allocation (and therefore toTransfer) is 0.
        if (!token.transfer(multisig, token.balanceOf(this))) throw;
        // Otherwise ether are trapped here, we could disallow payable instead...
        if (!multisig.send(this.balance)) throw;
    }

    // disallow payment after unlock block
    function () payable {
        if (block.number >= unlockedAtBlockNumber) throw;
    }

}

Best Answer

I believe the block.timestamp is the wall-clock date/time at which the block was mined. A block number set in the future based on some other block is based on an estimate of the rate of block mining. For example, the average/target block time is, at the time of writing, about ~17s. So if you want to set a time 24 hours in the future via block number, you can use 24 * 60 * 60 / 17 (number of seconds in a day divided by number of seconds per block) to determine roughly what block number will be mined at that time. Note that for times in the mid- and far- future, you will need to take into account the ice age: the rate of block generation will slow down, by design, to encourage a hard fork for proof-of-stake and, in the meantime, makes the profitability of mining decrease materially (when denominated in eth) as the ice age progresses.

Here is a simulator to get an idea of what is happening: https://gist.github.com/CJentzsch/c78768f9837afb8eef74 Note that the rate of slowing has been slowed by a more recent change to the Ethereum protocol, so the simulator is out of date.

Related Topic