forked from paradigmxyz/zk-eth-rng
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBlockhashOpcodeOracle.sol
63 lines (51 loc) · 2.41 KB
/
BlockhashOpcodeOracle.sol
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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
import "./IBlockhashOracle.sol";
/// @title Blockhash Opcode Oracle
/// @author AmanGotchu <[email protected]>
/// @author Sina Sabet <[email protected]>
/// @notice Blockhash opcode based blockhash oracle.
contract BlockhashOpcodeOracle is IBlockhashOracle {
/// @notice Maps validated blockhashes to their block number.
mapping(bytes32 => uint256) public blockhashToBlockNum;
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
error PokeRangeError();
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
/// @notice Validates the block hash of the block before the contract was initialized.
constructor() {
poke();
}
/// @notice Validates the block hash of the block before this tx is called.
/// @return The block number and blockhash being validated.
function poke() public returns (uint256, bytes32) {
uint256 prevBlockNum = block.number - 1;
bytes32 blockhashVal = blockhash(prevBlockNum);
setValidBlockhash(blockhashVal, prevBlockNum);
return (prevBlockNum, blockhashVal);
}
/// @notice Validates the block hash of a specified block number using
/// the blockhash opcode. The blockhash opcode is currently limited to
/// 256 blocks in the past. There have been discussions of EIPs that
/// allow for arbitrary blockhash lookback which makes this blockhash
/// oracle approach far better.
/// @param blockNum Block number to validate.
function pokeBlocknum(uint256 blockNum) public returns (bytes32) {
bytes32 blockhashVal = blockhash(blockNum);
if (blockhashVal == bytes32(0)) {
revert PokeRangeError();
}
setValidBlockhash(blockhashVal, blockNum);
return blockhashVal;
}
/// @notice Validates blockhash and blocknum in storage and emits a validated event.
/// @param blockNum Block number of the blockhash being validated.
/// @param blockHash Blockhash being validated.
function setValidBlockhash(bytes32 blockHash, uint256 blockNum) internal {
blockhashToBlockNum[blockHash] = blockNum;
emit BlockhashValidated(blockNum, blockHash);
}
}