Hack Solidity: Block Timestamp Manipulation
Kamil Polak
Posted on January 14, 2022
Timestamp provides information about the date and time in which the block is mined. When you go e.g. to the etherscan you can find a timestamp for each block that was mined.
Block timestamp can be manipulated by miners a then used to their advantage to attack a smart contract.
Let's go into details of how this could happen using the contract below.
contract Roulette {
uint public pastBlockTime;
constructor() payable {}
function spin() external payable {
require(msg.value == 5 ether); // player must send 5 ether to play
require(block.timestamp != pastBlockTime); // only 1 transaction per block
pastBlockTime = block.timestamp;
// if the block.timestamp is divisible by 7 you win the Ether in the contract
if (block.timestamp % 7 == 0) {
(bool sent, ) = msg.sender.call{value: address(this).balance}("");
require(sent, "Failed to send Ether");
}
}
}
I created a simple game where a player can win all of the Ether in the contract if he submits a transaction at a specific time.
To join the game player need to send 5 ether. To play the game player call the spin
function. If the block.timestamp is divisible by 7 player win all the Ether in the contract.
The miner that wants to win all of the Ethers can manipulate the contract. To do so he can:
call the
spin
function and submit 5 Ether to enter the gamesubmit a
block.timestamp
for the next block that is divisible by 7
How to prevent block timestamp attacks
There are two ways to prevent block timestamp attacks:
do not use block.timestamp in your contract
apply the 15-second rule which says that
If the scale of your time-dependent event can vary by 15 seconds and maintain integrity, it is safe to use a
block.timestamp
.
Sources
Posted on January 14, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.