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
.
Top comments (1)
at least make the modulo a bigger number than 7. it can literally be solved by just running it until u win which is like 10 times MAX