Timestamp Dependence
Timestamp Dependence¶
Be aware that the timestamp of the block can be manipulated by the miner, and all direct and indirect uses of the timestamp should be considered.
Block timestamps have historically been used for a variety of applications, such as entropy for random numbers (see the Entropy Illusion for further details), locking funds for periods of time, and various state-changing conditional statements that are time-dependent.
From Solidity docs:
Do not rely on
block.timestamp
,now
andblockhash
as a source of randomness, unless you know what you are doing. [..] The current block timestamp must be strictly larger than the timestamp of the last block, but the only guarantee is that it will be somewhere between the timestamps of two consecutive blocks in the canonical chain.
From Ethereum Stack Exchange question:
Block times are subject to the following constraints:
• If you stamp your block with a time too far in the future, no one else will build on it (miners will not build on a block timestamped "from the future").
• Your block time cannot be stamped with an earlier time than its parent.
• Difficulty is kept lowest (best deal for miners) by not stamping blocks as earlier than they actually occur.
• using strict equality ==
block.timestamp would not be safe, since a block with that exact timestamp may never get mined. So use >=
block.timestamp
Taken together, these factors suggest that most blocks produced by small hashrate miners who are not trying to manipulate anything will be pretty close to accurate. However, it is trivial for a more powerful miner to manipulate timestamps over short periods, especially if there is something to be gained by doing this.
Ultimate, there is no cryptographic way to verify the timestamp itself--only the ordering of certain cryptographic structures. Therefore block.timestamp needs to be supplemented with some other strategy in the case of high-value/risk applications.
block.timestamp
and its alias now
can be manipulated by miners if they have some incentive to do so. Let’s construct a simple game, shown in roulette.sol, that would be vulnerable to miner exploitation.
Block Timestamp vs Block Number
block.timestamp
can be manipulated by miners. The only constraint is that a timestamp has to be larger than the previous block's timestamp. Timestamps too far in the future are usually ignored by the network, but the miner usually has a 30-second window within which to choose a timestamp. Watch out for the use of block.timestamp
for anything that is time-sensitive, like auctions or lottery ends. Contracts should proceed without assuming timestamp accuracy.
block.number
can also lead to problems. There's no way to safely predict when a specific block will be mined.
As a rule of thumb, the block.timestamp
is generally preferred, subject to accommodation of its inaccurate nature.
Example
roulette.sol from Mastering Ethereum book
This contract behaves like a simple lottery. One transaction per block can bet 10 ether for a chance to win the balance of the contract. The assumption here is that block.timestamp
’s last two digits are uniformly distributed. If that were the case, there would be a 1 in 15 chance of winning this lottery.
However, as we know, miners can adjust the timestamp should they need to. In this particular case, if enough ether pools in the contract, a miner who solves a block is incentivized to choose a timestamp such that block.timestamp
or now
modulo 15 is 0. In doing so they may win the ether locked in this contract along with the block reward. As there is only one person allowed to bet per block, this is also vulnerable to front-running attacks (see Race Conditions/Front Running for further details).
In practice, block timestamps are monotonically increasing and so miners cannot choose arbitrary block timestamps (they must be later than their predecessors). They are also limited to setting block times not too far in the future, as these blocks will likely be rejected by the network (nodes will not validate blocks whose timestamps are in the future).
Example
From Consensys recommendations
Be aware that the timestamp of the block can be manipulated by a miner. Consider this contract
When the contract uses the timestamp to seed a random number, the miner can actually post a timestamp within 15 seconds of the block being validated, effectively allowing the miner to precompute an option more favorable to their chances in the lottery. Timestamps are not random and should not be used in that context.
The 15-second Rule
The Yellow Paper (Ethereum's reference specification) does not specify a constraint on how much blocks can drift in time, but it does specify that each timestamp should be bigger than the timestamp of its parent. Popular Ethereum protocol implementations Geth and Parity both reject blocks with timestamp more than 15 seconds in future. Therefore, a good rule of thumb in evaluating timestamp usage is:
Real-World Example: GovernMental
GovernMental, the old Ponzi scheme mentioned above, was also vulnerable to a timestamp-based attack. The contract paid out to the player who was the last player to join (for at least one minute) in a round. Thus, a miner who was a player could adjust the timestamp (to a future time, to make it look like a minute had elapsed) to make it appear that they were the last player to join for over a minute (even though this was not true in reality). More detail on this can be found in the “History of Ethereum Security Vulnerabilities, Hacks and Their Fixes” post by Tanya Bahrynovska.
References
https://consensys.github.io/smart-contract-best-practices/known_attacks/#timestamp-dependence https://github.com/ethereumbook/ethereumbook/blob/develop/09smart-contracts-security.asciidoc#block-timestamp-manipulation https://ethereum.stackexchange.com/questions/413/can-a-contract-safely-rely-on-block-timestamp
Preventative Techniques
To avoid miner manipulation in random number generation, there are a few solutions:
A commitment scheme such as RANDAO, a DAO where the random number is generated by all participants in the DAO.
External sources via oracles, e.g. Oraclize.
Using Bitcoin block hashes, as the network is more decentralized and blocks are more expensive to mine.
Timestamp Dependence
There are three main considerations when using a timestamp to execute a critical function in a contract, especially when actions involve fund transfer.
Time-sensitive logic is sometimes required; e.g., for unlocking contracts (time-locking), completing an ICO after a few weeks, or enforcing expiry dates. It is sometimes recommended to use block.number and an average block time to estimate times; with a 10 second
block time, 1 week
equates to approximately, 60480
blocks. Thus, specifying a block number at which to change a contract state can be more secure, as miners are unable easily to manipulate the block number. The BAT ICO contract employed this strategy.
It is possible to estimate a time delta using the block.number
property and average block time, however this is not future proof as block times may change (such as fork reorganisations and the difficulty bomb). In a sale spanning days, the 15-second rule allows one to achieve a more reliable estimate of time.
Note
If the scale of your time-dependent event can vary by 15 seconds and maintain integrity, it is safe to use a block.timestamp
.
Block Timestamp vs Block Number
block.timestamp can be manipulated by miners. The only constraint is that a timestamp has to be larger than the previous block's timestamp. Timestamps too far in the future are usually ignored by the network, but the miner usually has a 30-second window within which to choose a timestamp. Watch out for the use of block.timestamp
for anything that is time-sensitive, like auctions or lottery ends. Contracts should proceed without assuming timestamp accuracy.
block.number can also lead to problems. There's no way to safely predict when a specific block will be mined.
As a rule of thumb, the block.timestamp is generally preferred, subject to accommodation of its inaccurate nature.
Resources
Last updated