Commit b36be32b authored by clabby's avatar clabby

Only allow checkpointing 1 block back in the `BlockOracle`

parent e0c0f867
......@@ -36,8 +36,8 @@ type BlockOracleBlockInfo struct {
// BlockOracleMetaData contains all meta data concerning the BlockOracle contract.
var BlockOracleMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[],\"name\":\"BlockHashNotPresent\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BlockNumberOOB\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockNumber\",\"type\":\"uint256\"}],\"name\":\"load\",\"outputs\":[{\"components\":[{\"internalType\":\"Hash\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"internalType\":\"Timestamp\",\"name\":\"timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structBlockOracle.BlockInfo\",\"name\":\"blockInfo_\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockNumber\",\"type\":\"uint256\"}],\"name\":\"store\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
Bin: "0x608060405234801561001057600080fd5b50610279806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636057361d1461003b57806399d548aa14610050575b600080fd5b61004e6100493660046101d0565b61008c565b005b61006361005e3660046101d0565b610151565b604080518251815260209283015167ffffffffffffffff16928101929092520160405180910390f35b804060008190036100c9576040517fd82756d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006100d58343610218565b6100e090600d61022f565b6100ea9042610218565b60408051808201825293845267ffffffffffffffff918216602080860191825260009687528690529420925183559251600190920180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016929093169190911790915550565b604080518082018252600080825260209182018190528381528082528281208351808501909452805480855260019091015467ffffffffffffffff1692840192909252036101cb576040517f37cf270500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000602082840312156101e257600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561022a5761022a6101e9565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610267576102676101e9565b50029056fea164736f6c634300080f000a",
ABI: "[{\"inputs\":[],\"name\":\"BlockHashNotPresent\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"checkpoint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockNumber\",\"type\":\"uint256\"}],\"name\":\"load\",\"outputs\":[{\"components\":[{\"internalType\":\"Hash\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"internalType\":\"Timestamp\",\"name\":\"timestamp\",\"type\":\"uint64\"}],\"internalType\":\"structBlockOracle.BlockInfo\",\"name\":\"blockInfo_\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
Bin: "0x608060405234801561001057600080fd5b506101fb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806399d548aa1461003b578063c2c4c5c114610078575b600080fd5b61004e610049366004610197565b61008e565b604080518251815260209283015167ffffffffffffffff1692810192909252015b60405180910390f35b61008061010d565b60405190815260200161006f565b604080518082018252600080825260209182018190528381528082528281208351808501909452805480855260019091015467ffffffffffffffff169284019290925203610108576040517f37cf270500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008061011b6001436101b0565b9150508040600061012d600d426101b0565b60408051808201825293845267ffffffffffffffff9182166020808601918252600087815290819052919091209351845551600190930180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001693909116929092179091555090565b6000602082840312156101a957600080fd5b5035919050565b6000828210156101e9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a",
}
// BlockOracleABI is the input ABI used to generate the binding from.
......@@ -238,23 +238,23 @@ func (_BlockOracle *BlockOracleCallerSession) Load(_blockNumber *big.Int) (Block
return _BlockOracle.Contract.Load(&_BlockOracle.CallOpts, _blockNumber)
}
// Store is a paid mutator transaction binding the contract method 0x6057361d.
// Checkpoint is a paid mutator transaction binding the contract method 0xc2c4c5c1.
//
// Solidity: function store(uint256 _blockNumber) returns()
func (_BlockOracle *BlockOracleTransactor) Store(opts *bind.TransactOpts, _blockNumber *big.Int) (*types.Transaction, error) {
return _BlockOracle.contract.Transact(opts, "store", _blockNumber)
// Solidity: function checkpoint() returns(uint256 blockNumber_)
func (_BlockOracle *BlockOracleTransactor) Checkpoint(opts *bind.TransactOpts) (*types.Transaction, error) {
return _BlockOracle.contract.Transact(opts, "checkpoint")
}
// Store is a paid mutator transaction binding the contract method 0x6057361d.
// Checkpoint is a paid mutator transaction binding the contract method 0xc2c4c5c1.
//
// Solidity: function store(uint256 _blockNumber) returns()
func (_BlockOracle *BlockOracleSession) Store(_blockNumber *big.Int) (*types.Transaction, error) {
return _BlockOracle.Contract.Store(&_BlockOracle.TransactOpts, _blockNumber)
// Solidity: function checkpoint() returns(uint256 blockNumber_)
func (_BlockOracle *BlockOracleSession) Checkpoint() (*types.Transaction, error) {
return _BlockOracle.Contract.Checkpoint(&_BlockOracle.TransactOpts)
}
// Store is a paid mutator transaction binding the contract method 0x6057361d.
// Checkpoint is a paid mutator transaction binding the contract method 0xc2c4c5c1.
//
// Solidity: function store(uint256 _blockNumber) returns()
func (_BlockOracle *BlockOracleTransactorSession) Store(_blockNumber *big.Int) (*types.Transaction, error) {
return _BlockOracle.Contract.Store(&_BlockOracle.TransactOpts, _blockNumber)
// Solidity: function checkpoint() returns(uint256 blockNumber_)
func (_BlockOracle *BlockOracleTransactorSession) Checkpoint() (*types.Transaction, error) {
return _BlockOracle.Contract.Checkpoint(&_BlockOracle.TransactOpts)
}
......@@ -9,11 +9,11 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const BlockOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/dispute/BlockOracle.sol:BlockOracle\",\"label\":\"blockHashes\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_uint256,t_struct(BlockInfo)1001_storage)\"}],\"types\":{\"t_mapping(t_uint256,t_struct(BlockInfo)1001_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e struct BlockOracle.BlockInfo)\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_struct(BlockInfo)1001_storage\"},\"t_struct(BlockInfo)1001_storage\":{\"encoding\":\"inplace\",\"label\":\"struct BlockOracle.BlockInfo\",\"numberOfBytes\":\"64\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Hash)1002\":{\"encoding\":\"inplace\",\"label\":\"Hash\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Timestamp)1003\":{\"encoding\":\"inplace\",\"label\":\"Timestamp\",\"numberOfBytes\":\"8\"}}}"
const BlockOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/dispute/BlockOracle.sol:BlockOracle\",\"label\":\"blocks\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_uint256,t_struct(BlockInfo)1001_storage)\"}],\"types\":{\"t_mapping(t_uint256,t_struct(BlockInfo)1001_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e struct BlockOracle.BlockInfo)\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_struct(BlockInfo)1001_storage\"},\"t_struct(BlockInfo)1001_storage\":{\"encoding\":\"inplace\",\"label\":\"struct BlockOracle.BlockInfo\",\"numberOfBytes\":\"64\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Hash)1002\":{\"encoding\":\"inplace\",\"label\":\"Hash\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Timestamp)1003\":{\"encoding\":\"inplace\",\"label\":\"Timestamp\",\"numberOfBytes\":\"8\"}}}"
var BlockOracleStorageLayout = new(solc.StorageLayout)
var BlockOracleDeployedBin = "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80636057361d1461003b57806399d548aa14610050575b600080fd5b61004e6100493660046101d0565b61008c565b005b61006361005e3660046101d0565b610151565b604080518251815260209283015167ffffffffffffffff16928101929092520160405180910390f35b804060008190036100c9576040517fd82756d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006100d58343610218565b6100e090600d61022f565b6100ea9042610218565b60408051808201825293845267ffffffffffffffff918216602080860191825260009687528690529420925183559251600190920180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016929093169190911790915550565b604080518082018252600080825260209182018190528381528082528281208351808501909452805480855260019091015467ffffffffffffffff1692840192909252036101cb576040517f37cf270500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000602082840312156101e257600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561022a5761022a6101e9565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610267576102676101e9565b50029056fea164736f6c634300080f000a"
var BlockOracleDeployedBin = "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806399d548aa1461003b578063c2c4c5c114610078575b600080fd5b61004e610049366004610197565b61008e565b604080518251815260209283015167ffffffffffffffff1692810192909252015b60405180910390f35b61008061010d565b60405190815260200161006f565b604080518082018252600080825260209182018190528381528082528281208351808501909452805480855260019091015467ffffffffffffffff169284019290925203610108576040517f37cf270500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008061011b6001436101b0565b9150508040600061012d600d426101b0565b60408051808201825293845267ffffffffffffffff9182166020808601918252600087815290819052919091209351845551600190930180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001693909116929092179091555090565b6000602082840312156101a957600080fd5b5035919050565b6000828210156101e9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"
func init() {
if err := json.Unmarshal([]byte(BlockOracleStorageLayoutJSON), BlockOracleStorageLayout); err != nil {
......
......@@ -17,7 +17,7 @@ import (
// It configures the alphabet fault game as game type 0 (faultGameType)
// If/when the dispute game factory becomes a predeployed contract this can be removed and just use the
// predeployed version
func deployDisputeGameContracts(require *require.Assertions, ctx context.Context, client *ethclient.Client, opts *bind.TransactOpts, gameDuration uint64) (*bindings.DisputeGameFactory, uint64) {
func deployDisputeGameContracts(require *require.Assertions, ctx context.Context, client *ethclient.Client, opts *bind.TransactOpts, gameDuration uint64) (*bindings.DisputeGameFactory, *big.Int) {
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
defer cancel()
// Deploy the proxy
......@@ -51,14 +51,6 @@ func deployDisputeGameContracts(require *require.Assertions, ctx context.Context
alphaVMAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
// Deploy the block hash oracle
_, tx, _, err = bindings.DeployBlockOracle(opts, client)
require.NoError(err)
blockHashOracleAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
blockHashOracle, err := bindings.NewBlockOracle(blockHashOracleAddr, client)
require.NoError(err)
// Deploy the L2 output oracle
_, tx, _, err = bindings.DeployL2OutputOracle(
opts,
......@@ -77,15 +69,17 @@ func deployDisputeGameContracts(require *require.Assertions, ctx context.Context
l2OutputOracle, err := bindings.NewL2OutputOracle(l2OutputOracleAddr, client)
require.NoError(err)
// Deploy the fault dispute game implementation
_, tx, _, err = bindings.DeployFaultDisputeGame(opts, client, alphabetVMAbsolutePrestateClaim, big.NewInt(alphabetGameDepth), gameDuration, alphaVMAddr, l2OutputOracleAddr, blockHashOracleAddr)
// Deploy the block hash oracle
_, tx, _, err = bindings.DeployBlockOracle(opts, client)
require.NoError(err)
faultDisputeGameAddr, err := bind.WaitDeployed(ctx, client, tx)
blockHashOracleAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
blockHashOracle, err := bindings.NewBlockOracle(blockHashOracleAddr, client)
require.NoError(err)
// Propose 2 outputs
for i := uint8(0); i < 2; i++ {
nextBlockNumber, err := l2OutputOracle.NextBlockNumber(nil)
nextBlockNumber, err := l2OutputOracle.NextBlockNumber(&bind.CallOpts{Pending: true, Context: ctx})
require.NoError(err)
block, err := client.BlockByNumber(ctx, big.NewInt(int64(i)))
require.NoError(err)
......@@ -97,18 +91,36 @@ func deployDisputeGameContracts(require *require.Assertions, ctx context.Context
}
// Store the current block in the oracle
blockNo, err := client.BlockNumber(ctx)
require.NoError(err)
tx, err = blockHashOracle.Store(opts, big.NewInt(int64(blockNo)))
tx, err = blockHashOracle.Checkpoint(opts)
require.NoError(err)
_, err = utils.WaitReceiptOK(ctx, client, tx.Hash())
r, err := utils.WaitReceiptOK(ctx, client, tx.Hash())
require.NoError(err, "failed to store block in blockoracle")
_, tx, _, err = bindings.DeployMIPS(opts, client)
require.NoError(err)
_, err = bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
// Deploy the fault dispute game implementation
_, tx, _, err = bindings.DeployFaultDisputeGame(
opts,
client,
alphabetVMAbsolutePrestateClaim,
big.NewInt(alphabetGameDepth),
gameDuration,
alphaVMAddr,
l2OutputOracleAddr,
blockHashOracleAddr,
)
require.NoError(err)
faultDisputeGameAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
// Set the fault game type implementation
tx, err = factory.SetImplementation(opts, faultGameType, faultDisputeGameAddr)
require.NoError(err)
_, err = utils.WaitReceiptOK(ctx, client, tx.Hash())
require.NoError(err, "wait for final transaction to be included and OK")
return factory, blockNo
return factory, new(big.Int).Sub(r.BlockNumber, big.NewInt(1))
}
......@@ -44,7 +44,7 @@ type FactoryHelper struct {
client *ethclient.Client
opts *bind.TransactOpts
factory *bindings.DisputeGameFactory
l1Head uint64
l1Head *big.Int
}
func NewFactoryHelper(t *testing.T, ctx context.Context, client *ethclient.Client, gameDuration uint64) *FactoryHelper {
......@@ -74,7 +74,7 @@ func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet s
h.require.NoError(err, "get root claim")
extraData := make([]byte, 64)
binary.BigEndian.PutUint64(extraData[24:], uint64(3600))
binary.BigEndian.PutUint64(extraData[56:], h.l1Head)
binary.BigEndian.PutUint64(extraData[56:], h.l1Head.Uint64())
tx, err := h.factory.Create(h.opts, faultGameType, rootClaim, extraData)
h.require.NoError(err, "create fault dispute game")
rcpt, err := utils.WaitReceiptOK(ctx, h.client, tx.Hash())
......
......@@ -16,7 +16,8 @@ AssetReceiverTest:test_withdrawETHwithAmount_unauthorized_reverts() (gas: 10738)
AttestationStationTest:test_attest_bulk_succeeds() (gas: 703740)
AttestationStationTest:test_attest_individual_succeeds() (gas: 632078)
AttestationStationTest:test_attest_single_succeeds() (gas: 651316)
BlockOracle_Test:test_load_noBlockHash_reverts() (gas: 12849)
BlockOracle_Test:test_checkpointAndLoad_succeeds() (gas: 51618)
BlockOracle_Test:test_load_noBlockHash_reverts() (gas: 12805)
Bytes_slice_Test:test_slice_acrossMultipleWords_works() (gas: 9413)
Bytes_slice_Test:test_slice_acrossWords_works() (gas: 1430)
Bytes_slice_Test:test_slice_fromNonZeroIdx_works() (gas: 17240)
......@@ -102,7 +103,7 @@ FaultDisputeGame_Test:test_gameStart_succeeds() (gas: 10410)
FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8266)
FaultDisputeGame_Test:test_initialize_correctData_succeeds() (gas: 58226)
FaultDisputeGame_Test:test_initialize_firstOutput_reverts() (gas: 210532)
FaultDisputeGame_Test:test_initialize_l1HeadTooOld_reverts() (gas: 276399)
FaultDisputeGame_Test:test_initialize_l1HeadTooOld_reverts() (gas: 228360)
FaultDisputeGame_Test:test_move_clockCorrectness_succeeds() (gas: 415921)
FaultDisputeGame_Test:test_move_clockTimeExceeded_reverts() (gas: 26428)
FaultDisputeGame_Test:test_move_defendRoot_reverts() (gas: 13322)
......
......@@ -14,33 +14,31 @@ contract BlockOracle {
}
/// @notice Maps block numbers to block hashes and timestamps
mapping(uint256 => BlockInfo) internal blockHashes;
mapping(uint256 => BlockInfo) internal blocks;
/// @notice Loads a block hash for a given block number, assuming that the block number
/// has been stored in the oracle.
/// @param _blockNumber The block number to load the block hash and timestamp for.
/// @return blockInfo_ The block hash and timestamp for the given block number.
function load(uint256 _blockNumber) external view returns (BlockInfo memory blockInfo_) {
blockInfo_ = blockHashes[_blockNumber];
blockInfo_ = blocks[_blockNumber];
if (Hash.unwrap(blockInfo_.hash) == 0) revert BlockHashNotPresent();
}
/// @notice Stores a block hash for a given block number, assuming that the block number
/// @notice Stores a block hash for the previous block number, assuming that the block number
/// is within the acceptable range of [tip - 256, tip].
/// @param _blockNumber The block number to persist the block hash for.
function store(uint256 _blockNumber) external {
function checkpoint() external returns (uint256 blockNumber_) {
// Fetch the block hash for the given block number and revert if it is out of
// the `BLOCKHASH` opcode's range.
bytes32 blockHash = blockhash(_blockNumber);
if (blockHash == 0) revert BlockNumberOOB();
// SAFETY: This block hash will always be accessible by the `BLOCKHASH` opcode,
// and in the case of `block.number = 0`, we'll underflow.
bytes32 blockHash = blockhash(blockNumber_ = block.number - 1);
// Estimate the timestamp of the block assuming an average block time of 13 seconds.
Timestamp estimatedTimestamp = Timestamp.wrap(
uint64(block.timestamp - ((block.number - _blockNumber) * 13))
);
Timestamp estimatedTimestamp = Timestamp.wrap(uint64(block.timestamp - 13));
// Persist the block information.
blockHashes[_blockNumber] = BlockInfo({
blocks[blockNumber_] = BlockInfo({
hash: Hash.wrap(blockHash),
timestamp: estimatedTimestamp
});
......
......@@ -478,7 +478,9 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
// the game cannot be played.
// TODO(clabby): The block timestamp in the oracle is an estimate that assumes a 13
// second block time. Should we add a buffer here to ensure that the
// estimation has room for error? This invariant cannot break.
// estimation has room for error? This invariant cannot break. We could
// add the L1 block number to the `Types.OutputProposal` type as well,
// which would remove the need for estimation.
if (Timestamp.unwrap(blockInfo.timestamp) < disputed.timestamp) revert L1HeadTooOld();
// Persist the output proposals fetched from the oracle. These outputs will be referenced
......
......@@ -11,36 +11,19 @@ contract BlockOracle_Test is Test {
function setUp() public {
oracle = new BlockOracle();
// Roll the chain forward 255 blocks.
vm.roll(block.number + 255);
// Set the time to a realistic date.
vm.warp(1690906994);
// Roll the chain forward 1 block.
vm.roll(block.number + 1);
vm.warp(block.timestamp + 13);
}
/// @notice Tests that loading a block hash for a block number within the range of the
/// `BLOCKHASH` opcode succeeds.
function testFuzz_store_succeeds(uint256 _blockNumber) public {
_blockNumber = bound(_blockNumber, 0, 255);
oracle.store(_blockNumber);
/// @notice Tests that checkpointing a block and loading its information succeeds.
function test_checkpointAndLoad_succeeds() public {
oracle.checkpoint();
uint256 blockNumber = block.number - 1;
BlockOracle.BlockInfo memory res = oracle.load(blockNumber);
BlockOracle.BlockInfo memory res = oracle.load(_blockNumber);
assertEq(Hash.unwrap(res.hash), blockhash(_blockNumber));
assertEq(Timestamp.unwrap(res.timestamp), block.timestamp - ((block.number - _blockNumber) * 13));
}
/// @notice Tests that loading a block hash for a block number outside the range of the
/// `BLOCKHASH` opcode fails.
function testFuzz_store_oob_reverts(uint256 _blockNumber) public {
// Fast forward another 256 blocks.
vm.roll(block.number + 256);
// Bound the block number to the set { 0, ..., 255 } ∪ { 512, ..., type(uint256).max }
_blockNumber = _blockNumber % 2 == 0
? bound(_blockNumber, 0, 255)
: bound(_blockNumber, 512, type(uint256).max);
// Attempt to load the block hash, which should fail.
vm.expectRevert(BlockNumberOOB.selector);
oracle.store(_blockNumber);
assertEq(Hash.unwrap(res.hash), blockhash(blockNumber));
assertEq(Timestamp.unwrap(res.timestamp), block.timestamp - 13);
}
/// @notice Tests that the `load` function reverts if the block hash for the given block
......
......@@ -53,7 +53,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
// Deploy a new block hash oracle and store the block hash for the genesis block.
BlockOracle blockOracle = new BlockOracle();
blockOracle.store(block.number - 1);
blockOracle.checkpoint();
// Set the extra data for the game creation
extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, block.number - 1);
......@@ -127,8 +127,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// @dev Tests that a game cannot be created by the factory if the L1 head hash does not
/// contain the disputed L2 output root.
function test_initialize_l1HeadTooOld_reverts() public {
gameProxy.BLOCK_ORACLE().store(block.number - 128);
bytes memory _extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, block.number - 128);
// Store a mock block hash for the genesis block. The timestamp will default to 0.
vm.store(address(gameImpl.BLOCK_ORACLE()), keccak256(abi.encode(0, 0)), bytes32(uint256(1)));
bytes memory _extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, 0);
vm.expectRevert(L1HeadTooOld.selector);
factory.create(GAME_TYPE, ROOT_CLAIM, _extraData);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment