The dangers of using blockhash and block timestamp for randomness in Ethereum contracts
blockhash and block.timestamp are two properties of blocks in the Ethereum blockchain that contract developers often use to generate random numbers. However, there are several reasons why these methods should be avoided for this purpose.
First, the blockhash of a block is determined by the transactions and state roots of the previous block. This means that it is not truly random, as it is based on known information when the block is mined.
Similarly, the block timestamp is set by the block's miner and is not guaranteed to be accurate. Miners can manipulate the timestamp to their advantage, leading to potential security vulnerabilities.
Additionally, both blockhash and block timestamp are deterministic, which means that they will always produce the same output given the same input. This makes it easy for attackers to predict the output of these functions and exploit any vulnerabilities that may exist in your contract.
Here is an example:
contract GuessRandomNo {
contructor() payable {}
function guessNo(uint _guess) public {
uint anser = uint(keccak256(abi.encodePacked(blockhash(block.number - 1), block.timestamp)));
}
if (_guess == answer){
(bool sent, ) = msg.sender.call{value: 1 ether}("");
require(sent, "Failed to send ether");
}
}
The above vulnerability can easily be exploited:
contract Attack {
receive() external payable {}
function attact(GuessTheRandomNumber guessTheRandomNumber) public {
uint answer = uint(keccak256(abi.encodePacked(blockhash(block.number - 1), block.timestamp)));
guessRandomNo.guessNo(answer);
}
function getBalance() public view returns(uint) {
return address(this).balance;
}
}
Since both the transaction will be in the same block, the blocknumber and therefore blockhash will be same, and block.timestamp will also be the same, and therefore, attacker can easily find the random number and extract the ethers out of the contract.
In summary, it is important to be cautious when using blockhash and block.timestamp for generating random numbers in your contracts. Instead, consider using Oracles like chainlink VRF.