A miner can manipulate the block timestamp which can be used to their advantage to attack a smart contract. In this tutorial we will review how a miner can manipulate the Ethereum system to remove Ether from a Solidity smart contract.
Manipulating the block timestamp on the blockchain
Blocks have a timestamp field in the block header which is set by the miner and can be changed to whatever they want (with some restriction). In order for a miner to set a block timestamp they need to win the next block and abide by the following time constrains:
- The next timestamp is after the last block timestamp
- The timestamp can not be too far into the future
If the miner wins a block they can slightly change the block timestamp to their advantage.
Solidity smart contract that uses block timestamp
In the example below Alice’s contract is exploited by Mike the miner..
Lets go into more details of how this could happen using the contract below.
The roulette contract below is a game where you can win all of the Ether in the contract if you can submit a transaction at a specific time. The contract contains 10 Ether. To play the game you call the function spin and send the contract 1 Ether. If the block.timestamp is divisible by 7 you win all the Ether in the contract.
pragma solidity ^0.7.6;
contract Roulette {
uint public pastBlockTime;
constructor() payable {}
// call spin and send 1 ether to play
function spin() external payable {
require(msg.value == 1 ether);
require(block.timestamp != pastBlockTime);
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");
}
}
}
Try it in Remix
Miner attack by manipulating the block timestamp
A large miner will try to manipulate the system to win the Ether in this contract. They will perform the following steps:
- Call the spin function and submit 1 Ether to play the game
- Then submit a block timestamp for the next block that is divisible by 7
If the miner wins the next block he will win all the Ether in the smart contract. This is one of the many examples of how a Solidity smart contract can be exploited with block.timestamp.
Prevent block timestamp attacks
To prevent this type of attack do not use block.timestamp in your contract or follow the 15 second rule. The 15 second rule states:
If the scale of your time-dependent event can vary by 15 seconds and maintain integrity, it is safe to use a block.timestamp
.
This means if your contract does not rely on an interval of less then 15 seconds then it is okay to use block.timestamp.
This code is for learning and entertainment purposes only. This code has not been audited so use at your own risk. Remember smart contracts are experimental and could contain bugs.
Click here for more information about how to use the Ethereum test network and how to obtain test ETH.
1 thought on “Block timestamp manipulation attack”