Commit 35757456 authored by Maurelian's avatar Maurelian Committed by GitHub

bedrock: use block number for key in output oracle (#2707)

* bedrock: use block number for key in output oracle

* contracts: Apply seaport style to natspec comments

Inspo: https://github.com/ProjectOpenSea/seaport/blob/main/contracts/Seaport.sol

* bedrock: Improve oracle error messages

* bedrock: update node and proposer with new oracle interface

* bedrock: add tests for oracle reorg protection.

* Fix op-proposer & withdrawals logic

* Golang PR Fixes

* specs: use block number for key in output oracle

* bedrock: Fix CamelCase on oracle events

* bedrock: Update arg name in usage of getL2Output

* bedrock: Oracle add computeL2Timestamp and check on append
Co-authored-by: default avatarJoshua Gutow <jgutow@optimism.io>
parent b81eae57
---
'@eth-optimism/contracts-bedrock': minor
---
Replaces L2 timestamps with block numbers as the key in mapping(uint => OutputProposal).
......@@ -36,8 +36,8 @@ type L2OutputOracleOutputProposal struct {
// L2OutputOracleMetaData contains all meta data concerning the L2OutputOracle contract.
var L2OutputOracleMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputAppended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"l2OutputDeleted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HISTORICAL_TOTAL_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_BLOCK_TIMESTAMP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1Blocknumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2timestamp\",\"type\":\"uint256\"}],\"name\":\"computeL2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structL2OutputOracle.OutputProposal\",\"name\":\"_proposal\",\"type\":\"tuple\"}],\"name\":\"deleteL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structL2OutputOracle.OutputProposal\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
Bin: "0x61010060405234801561001157600080fd5b50604051610f9e380380610f9e83398101604081905261003091610164565b61003933610114565b61004385876101c8565b156100ba5760405162461bcd60e51b815260206004820152603760248201527f5375626d697373696f6e20496e74657276616c206d7573742062652061206d7560448201527f6c7469706c65206f66204c3220426c6f636b2054696d65000000000000000000606482015260840160405180910390fd5b608086905260a0859052604080518082018252858152426020808301918252600086815260029091529290922090518155905160019182015560c084905282905560e082905261010981610114565b5050505050506101ea565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060008060008060c0878903121561017d57600080fd5b86516020880151604089015160608a015160808b015160a08c0151949a50929850909650945092506001600160a01b03811681146101ba57600080fd5b809150509295509295509295565b6000826101e557634e487b7160e01b600052601260045260246000fd5b500690565b60805160a05160c05160e051610d5261024c600039600081816101af0152818161031b01526103f10152600081816102d5015261042201526000818160e801526103d00152600081816101e30152818161062201526109570152610d526000f3fe6080604052600436106100d15760003560e01c806341840fa61161007f5780638da5cb5b116100595780638da5cb5b1461021a578063a25ae5571461024f578063a4771aad146102c3578063f2fde38b146102f757600080fd5b806341840fa61461019d578063529933df146101d1578063715018a61461020557600080fd5b80630c1952d3116100b05780630c1952d31461015f5780632518810414610175578063357e951f1461018857600080fd5b80622134cc146100d657806302e513451461011d578063093b3d901461013d575b600080fd5b3480156100e257600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561012957600080fd5b5061010a610138366004610bba565b610317565b34801561014957600080fd5b5061015d610158366004610bd3565b610449565b005b34801561016b57600080fd5b5061010a60015481565b61015d610183366004610c49565b61064e565b34801561019457600080fd5b5061010a610953565b3480156101a957600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101dd57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561021157600080fd5b5061015d610988565b34801561022657600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610114565b34801561025b57600080fd5b506102a861026a366004610bba565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b60408051825181526020928301519281019290925201610114565b3480156102cf57600080fd5b5061010a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561030357600080fd5b5061015d610312366004610c7b565b610a15565b60007f00000000000000000000000000000000000000000000000000000000000000008210156103ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f54696d657374616d70207072696f7220746f207374617274696e67426c6f636b60448201527f54696d657374616d70000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083038161041f5761041f610cb8565b047f0000000000000000000000000000000000000000000000000000000000000000019050919050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b6001805460009081526002602090815260409182902082518084019093528054808452930154908201528251909114610585576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f43616e206f6e6c792064656c65746520746865206d6f737420726563656e742060448201527f6f75747075742e0000000000000000000000000000000000000000000000000060648201526084016103c5565b80602001518260200151146105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600060248201526044016103c5565b600154602082015182516040517f6897e92e2fea3b89bf0d45ed867487716da71bfa624c6878569d227d736c700990600090a460018054600090815260026020526040812081815582015554610647907f000000000000000000000000000000000000000000000000000000000000000090610d16565b6001555050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b42831061075e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f43616e6e6f7420617070656e64204c32206f757470757420696e20667574757260448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016103c5565b610766610953565b83146107f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f54696d657374616d70206e6f7420657175616c20746f206e657874206578706560448201527f637465642074696d657374616d7000000000000000000000000000000000000060648201526084016103c5565b8361085b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f74207375626d697420656d707479204c32206f757470757400000060448201526064016103c5565b81156108f157818140146108f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f426c6f636b6861736820646f6573206e6f74206d61746368207468652068617360448201527f6820617420746865206578706563746564206865696768742e0000000000000060648201526084016103c5565b60408051808201825285815242602080830182815260008881526002909252848220935184555160019384015591869055915185929187917f54fbf9b58db0b6543a3a0cb9fbd4e98a7c7b88878978fa125b84a2c7f51d34ba9190a450505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001546109839190610d2d565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b610a136000610b45565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103c5565b73ffffffffffffffffffffffffffffffffffffffff8116610b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103c5565b610b4281610b45565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610bcc57600080fd5b5035919050565b600060408284031215610be557600080fd5b6040516040810181811067ffffffffffffffff82111715610c2f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823581526020928301359281019290925250919050565b60008060008060808587031215610c5f57600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215610c8d57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610cb157600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610d2857610d28610ce7565b500390565b60008219821115610d4057610d40610ce7565b50019056fea164736f6c634300080a000a",
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_genesisL2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_historicalTotalBlocks\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sequencer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"L2OutputAppended\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l1Timestamp\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"L2OutputDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HISTORICAL_TOTAL_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_BLOCK_NUMBER\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STARTING_TIMESTAMP\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_l2Output\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1Blockhash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1BlockNumber\",\"type\":\"uint256\"}],\"name\":\"appendL2Output\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"computeL2Timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structL2OutputOracle.OutputProposal\",\"name\":\"_proposal\",\"type\":\"tuple\"}],\"name\":\"deleteL2Output\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"getL2Output\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"internalType\":\"structL2OutputOracle.OutputProposal\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
Bin: "0x61012060405234801561001157600080fd5b5060405161112c38038061112c8339810160408190526100309161016f565b6100393361011f565b4282106100be5760405162461bcd60e51b815260206004820152604360248201527f4f7574707574204f7261636c653a20496e697469616c204c3220626c6f636b2060448201527f74696d65206d757374206265206c657373207468616e2063757272656e742074606482015262696d6560e81b608482015260a40160405180910390fd5b608087905260a085905260c084905260e083905261010082905260408051808201825287815242602080830191825260008881526002909152929092209051815590516001918201558490556101138161011f565b505050505050506101de565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080600080600080600060e0888a03121561018a57600080fd5b8751602089015160408a015160608b015160808c015160a08d015160c08e0151959c50939a509198509650945092506001600160a01b03811681146101ce57600080fd5b8091505092959891949750929550565b60805160a05160c05160e05161010051610ee161024b600039600060f301526000818161015c0152610b370152600081816101b901528181610a080152610b02015260006102df0152600081816101ed015281816105cc01528181610ade0152610b650152610ee16000f3fe6080604052600436106100dc5760003560e01c8063715018a61161007f578063a4771aad11610059578063a4771aad146102cd578063d1de856c14610301578063dcec334814610321578063f2fde38b1461033657600080fd5b8063715018a61461020f5780638da5cb5b14610224578063a25ae5571461025957600080fd5b806325188104116100bb578063251881041461017e5780634599c788146101915780634ab65d73146101a7578063529933df146101db57600080fd5b80622134cc146100e1578063093b3d901461012857806320e9fcd41461014a575b600080fd5b3480156100ed57600080fd5b506101157f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561013457600080fd5b50610148610143366004610d3b565b610356565b005b34801561015657600080fd5b506101157f000000000000000000000000000000000000000000000000000000000000000081565b61014861018c366004610db1565b6105f8565b34801561019d57600080fd5b5061011560015481565b3480156101b357600080fd5b506101157f000000000000000000000000000000000000000000000000000000000000000081565b3480156101e757600080fd5b506101157f000000000000000000000000000000000000000000000000000000000000000081565b34801561021b57600080fd5b50610148610977565b34801561023057600080fd5b5060005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161011f565b34801561026557600080fd5b506102b2610274366004610de3565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b6040805182518152602092830151928101929092520161011f565b3480156102d957600080fd5b506101157f000000000000000000000000000000000000000000000000000000000000000081565b34801561030d57600080fd5b5061011561031c366004610de3565b610a04565b34801561032d57600080fd5b50610115610b61565b34801561034257600080fd5b50610148610351366004610dfc565b610b96565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b60018054600090815260026020908152604091829020825180840190935280548084529301549082015282519091146104bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605260248201527f4f75747075744f7261636c653a20546865206f757470757420726f6f7420746f60448201527f2064656c65746520646f6573206e6f74206d6174636820746865206c6174657360648201527f74206f75747075742070726f706f73616c2e0000000000000000000000000000608482015260a4016103d3565b806020015182602001511461057a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f4f75747075744f7261636c653a205468652074696d657374616d7020746f206460448201527f656c65746520646f6573206e6f74206d6174636820746865206c61746573742060648201527f6f75747075742070726f706f73616c2e00000000000000000000000000000000608482015260a4016103d3565b600154602082015182516040517f7320566fd5256cf8923648a5d9f560f1e92f1435a1bb32ddd1fe107f224ad35990600090a4600180546000908152600260205260408120818155820155546105f1907f000000000000000000000000000000000000000000000000000000000000000090610e68565b6001555050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610679576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103d3565b610681610b61565b8314610735576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604760248201527f4f75747075744f7261636c653a20426c6f636b206e756d626572206d7573742060448201527f626520657175616c20746f206e65787420657870656374656420626c6f636b2060648201527f6e756d6265722e00000000000000000000000000000000000000000000000000608482015260a4016103d3565b4261073f84610a04565b106107cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4f75747075744f7261636c653a2043616e6e6f7420617070656e64204c32206f60448201527f757470757420696e206675747572652e0000000000000000000000000000000060648201526084016103d3565b83610859576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4f75747075744f7261636c653a2043616e6e6f74207375626d697420656d707460448201527f79204c32206f75747075742e000000000000000000000000000000000000000060648201526084016103d3565b81156109155781814014610915576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604760248201527f4f75747075744f7261636c653a20426c6f636b6861736820646f6573206e6f7460448201527f206d61746368207468652068617368206174207468652065787065637465642060648201527f6865696768742e00000000000000000000000000000000000000000000000000608482015260a4016103d3565b60408051808201825285815242602080830182815260008881526002909252848220935184555160019384015591869055915185929187917fd6703ded1701060d9ae1793db76d594790a4e775781225f79b5aa8a77987c0809190a450505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103d3565b610a026000610cc6565b565b60007f0000000000000000000000000000000000000000000000000000000000000000821015610adc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605660248201527f4f75747075744f7261636c653a20426c6f636b206e756d626572206d7573742060448201527f62652067726561746572207468616e206f7220657175616c20746f207468652060648201527f7374617274696e6720626c6f636b206e756d6265722e00000000000000000000608482015260a4016103d3565b7f0000000000000000000000000000000000000000000000000000000000000000610b277f000000000000000000000000000000000000000000000000000000000000000084610e68565b610b319190610e7f565b610b5b907f0000000000000000000000000000000000000000000000000000000000000000610ebc565b92915050565b60007f0000000000000000000000000000000000000000000000000000000000000000600154610b919190610ebc565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103d3565b73ffffffffffffffffffffffffffffffffffffffff8116610cba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103d3565b610cc381610cc6565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060408284031215610d4d57600080fd5b6040516040810181811067ffffffffffffffff82111715610d97577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823581526020928301359281019290925250919050565b60008060008060808587031215610dc757600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215610df557600080fd5b5035919050565b600060208284031215610e0e57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610e3257600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015610e7a57610e7a610e39565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610eb757610eb7610e39565b500290565b60008219821115610ecf57610ecf610e39565b50019056fea164736f6c634300080a000a",
}
// L2OutputOracleABI is the input ABI used to generate the binding from.
......@@ -49,7 +49,7 @@ var L2OutputOracleABI = L2OutputOracleMetaData.ABI
var L2OutputOracleBin = L2OutputOracleMetaData.Bin
// DeployL2OutputOracle deploys a new Ethereum contract, binding an instance of L2OutputOracle to it.
func DeployL2OutputOracle(auth *bind.TransactOpts, backend bind.ContractBackend, _submissionInterval *big.Int, _l2BlockTime *big.Int, _genesisL2Output [32]byte, _historicalTotalBlocks *big.Int, _startingBlockTimestamp *big.Int, _sequencer common.Address) (common.Address, *types.Transaction, *L2OutputOracle, error) {
func DeployL2OutputOracle(auth *bind.TransactOpts, backend bind.ContractBackend, _submissionInterval *big.Int, _genesisL2Output [32]byte, _historicalTotalBlocks *big.Int, _startingBlockNumber *big.Int, _startingTimestamp *big.Int, _l2BlockTime *big.Int, _sequencer common.Address) (common.Address, *types.Transaction, *L2OutputOracle, error) {
parsed, err := L2OutputOracleMetaData.GetAbi()
if err != nil {
return common.Address{}, nil, nil, err
......@@ -58,7 +58,7 @@ func DeployL2OutputOracle(auth *bind.TransactOpts, backend bind.ContractBackend,
return common.Address{}, nil, nil, errors.New("GetABI returned nil")
}
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(L2OutputOracleBin), backend, _submissionInterval, _l2BlockTime, _genesisL2Output, _historicalTotalBlocks, _startingBlockTimestamp, _sequencer)
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(L2OutputOracleBin), backend, _submissionInterval, _genesisL2Output, _historicalTotalBlocks, _startingBlockNumber, _startingTimestamp, _l2BlockTime, _sequencer)
if err != nil {
return common.Address{}, nil, nil, err
}
......@@ -269,12 +269,12 @@ func (_L2OutputOracle *L2OutputOracleCallerSession) L2BLOCKTIME() (*big.Int, err
return _L2OutputOracle.Contract.L2BLOCKTIME(&_L2OutputOracle.CallOpts)
}
// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6.
// STARTINGBLOCKNUMBER is a free data retrieval call binding the contract method 0x4ab65d73.
//
// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCaller) STARTINGBLOCKTIMESTAMP(opts *bind.CallOpts) (*big.Int, error) {
// Solidity: function STARTING_BLOCK_NUMBER() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCaller) STARTINGBLOCKNUMBER(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _L2OutputOracle.contract.Call(opts, &out, "STARTING_BLOCK_TIMESTAMP")
err := _L2OutputOracle.contract.Call(opts, &out, "STARTING_BLOCK_NUMBER")
if err != nil {
return *new(*big.Int), err
......@@ -286,18 +286,49 @@ func (_L2OutputOracle *L2OutputOracleCaller) STARTINGBLOCKTIMESTAMP(opts *bind.C
}
// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6.
// STARTINGBLOCKNUMBER is a free data retrieval call binding the contract method 0x4ab65d73.
//
// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleSession) STARTINGBLOCKTIMESTAMP() (*big.Int, error) {
return _L2OutputOracle.Contract.STARTINGBLOCKTIMESTAMP(&_L2OutputOracle.CallOpts)
// Solidity: function STARTING_BLOCK_NUMBER() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleSession) STARTINGBLOCKNUMBER() (*big.Int, error) {
return _L2OutputOracle.Contract.STARTINGBLOCKNUMBER(&_L2OutputOracle.CallOpts)
}
// STARTINGBLOCKTIMESTAMP is a free data retrieval call binding the contract method 0x41840fa6.
// STARTINGBLOCKNUMBER is a free data retrieval call binding the contract method 0x4ab65d73.
//
// Solidity: function STARTING_BLOCK_TIMESTAMP() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCallerSession) STARTINGBLOCKTIMESTAMP() (*big.Int, error) {
return _L2OutputOracle.Contract.STARTINGBLOCKTIMESTAMP(&_L2OutputOracle.CallOpts)
// Solidity: function STARTING_BLOCK_NUMBER() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCallerSession) STARTINGBLOCKNUMBER() (*big.Int, error) {
return _L2OutputOracle.Contract.STARTINGBLOCKNUMBER(&_L2OutputOracle.CallOpts)
}
// STARTINGTIMESTAMP is a free data retrieval call binding the contract method 0x20e9fcd4.
//
// Solidity: function STARTING_TIMESTAMP() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCaller) STARTINGTIMESTAMP(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _L2OutputOracle.contract.Call(opts, &out, "STARTING_TIMESTAMP")
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// STARTINGTIMESTAMP is a free data retrieval call binding the contract method 0x20e9fcd4.
//
// Solidity: function STARTING_TIMESTAMP() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleSession) STARTINGTIMESTAMP() (*big.Int, error) {
return _L2OutputOracle.Contract.STARTINGTIMESTAMP(&_L2OutputOracle.CallOpts)
}
// STARTINGTIMESTAMP is a free data retrieval call binding the contract method 0x20e9fcd4.
//
// Solidity: function STARTING_TIMESTAMP() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCallerSession) STARTINGTIMESTAMP() (*big.Int, error) {
return _L2OutputOracle.Contract.STARTINGTIMESTAMP(&_L2OutputOracle.CallOpts)
}
// SUBMISSIONINTERVAL is a free data retrieval call binding the contract method 0x529933df.
......@@ -331,12 +362,12 @@ func (_L2OutputOracle *L2OutputOracleCallerSession) SUBMISSIONINTERVAL() (*big.I
return _L2OutputOracle.Contract.SUBMISSIONINTERVAL(&_L2OutputOracle.CallOpts)
}
// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345.
// ComputeL2Timestamp is a free data retrieval call binding the contract method 0xd1de856c.
//
// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.CallOpts, _l2timestamp *big.Int) (*big.Int, error) {
// Solidity: function computeL2Timestamp(uint256 _l2BlockNumber) view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2Timestamp(opts *bind.CallOpts, _l2BlockNumber *big.Int) (*big.Int, error) {
var out []interface{}
err := _L2OutputOracle.contract.Call(opts, &out, "computeL2BlockNumber", _l2timestamp)
err := _L2OutputOracle.contract.Call(opts, &out, "computeL2Timestamp", _l2BlockNumber)
if err != nil {
return *new(*big.Int), err
......@@ -348,26 +379,26 @@ func (_L2OutputOracle *L2OutputOracleCaller) ComputeL2BlockNumber(opts *bind.Cal
}
// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345.
// ComputeL2Timestamp is a free data retrieval call binding the contract method 0xd1de856c.
//
// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256)
func (_L2OutputOracle *L2OutputOracleSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) {
return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp)
// Solidity: function computeL2Timestamp(uint256 _l2BlockNumber) view returns(uint256)
func (_L2OutputOracle *L2OutputOracleSession) ComputeL2Timestamp(_l2BlockNumber *big.Int) (*big.Int, error) {
return _L2OutputOracle.Contract.ComputeL2Timestamp(&_L2OutputOracle.CallOpts, _l2BlockNumber)
}
// ComputeL2BlockNumber is a free data retrieval call binding the contract method 0x02e51345.
// ComputeL2Timestamp is a free data retrieval call binding the contract method 0xd1de856c.
//
// Solidity: function computeL2BlockNumber(uint256 _l2timestamp) view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCallerSession) ComputeL2BlockNumber(_l2timestamp *big.Int) (*big.Int, error) {
return _L2OutputOracle.Contract.ComputeL2BlockNumber(&_L2OutputOracle.CallOpts, _l2timestamp)
// Solidity: function computeL2Timestamp(uint256 _l2BlockNumber) view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCallerSession) ComputeL2Timestamp(_l2BlockNumber *big.Int) (*big.Int, error) {
return _L2OutputOracle.Contract.ComputeL2Timestamp(&_L2OutputOracle.CallOpts, _l2BlockNumber)
}
// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557.
//
// Solidity: function getL2Output(uint256 _l2Timestamp) view returns((bytes32,uint256))
func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l2Timestamp *big.Int) (L2OutputOracleOutputProposal, error) {
// Solidity: function getL2Output(uint256 _l2BlockNumber) view returns((bytes32,uint256))
func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l2BlockNumber *big.Int) (L2OutputOracleOutputProposal, error) {
var out []interface{}
err := _L2OutputOracle.contract.Call(opts, &out, "getL2Output", _l2Timestamp)
err := _L2OutputOracle.contract.Call(opts, &out, "getL2Output", _l2BlockNumber)
if err != nil {
return *new(L2OutputOracleOutputProposal), err
......@@ -381,24 +412,24 @@ func (_L2OutputOracle *L2OutputOracleCaller) GetL2Output(opts *bind.CallOpts, _l
// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557.
//
// Solidity: function getL2Output(uint256 _l2Timestamp) view returns((bytes32,uint256))
func (_L2OutputOracle *L2OutputOracleSession) GetL2Output(_l2Timestamp *big.Int) (L2OutputOracleOutputProposal, error) {
return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp)
// Solidity: function getL2Output(uint256 _l2BlockNumber) view returns((bytes32,uint256))
func (_L2OutputOracle *L2OutputOracleSession) GetL2Output(_l2BlockNumber *big.Int) (L2OutputOracleOutputProposal, error) {
return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2BlockNumber)
}
// GetL2Output is a free data retrieval call binding the contract method 0xa25ae557.
//
// Solidity: function getL2Output(uint256 _l2Timestamp) view returns((bytes32,uint256))
func (_L2OutputOracle *L2OutputOracleCallerSession) GetL2Output(_l2Timestamp *big.Int) (L2OutputOracleOutputProposal, error) {
return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2Timestamp)
// Solidity: function getL2Output(uint256 _l2BlockNumber) view returns((bytes32,uint256))
func (_L2OutputOracle *L2OutputOracleCallerSession) GetL2Output(_l2BlockNumber *big.Int) (L2OutputOracleOutputProposal, error) {
return _L2OutputOracle.Contract.GetL2Output(&_L2OutputOracle.CallOpts, _l2BlockNumber)
}
// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3.
// LatestBlockNumber is a free data retrieval call binding the contract method 0x4599c788.
//
// Solidity: function latestBlockTimestamp() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCaller) LatestBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) {
// Solidity: function latestBlockNumber() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCaller) LatestBlockNumber(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _L2OutputOracle.contract.Call(opts, &out, "latestBlockTimestamp")
err := _L2OutputOracle.contract.Call(opts, &out, "latestBlockNumber")
if err != nil {
return *new(*big.Int), err
......@@ -410,26 +441,26 @@ func (_L2OutputOracle *L2OutputOracleCaller) LatestBlockTimestamp(opts *bind.Cal
}
// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3.
// LatestBlockNumber is a free data retrieval call binding the contract method 0x4599c788.
//
// Solidity: function latestBlockTimestamp() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleSession) LatestBlockTimestamp() (*big.Int, error) {
return _L2OutputOracle.Contract.LatestBlockTimestamp(&_L2OutputOracle.CallOpts)
// Solidity: function latestBlockNumber() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleSession) LatestBlockNumber() (*big.Int, error) {
return _L2OutputOracle.Contract.LatestBlockNumber(&_L2OutputOracle.CallOpts)
}
// LatestBlockTimestamp is a free data retrieval call binding the contract method 0x0c1952d3.
// LatestBlockNumber is a free data retrieval call binding the contract method 0x4599c788.
//
// Solidity: function latestBlockTimestamp() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCallerSession) LatestBlockTimestamp() (*big.Int, error) {
return _L2OutputOracle.Contract.LatestBlockTimestamp(&_L2OutputOracle.CallOpts)
// Solidity: function latestBlockNumber() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCallerSession) LatestBlockNumber() (*big.Int, error) {
return _L2OutputOracle.Contract.LatestBlockNumber(&_L2OutputOracle.CallOpts)
}
// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f.
// NextBlockNumber is a free data retrieval call binding the contract method 0xdcec3348.
//
// Solidity: function nextTimestamp() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCaller) NextTimestamp(opts *bind.CallOpts) (*big.Int, error) {
// Solidity: function nextBlockNumber() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCaller) NextBlockNumber(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _L2OutputOracle.contract.Call(opts, &out, "nextTimestamp")
err := _L2OutputOracle.contract.Call(opts, &out, "nextBlockNumber")
if err != nil {
return *new(*big.Int), err
......@@ -441,18 +472,18 @@ func (_L2OutputOracle *L2OutputOracleCaller) NextTimestamp(opts *bind.CallOpts)
}
// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f.
// NextBlockNumber is a free data retrieval call binding the contract method 0xdcec3348.
//
// Solidity: function nextTimestamp() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleSession) NextTimestamp() (*big.Int, error) {
return _L2OutputOracle.Contract.NextTimestamp(&_L2OutputOracle.CallOpts)
// Solidity: function nextBlockNumber() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleSession) NextBlockNumber() (*big.Int, error) {
return _L2OutputOracle.Contract.NextBlockNumber(&_L2OutputOracle.CallOpts)
}
// NextTimestamp is a free data retrieval call binding the contract method 0x357e951f.
// NextBlockNumber is a free data retrieval call binding the contract method 0xdcec3348.
//
// Solidity: function nextTimestamp() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCallerSession) NextTimestamp() (*big.Int, error) {
return _L2OutputOracle.Contract.NextTimestamp(&_L2OutputOracle.CallOpts)
// Solidity: function nextBlockNumber() view returns(uint256)
func (_L2OutputOracle *L2OutputOracleCallerSession) NextBlockNumber() (*big.Int, error) {
return _L2OutputOracle.Contract.NextBlockNumber(&_L2OutputOracle.CallOpts)
}
// Owner is a free data retrieval call binding the contract method 0x8da5cb5b.
......@@ -488,23 +519,23 @@ func (_L2OutputOracle *L2OutputOracleCallerSession) Owner() (common.Address, err
// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104.
//
// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns()
func (_L2OutputOracle *L2OutputOracleTransactor) AppendL2Output(opts *bind.TransactOpts, _l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) {
return _L2OutputOracle.contract.Transact(opts, "appendL2Output", _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber)
// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2BlockNumber, bytes32 _l1Blockhash, uint256 _l1BlockNumber) payable returns()
func (_L2OutputOracle *L2OutputOracleTransactor) AppendL2Output(opts *bind.TransactOpts, _l2Output [32]byte, _l2BlockNumber *big.Int, _l1Blockhash [32]byte, _l1BlockNumber *big.Int) (*types.Transaction, error) {
return _L2OutputOracle.contract.Transact(opts, "appendL2Output", _l2Output, _l2BlockNumber, _l1Blockhash, _l1BlockNumber)
}
// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104.
//
// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns()
func (_L2OutputOracle *L2OutputOracleSession) AppendL2Output(_l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) {
return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber)
// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2BlockNumber, bytes32 _l1Blockhash, uint256 _l1BlockNumber) payable returns()
func (_L2OutputOracle *L2OutputOracleSession) AppendL2Output(_l2Output [32]byte, _l2BlockNumber *big.Int, _l1Blockhash [32]byte, _l1BlockNumber *big.Int) (*types.Transaction, error) {
return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2BlockNumber, _l1Blockhash, _l1BlockNumber)
}
// AppendL2Output is a paid mutator transaction binding the contract method 0x25188104.
//
// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2timestamp, bytes32 _l1Blockhash, uint256 _l1Blocknumber) payable returns()
func (_L2OutputOracle *L2OutputOracleTransactorSession) AppendL2Output(_l2Output [32]byte, _l2timestamp *big.Int, _l1Blockhash [32]byte, _l1Blocknumber *big.Int) (*types.Transaction, error) {
return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2timestamp, _l1Blockhash, _l1Blocknumber)
// Solidity: function appendL2Output(bytes32 _l2Output, uint256 _l2BlockNumber, bytes32 _l1Blockhash, uint256 _l1BlockNumber) payable returns()
func (_L2OutputOracle *L2OutputOracleTransactorSession) AppendL2Output(_l2Output [32]byte, _l2BlockNumber *big.Int, _l1Blockhash [32]byte, _l1BlockNumber *big.Int) (*types.Transaction, error) {
return _L2OutputOracle.Contract.AppendL2Output(&_L2OutputOracle.TransactOpts, _l2Output, _l2BlockNumber, _l1Blockhash, _l1BlockNumber)
}
// DeleteL2Output is a paid mutator transaction binding the contract method 0x093b3d90.
......@@ -570,9 +601,9 @@ func (_L2OutputOracle *L2OutputOracleTransactorSession) TransferOwnership(newOwn
return _L2OutputOracle.Contract.TransferOwnership(&_L2OutputOracle.TransactOpts, newOwner)
}
// L2OutputOracleOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the L2OutputOracle contract.
type L2OutputOracleOwnershipTransferredIterator struct {
Event *L2OutputOracleOwnershipTransferred // Event containing the contract specifics and raw log
// L2OutputOracleL2OutputAppendedIterator is returned from FilterL2OutputAppended and is used to iterate over the raw logs and unpacked data for L2OutputAppended events raised by the L2OutputOracle contract.
type L2OutputOracleL2OutputAppendedIterator struct {
Event *L2OutputOracleL2OutputAppended // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
......@@ -586,7 +617,7 @@ type L2OutputOracleOwnershipTransferredIterator struct {
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *L2OutputOracleOwnershipTransferredIterator) Next() bool {
func (it *L2OutputOracleL2OutputAppendedIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
......@@ -595,7 +626,7 @@ func (it *L2OutputOracleOwnershipTransferredIterator) Next() bool {
if it.done {
select {
case log := <-it.logs:
it.Event = new(L2OutputOracleOwnershipTransferred)
it.Event = new(L2OutputOracleL2OutputAppended)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
......@@ -610,7 +641,7 @@ func (it *L2OutputOracleOwnershipTransferredIterator) Next() bool {
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(L2OutputOracleOwnershipTransferred)
it.Event = new(L2OutputOracleL2OutputAppended)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
......@@ -626,60 +657,69 @@ func (it *L2OutputOracleOwnershipTransferredIterator) Next() bool {
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *L2OutputOracleOwnershipTransferredIterator) Error() error {
func (it *L2OutputOracleL2OutputAppendedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *L2OutputOracleOwnershipTransferredIterator) Close() error {
func (it *L2OutputOracleL2OutputAppendedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// L2OutputOracleOwnershipTransferred represents a OwnershipTransferred event raised by the L2OutputOracle contract.
type L2OutputOracleOwnershipTransferred struct {
PreviousOwner common.Address
NewOwner common.Address
// L2OutputOracleL2OutputAppended represents a L2OutputAppended event raised by the L2OutputOracle contract.
type L2OutputOracleL2OutputAppended struct {
L2Output [32]byte
L1Timestamp *big.Int
L2BlockNumber *big.Int
Raw types.Log // Blockchain specific contextual infos
}
// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
// FilterL2OutputAppended is a free log retrieval operation binding the contract event 0xd6703ded1701060d9ae1793db76d594790a4e775781225f79b5aa8a77987c080.
//
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_L2OutputOracle *L2OutputOracleFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*L2OutputOracleOwnershipTransferredIterator, error) {
// Solidity: event L2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2BlockNumber)
func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputAppended(opts *bind.FilterOpts, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2BlockNumber []*big.Int) (*L2OutputOracleL2OutputAppendedIterator, error) {
var previousOwnerRule []interface{}
for _, previousOwnerItem := range previousOwner {
previousOwnerRule = append(previousOwnerRule, previousOwnerItem)
var _l2OutputRule []interface{}
for _, _l2OutputItem := range _l2Output {
_l2OutputRule = append(_l2OutputRule, _l2OutputItem)
}
var newOwnerRule []interface{}
for _, newOwnerItem := range newOwner {
newOwnerRule = append(newOwnerRule, newOwnerItem)
var _l1TimestampRule []interface{}
for _, _l1TimestampItem := range _l1Timestamp {
_l1TimestampRule = append(_l1TimestampRule, _l1TimestampItem)
}
var _l2BlockNumberRule []interface{}
for _, _l2BlockNumberItem := range _l2BlockNumber {
_l2BlockNumberRule = append(_l2BlockNumberRule, _l2BlockNumberItem)
}
logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule)
logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "L2OutputAppended", _l2OutputRule, _l1TimestampRule, _l2BlockNumberRule)
if err != nil {
return nil, err
}
return &L2OutputOracleOwnershipTransferredIterator{contract: _L2OutputOracle.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil
return &L2OutputOracleL2OutputAppendedIterator{contract: _L2OutputOracle.contract, event: "L2OutputAppended", logs: logs, sub: sub}, nil
}
// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
// WatchL2OutputAppended is a free log subscription operation binding the contract event 0xd6703ded1701060d9ae1793db76d594790a4e775781225f79b5aa8a77987c080.
//
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_L2OutputOracle *L2OutputOracleFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *L2OutputOracleOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) {
// Solidity: event L2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2BlockNumber)
func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputAppended(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputAppended, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2BlockNumber []*big.Int) (event.Subscription, error) {
var previousOwnerRule []interface{}
for _, previousOwnerItem := range previousOwner {
previousOwnerRule = append(previousOwnerRule, previousOwnerItem)
var _l2OutputRule []interface{}
for _, _l2OutputItem := range _l2Output {
_l2OutputRule = append(_l2OutputRule, _l2OutputItem)
}
var newOwnerRule []interface{}
for _, newOwnerItem := range newOwner {
newOwnerRule = append(newOwnerRule, newOwnerItem)
var _l1TimestampRule []interface{}
for _, _l1TimestampItem := range _l1Timestamp {
_l1TimestampRule = append(_l1TimestampRule, _l1TimestampItem)
}
var _l2BlockNumberRule []interface{}
for _, _l2BlockNumberItem := range _l2BlockNumber {
_l2BlockNumberRule = append(_l2BlockNumberRule, _l2BlockNumberItem)
}
logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule)
logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "L2OutputAppended", _l2OutputRule, _l1TimestampRule, _l2BlockNumberRule)
if err != nil {
return nil, err
}
......@@ -689,8 +729,8 @@ func (_L2OutputOracle *L2OutputOracleFilterer) WatchOwnershipTransferred(opts *b
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(L2OutputOracleOwnershipTransferred)
if err := _L2OutputOracle.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil {
event := new(L2OutputOracleL2OutputAppended)
if err := _L2OutputOracle.contract.UnpackLog(event, "L2OutputAppended", log); err != nil {
return err
}
event.Raw = log
......@@ -711,21 +751,21 @@ func (_L2OutputOracle *L2OutputOracleFilterer) WatchOwnershipTransferred(opts *b
}), nil
}
// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
// ParseL2OutputAppended is a log parse operation binding the contract event 0xd6703ded1701060d9ae1793db76d594790a4e775781225f79b5aa8a77987c080.
//
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_L2OutputOracle *L2OutputOracleFilterer) ParseOwnershipTransferred(log types.Log) (*L2OutputOracleOwnershipTransferred, error) {
event := new(L2OutputOracleOwnershipTransferred)
if err := _L2OutputOracle.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil {
// Solidity: event L2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2BlockNumber)
func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputAppended(log types.Log) (*L2OutputOracleL2OutputAppended, error) {
event := new(L2OutputOracleL2OutputAppended)
if err := _L2OutputOracle.contract.UnpackLog(event, "L2OutputAppended", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// L2OutputOracleL2OutputAppendedIterator is returned from FilterL2OutputAppended and is used to iterate over the raw logs and unpacked data for L2OutputAppended events raised by the L2OutputOracle contract.
type L2OutputOracleL2OutputAppendedIterator struct {
Event *L2OutputOracleL2OutputAppended // Event containing the contract specifics and raw log
// L2OutputOracleL2OutputDeletedIterator is returned from FilterL2OutputDeleted and is used to iterate over the raw logs and unpacked data for L2OutputDeleted events raised by the L2OutputOracle contract.
type L2OutputOracleL2OutputDeletedIterator struct {
Event *L2OutputOracleL2OutputDeleted // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
......@@ -739,7 +779,7 @@ type L2OutputOracleL2OutputAppendedIterator struct {
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *L2OutputOracleL2OutputAppendedIterator) Next() bool {
func (it *L2OutputOracleL2OutputDeletedIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
......@@ -748,7 +788,7 @@ func (it *L2OutputOracleL2OutputAppendedIterator) Next() bool {
if it.done {
select {
case log := <-it.logs:
it.Event = new(L2OutputOracleL2OutputAppended)
it.Event = new(L2OutputOracleL2OutputDeleted)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
......@@ -763,7 +803,7 @@ func (it *L2OutputOracleL2OutputAppendedIterator) Next() bool {
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(L2OutputOracleL2OutputAppended)
it.Event = new(L2OutputOracleL2OutputDeleted)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
......@@ -779,29 +819,29 @@ func (it *L2OutputOracleL2OutputAppendedIterator) Next() bool {
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *L2OutputOracleL2OutputAppendedIterator) Error() error {
func (it *L2OutputOracleL2OutputDeletedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *L2OutputOracleL2OutputAppendedIterator) Close() error {
func (it *L2OutputOracleL2OutputDeletedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// L2OutputOracleL2OutputAppended represents a L2OutputAppended event raised by the L2OutputOracle contract.
type L2OutputOracleL2OutputAppended struct {
L2Output [32]byte
L1Timestamp *big.Int
L2timestamp *big.Int
Raw types.Log // Blockchain specific contextual infos
// L2OutputOracleL2OutputDeleted represents a L2OutputDeleted event raised by the L2OutputOracle contract.
type L2OutputOracleL2OutputDeleted struct {
L2Output [32]byte
L1Timestamp *big.Int
L2BlockNumber *big.Int
Raw types.Log // Blockchain specific contextual infos
}
// FilterL2OutputAppended is a free log retrieval operation binding the contract event 0x54fbf9b58db0b6543a3a0cb9fbd4e98a7c7b88878978fa125b84a2c7f51d34ba.
// FilterL2OutputDeleted is a free log retrieval operation binding the contract event 0x7320566fd5256cf8923648a5d9f560f1e92f1435a1bb32ddd1fe107f224ad359.
//
// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp)
func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputAppended(opts *bind.FilterOpts, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputAppendedIterator, error) {
// Solidity: event L2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2BlockNumber)
func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputDeleted(opts *bind.FilterOpts, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2BlockNumber []*big.Int) (*L2OutputOracleL2OutputDeletedIterator, error) {
var _l2OutputRule []interface{}
for _, _l2OutputItem := range _l2Output {
......@@ -811,22 +851,22 @@ func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputAppended(opts *bind
for _, _l1TimestampItem := range _l1Timestamp {
_l1TimestampRule = append(_l1TimestampRule, _l1TimestampItem)
}
var _l2timestampRule []interface{}
for _, _l2timestampItem := range _l2timestamp {
_l2timestampRule = append(_l2timestampRule, _l2timestampItem)
var _l2BlockNumberRule []interface{}
for _, _l2BlockNumberItem := range _l2BlockNumber {
_l2BlockNumberRule = append(_l2BlockNumberRule, _l2BlockNumberItem)
}
logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputAppended", _l2OutputRule, _l1TimestampRule, _l2timestampRule)
logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "L2OutputDeleted", _l2OutputRule, _l1TimestampRule, _l2BlockNumberRule)
if err != nil {
return nil, err
}
return &L2OutputOracleL2OutputAppendedIterator{contract: _L2OutputOracle.contract, event: "l2OutputAppended", logs: logs, sub: sub}, nil
return &L2OutputOracleL2OutputDeletedIterator{contract: _L2OutputOracle.contract, event: "L2OutputDeleted", logs: logs, sub: sub}, nil
}
// WatchL2OutputAppended is a free log subscription operation binding the contract event 0x54fbf9b58db0b6543a3a0cb9fbd4e98a7c7b88878978fa125b84a2c7f51d34ba.
// WatchL2OutputDeleted is a free log subscription operation binding the contract event 0x7320566fd5256cf8923648a5d9f560f1e92f1435a1bb32ddd1fe107f224ad359.
//
// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp)
func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputAppended(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputAppended, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2timestamp []*big.Int) (event.Subscription, error) {
// Solidity: event L2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2BlockNumber)
func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputDeleted(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputDeleted, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2BlockNumber []*big.Int) (event.Subscription, error) {
var _l2OutputRule []interface{}
for _, _l2OutputItem := range _l2Output {
......@@ -836,12 +876,12 @@ func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputAppended(opts *bind.
for _, _l1TimestampItem := range _l1Timestamp {
_l1TimestampRule = append(_l1TimestampRule, _l1TimestampItem)
}
var _l2timestampRule []interface{}
for _, _l2timestampItem := range _l2timestamp {
_l2timestampRule = append(_l2timestampRule, _l2timestampItem)
var _l2BlockNumberRule []interface{}
for _, _l2BlockNumberItem := range _l2BlockNumber {
_l2BlockNumberRule = append(_l2BlockNumberRule, _l2BlockNumberItem)
}
logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputAppended", _l2OutputRule, _l1TimestampRule, _l2timestampRule)
logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "L2OutputDeleted", _l2OutputRule, _l1TimestampRule, _l2BlockNumberRule)
if err != nil {
return nil, err
}
......@@ -851,8 +891,8 @@ func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputAppended(opts *bind.
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(L2OutputOracleL2OutputAppended)
if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputAppended", log); err != nil {
event := new(L2OutputOracleL2OutputDeleted)
if err := _L2OutputOracle.contract.UnpackLog(event, "L2OutputDeleted", log); err != nil {
return err
}
event.Raw = log
......@@ -873,21 +913,21 @@ func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputAppended(opts *bind.
}), nil
}
// ParseL2OutputAppended is a log parse operation binding the contract event 0x54fbf9b58db0b6543a3a0cb9fbd4e98a7c7b88878978fa125b84a2c7f51d34ba.
// ParseL2OutputDeleted is a log parse operation binding the contract event 0x7320566fd5256cf8923648a5d9f560f1e92f1435a1bb32ddd1fe107f224ad359.
//
// Solidity: event l2OutputAppended(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp)
func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputAppended(log types.Log) (*L2OutputOracleL2OutputAppended, error) {
event := new(L2OutputOracleL2OutputAppended)
if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputAppended", log); err != nil {
// Solidity: event L2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2BlockNumber)
func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputDeleted(log types.Log) (*L2OutputOracleL2OutputDeleted, error) {
event := new(L2OutputOracleL2OutputDeleted)
if err := _L2OutputOracle.contract.UnpackLog(event, "L2OutputDeleted", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// L2OutputOracleL2OutputDeletedIterator is returned from FilterL2OutputDeleted and is used to iterate over the raw logs and unpacked data for L2OutputDeleted events raised by the L2OutputOracle contract.
type L2OutputOracleL2OutputDeletedIterator struct {
Event *L2OutputOracleL2OutputDeleted // Event containing the contract specifics and raw log
// L2OutputOracleOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the L2OutputOracle contract.
type L2OutputOracleOwnershipTransferredIterator struct {
Event *L2OutputOracleOwnershipTransferred // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
......@@ -901,7 +941,7 @@ type L2OutputOracleL2OutputDeletedIterator struct {
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *L2OutputOracleL2OutputDeletedIterator) Next() bool {
func (it *L2OutputOracleOwnershipTransferredIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
......@@ -910,7 +950,7 @@ func (it *L2OutputOracleL2OutputDeletedIterator) Next() bool {
if it.done {
select {
case log := <-it.logs:
it.Event = new(L2OutputOracleL2OutputDeleted)
it.Event = new(L2OutputOracleOwnershipTransferred)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
......@@ -925,7 +965,7 @@ func (it *L2OutputOracleL2OutputDeletedIterator) Next() bool {
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(L2OutputOracleL2OutputDeleted)
it.Event = new(L2OutputOracleOwnershipTransferred)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
......@@ -941,69 +981,60 @@ func (it *L2OutputOracleL2OutputDeletedIterator) Next() bool {
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *L2OutputOracleL2OutputDeletedIterator) Error() error {
func (it *L2OutputOracleOwnershipTransferredIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *L2OutputOracleL2OutputDeletedIterator) Close() error {
func (it *L2OutputOracleOwnershipTransferredIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// L2OutputOracleL2OutputDeleted represents a L2OutputDeleted event raised by the L2OutputOracle contract.
type L2OutputOracleL2OutputDeleted struct {
L2Output [32]byte
L1Timestamp *big.Int
L2timestamp *big.Int
Raw types.Log // Blockchain specific contextual infos
// L2OutputOracleOwnershipTransferred represents a OwnershipTransferred event raised by the L2OutputOracle contract.
type L2OutputOracleOwnershipTransferred struct {
PreviousOwner common.Address
NewOwner common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterL2OutputDeleted is a free log retrieval operation binding the contract event 0x6897e92e2fea3b89bf0d45ed867487716da71bfa624c6878569d227d736c7009.
// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
//
// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp)
func (_L2OutputOracle *L2OutputOracleFilterer) FilterL2OutputDeleted(opts *bind.FilterOpts, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2timestamp []*big.Int) (*L2OutputOracleL2OutputDeletedIterator, error) {
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_L2OutputOracle *L2OutputOracleFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*L2OutputOracleOwnershipTransferredIterator, error) {
var _l2OutputRule []interface{}
for _, _l2OutputItem := range _l2Output {
_l2OutputRule = append(_l2OutputRule, _l2OutputItem)
}
var _l1TimestampRule []interface{}
for _, _l1TimestampItem := range _l1Timestamp {
_l1TimestampRule = append(_l1TimestampRule, _l1TimestampItem)
var previousOwnerRule []interface{}
for _, previousOwnerItem := range previousOwner {
previousOwnerRule = append(previousOwnerRule, previousOwnerItem)
}
var _l2timestampRule []interface{}
for _, _l2timestampItem := range _l2timestamp {
_l2timestampRule = append(_l2timestampRule, _l2timestampItem)
var newOwnerRule []interface{}
for _, newOwnerItem := range newOwner {
newOwnerRule = append(newOwnerRule, newOwnerItem)
}
logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "l2OutputDeleted", _l2OutputRule, _l1TimestampRule, _l2timestampRule)
logs, sub, err := _L2OutputOracle.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule)
if err != nil {
return nil, err
}
return &L2OutputOracleL2OutputDeletedIterator{contract: _L2OutputOracle.contract, event: "l2OutputDeleted", logs: logs, sub: sub}, nil
return &L2OutputOracleOwnershipTransferredIterator{contract: _L2OutputOracle.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil
}
// WatchL2OutputDeleted is a free log subscription operation binding the contract event 0x6897e92e2fea3b89bf0d45ed867487716da71bfa624c6878569d227d736c7009.
// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
//
// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp)
func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputDeleted(opts *bind.WatchOpts, sink chan<- *L2OutputOracleL2OutputDeleted, _l2Output [][32]byte, _l1Timestamp []*big.Int, _l2timestamp []*big.Int) (event.Subscription, error) {
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_L2OutputOracle *L2OutputOracleFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *L2OutputOracleOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) {
var _l2OutputRule []interface{}
for _, _l2OutputItem := range _l2Output {
_l2OutputRule = append(_l2OutputRule, _l2OutputItem)
}
var _l1TimestampRule []interface{}
for _, _l1TimestampItem := range _l1Timestamp {
_l1TimestampRule = append(_l1TimestampRule, _l1TimestampItem)
var previousOwnerRule []interface{}
for _, previousOwnerItem := range previousOwner {
previousOwnerRule = append(previousOwnerRule, previousOwnerItem)
}
var _l2timestampRule []interface{}
for _, _l2timestampItem := range _l2timestamp {
_l2timestampRule = append(_l2timestampRule, _l2timestampItem)
var newOwnerRule []interface{}
for _, newOwnerItem := range newOwner {
newOwnerRule = append(newOwnerRule, newOwnerItem)
}
logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "l2OutputDeleted", _l2OutputRule, _l1TimestampRule, _l2timestampRule)
logs, sub, err := _L2OutputOracle.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule)
if err != nil {
return nil, err
}
......@@ -1013,8 +1044,8 @@ func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputDeleted(opts *bind.W
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(L2OutputOracleL2OutputDeleted)
if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputDeleted", log); err != nil {
event := new(L2OutputOracleOwnershipTransferred)
if err := _L2OutputOracle.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil {
return err
}
event.Raw = log
......@@ -1035,12 +1066,12 @@ func (_L2OutputOracle *L2OutputOracleFilterer) WatchL2OutputDeleted(opts *bind.W
}), nil
}
// ParseL2OutputDeleted is a log parse operation binding the contract event 0x6897e92e2fea3b89bf0d45ed867487716da71bfa624c6878569d227d736c7009.
// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
//
// Solidity: event l2OutputDeleted(bytes32 indexed _l2Output, uint256 indexed _l1Timestamp, uint256 indexed _l2timestamp)
func (_L2OutputOracle *L2OutputOracleFilterer) ParseL2OutputDeleted(log types.Log) (*L2OutputOracleL2OutputDeleted, error) {
event := new(L2OutputOracleL2OutputDeleted)
if err := _L2OutputOracle.contract.UnpackLog(event, "l2OutputDeleted", log); err != nil {
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_L2OutputOracle *L2OutputOracleFilterer) ParseOwnershipTransferred(log types.Log) (*L2OutputOracleOwnershipTransferred, error) {
event := new(L2OutputOracleOwnershipTransferred)
if err := _L2OutputOracle.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil {
return nil, err
}
event.Raw = log
......
......@@ -38,7 +38,7 @@ type WithdrawalVerifierOutputRootProof struct {
// OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract.
var OptimismPortalMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASE_FEE_MAX_CHANGE_DENOMINATOR\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ELASTICITY_MULTIPLIER\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INITIAL_BASE_FEE\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINIMUM_BASE_FEE\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TARGET_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_l2Timestamp\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]",
ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mint\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isCreation\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASE_FEE_MAX_CHANGE_DENOMINATOR\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ELASTICITY_MULTIPLIER\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INITIAL_BASE_FEE\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINIMUM_BASE_FEE\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TARGET_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawerStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structWithdrawalVerifier.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_withdrawalProof\",\"type\":\"bytes\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]",
Bin: "0x60c0604052600180546001600160a01b03191661dead1790553480156200002557600080fd5b50604051620035c6380380620035c6833981016040819052620000489162000096565b60408051606081018252633b9aca00808252600060208301819052436001600160401b031692909301829052600160c01b9091021790556001600160a01b0390911660a052608052620000d2565b60008060408385031215620000aa57600080fd5b82516001600160a01b0381168114620000c257600080fd5b6020939093015192949293505050565b60805160a0516134c0620001066000396000818161011301526109ac0152600081816103580152610a2f01526134c06000f3fe6080604052600436106100d55760003560e01c8063a14238e71161007f578063cff0ab9611610059578063cff0ab961461027f578063e9e05c4214610320578063eecf1c3614610333578063f4daa2911461034657600080fd5b8063a14238e714610215578063ca3e99ba14610255578063cd7c97891461026a57600080fd5b80636bb0291e116100b05780636bb0291e146101bd578063867ead13146101d25780639bf62d82146101e857600080fd5b80621c2ff61461010157806313620abd1461015f57806364b792081461019857600080fd5b366100fc576100fa3334620186a060006040518060200160405280600081525061037a565b005b600080fd5b34801561010d57600080fd5b506101357f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561016b57600080fd5b50610177633b9aca0081565b6040516fffffffffffffffffffffffffffffffff9091168152602001610156565b3480156101a457600080fd5b506101af627a120081565b604051908152602001610156565b3480156101c957600080fd5b506101af600481565b3480156101de57600080fd5b506101af61271081565b3480156101f457600080fd5b506001546101359073ffffffffffffffffffffffffffffffffffffffff1681565b34801561022157600080fd5b50610245610230366004612bb8565b60026020526000908152604090205460ff1681565b6040519015158152602001610156565b34801561026157600080fd5b506101af61081a565b34801561027657600080fd5b506101af600881565b34801561028b57600080fd5b506000546102e7906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff9283166020850152911690820152606001610156565b6100fa61032e366004612c78565b61037a565b6100fa610341366004612dc2565b61082b565b34801561035257600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156104315773ffffffffffffffffffffffffffffffffffffffff87161561043157604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b33328114610452575033731111000000000000000000000000000000001111015b8773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f78231ae6eb73366f912bb1d64351601fb76344c537bbab635ce14d0f376f0195348a8a8a8a6040516104b7959493929190612f2d565b60405180910390a350600080546104f4907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643612f93565b9050801561067c57600061050c6004627a1200612fd9565b6000546105379190700100000000000000000000000000000000900467ffffffffffffffff16613041565b90506000600861054b6004627a1200612fd9565b60005461056b9085906fffffffffffffffffffffffffffffffff166130b5565b6105759190612fd9565b61057f9190612fd9565b60008054919250906105ca906105b4906105ac9085906fffffffffffffffffffffffffffffffff16613171565b612710610f22565b6fffffffffffffffffffffffffffffffff610f3d565b9050600184111561063d5761063a6105b4670de0b6b3a76400006106266105f2600883612fd9565b61060490670de0b6b3a7640000613041565b61060f60018a612f93565b61062190670de0b6b3a76400006131e5565b610f4c565b61063090856130b5565b6105ac9190612fd9565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760005550505b600080548491906010906106af908490700100000000000000000000000000000000900467ffffffffffffffff16613222565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a12006000800160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561078a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603c60248201527f4f7074696d69736d506f7274616c3a2063616e6e6f7420627579206d6f72652060448201527f676173207468616e20617661696c61626c6520676173206c696d6974000000006064820152608401610428565b600080546107b4906fffffffffffffffffffffffffffffffff1667ffffffffffffffff861661324e565b6fffffffffffffffffffffffffffffffff16905060006107d848633b9aca00610f7d565b6107e29083613286565b905060005a6107f19086612f93565b90508082111561080d5761080d6108088284612f93565b610f8d565b5050505050505050505050565b6108286004627a1200612fd9565b81565b60015473ffffffffffffffffffffffffffffffffffffffff1661dead146108d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610428565b73ffffffffffffffffffffffffffffffffffffffff891630141561097a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610428565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2b919061329a565b90507f00000000000000000000000000000000000000000000000000000000000000008160200151610a5d91906132e9565b4211610aeb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4f7074696d69736d506f7274616c3a2070726f706f73616c206973206e6f742060448201527f7965742066696e616c697a6564000000000000000000000000000000000000006064820152608401610428565b610b02610afd36869003860186613301565b610fbb565b815114610b91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610428565b6000610bd78d8d8d8d8d8d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061101792505050565b9050610c1e81866040013586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061105692505050565b610caa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610428565b60008181526002602052604090205460ff1615610d49576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610428565b600081815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610d8c614e208a6132e9565b5a1015610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c0000000000000000006064820152608401610428565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8e16179055604080516020601f8a01819004810282018101909252888152600091610ea4918e918d918f918691908f908f908190840183828082843760009201919091525061111f92505050565b50600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610f0a90841515815260200190565b60405180910390a25050505050505050505050505050565b600081831215610f325781610f34565b825b90505b92915050565b6000818312610f325781610f34565b6000610f34670de0b6b3a764000083610f64866111aa565b610f6e91906130b5565b610f789190612fd9565b6113ee565b600081831015610f325781610f34565b6000805a90505b825a610fa09083612f93565b1015610fb657610faf82613367565b9150610f94565b505050565b60008160000151826020015183604001518460600151604051602001610ffa949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b6000868686868686604051602001611034969594939291906133a0565b6040516020818303038152906040528051906020012090509695505050505050565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506111149101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290858761162d565b9150505b9392505050565b6000606060008060008661ffff1667ffffffffffffffff81111561114557611145612bfa565b6040519080825280601f01601f19166020018201604052801561116f576020820181803683370190505b5090506000808751602089018b8e8ef191503d925086831115611190578692505b828152826000602083013e90999098509650505050505050565b6000808213611215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610428565b6000606061122284611651565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361141f57506000919050565b680755bf798b4a1bf1e58212611491576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610428565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b60008061163986611727565b905061164781868686611759565b9695505050505050565b60008082116116bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610428565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b6060818051906020012060405160200161174391815260200190565b6040516020818303038152906040529050919050565b6000806000611769878686611796565b9150915081801561178b57508051602080830191909120875191880191909120145b979650505050505050565b6000606060006117a58561188b565b905060008060006117b7848a89611986565b815192955090935091501580806117cb5750815b611831576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610428565b60008161184d5760405180602001604052806000815250611879565b6118798661185c600188612f93565b8151811061186c5761186c6133f7565b6020026020010151611ea3565b919b919a509098505050505050505050565b6060600061189883611ecd565b90506000815167ffffffffffffffff8111156118b6576118b6612bfa565b6040519080825280602002602001820160405280156118fb57816020015b60408051808201909152606080825260208201528152602001906001900390816118d45790505b50905060005b825181101561197e57600061192e848381518110611921576119216133f7565b6020026020010151611f00565b9050604051806040016040528082815260200161194a83611ecd565b81525083838151811061195f5761195f6133f7565b602002602001018190525050808061197690613367565b915050611901565b509392505050565b6000606081808061199687611faa565b905060008690506000806119bd604051806040016040528060608152602001606081525090565b60005b8c51811015611e5f578c81815181106119db576119db6133f7565b6020026020010151915082846119f191906132e9565b93506119fe6001886132e9565b965083611a7c57815180516020909101208514611a77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f496e76616c696420726f6f7420686173680000000000000000000000000000006044820152606401610428565b611b6d565b815151602011611af857815180516020909101208514611a77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610428565b84611b06836000015161212d565b14611b6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610428565b611b79601060016132e9565b8260200151511415611bf2578551841415611b9357611e5f565b6000868581518110611ba757611ba76133f7565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110611bd257611bd26133f7565b60200260200101519050611be581612155565b9650600194505050611e4d565b60028260200151511415611deb576000611c0b8361218b565b9050600081600081518110611c2257611c226133f7565b016020015160f81c90506000611c39600283613426565b611c44906002613448565b90506000611c55848360ff166121af565b90506000611c638b8a6121af565b90506000611c7183836121e5565b905060ff851660021480611c88575060ff85166003145b15611cde57808351148015611c9d5750808251145b15611caf57611cac818b6132e9565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950611e5f945050505050565b60ff85161580611cf1575060ff85166001145b15611d635782518114611d2d57507f80000000000000000000000000000000000000000000000000000000000000009950611e5f945050505050565b611d548860200151600181518110611d4757611d476133f7565b6020026020010151612155565b9a509750611e4d945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f70726566697800000000000000000000000000000000000000000000000000006064820152608401610428565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610428565b80611e5781613367565b9150506119c0565b507f8000000000000000000000000000000000000000000000000000000000000000841486611e8e87866121af565b909e909d50909b509950505050505050505050565b60208101518051606091610f3791611ebd90600190612f93565b81518110611921576119216133f7565b604080518082018252600080825260209182015281518083019092528251825280830190820152606090610f3790612291565b60606000806000611f10856124c4565b919450925090506000816001811115611f2b57611f2b61346b565b14611f92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610428565b611fa1856020015184846128cb565b95945050505050565b6060600082516002611fbc91906131e5565b67ffffffffffffffff811115611fd457611fd4612bfa565b6040519080825280601f01601f191660200182016040528015611ffe576020820181803683370190505b50905060005b8351811015612126576004848281518110612021576120216133f7565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c826120568360026131e5565b81518110612066576120666133f7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106120a9576120a96133f7565b01602001516120bb919060f81c613426565b60f81b826120ca8360026131e5565b6120d59060016132e9565b815181106120e5576120e56133f7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061211e81613367565b915050612004565b5092915050565b600060208251101561214157506020015190565b81806020019051810190610f37919061349a565b600060606020836000015110156121765761216f836129aa565b9050612182565b61217f83611f00565b90505b6111188161212d565b6060610f376121aa8360200151600081518110611921576119216133f7565b611faa565b6060825182106121ce5750604080516020810190915260008152610f37565b610f3483838486516121e09190612f93565b6129b5565b6000805b8084511180156121f95750808351115b801561227a5750828181518110612212576122126133f7565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848281518110612251576122516133f7565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15610f34578061228981613367565b9150506121e9565b606060008061229f846124c4565b919350909150600190508160018111156122bb576122bb61346b565b14612322576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610428565b6040805160208082526104208201909252600091816020015b604080518082019091526000808252602082015281526020019060019003908161233b5790505090506000835b86518110156124b95760208210612401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610428565b60008061243e6040518060400160405280858c600001516124229190612f93565b8152602001858c6020015161243791906132e9565b90526124c4565b50915091506040518060400160405280838361245a91906132e9565b8152602001848b6020015161246f91906132e9565b815250858581518110612484576124846133f7565b602090810291909101015261249a6001856132e9565b93506124a681836132e9565b6124b090846132e9565b92505050612368565b508152949350505050565b600080600080846000015111612536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610428565b6020840151805160001a607f811161255b5760006001600094509450945050506128c4565b60b781116125f1576000612570608083612f93565b9050808760000151116125df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610428565b600195509350600092506128c4915050565b60bf811161271457600061260660b783612f93565b905080876000015111612675576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610428565b600183015160208290036101000a900461268f81836132e9565b8851116126f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610428565b6127038260016132e9565b96509450600093506128c492505050565b60f781116127a957600061272960c083612f93565b905080876000015111612798576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610428565b6001955093508492506128c4915050565b60006127b660f783612f93565b905080876000015111612825576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610428565b600183015160208290036101000a900461283f81836132e9565b8851116128a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610428565b6128b38260016132e9565b96509450600193506128c492505050565b9193909250565b606060008267ffffffffffffffff8111156128e8576128e8612bfa565b6040519080825280601f01601f191660200182016040528015612912576020820181803683370190505b509050805160001415612926579050611118565b600061293285876132e9565b90506020820160005b612946602087613286565b81101561297d578251825261295c6020846132e9565b92506129696020836132e9565b91508061297581613367565b91505061293b565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b6060610f3782612ba2565b6060816129c381601f6132e9565b1015612a2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610428565b82612a3683826132e9565b1015612a9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610428565b612aa882846132e9565b84511015612b12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610428565b606082158015612b315760405191506000825260208201604052612b99565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612b6a578051835260209283019201612b52565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6060610f378260200151600084600001516128cb565b600060208284031215612bca57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612bf557600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612c7057612c70612bfa565b604052919050565b600080600080600060a08688031215612c9057600080fd5b612c9986612bd1565b94506020808701359450604087013567ffffffffffffffff8082168214612cbf57600080fd5b9094506060880135908115158214612cd657600080fd5b90935060808801359080821115612cec57600080fd5b818901915089601f830112612d0057600080fd5b813581811115612d1257612d12612bfa565b612d42847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612c29565b91508082528a84828501011115612d5857600080fd5b80848401858401376000848284010152508093505050509295509295909350565b60008083601f840112612d8b57600080fd5b50813567ffffffffffffffff811115612da357600080fd5b602083019150836020828501011115612dbb57600080fd5b9250929050565b60008060008060008060008060008060006101808c8e031215612de457600080fd5b8b359a50612df460208d01612bd1565b9950612e0260408d01612bd1565b985060608c0135975060808c0135965067ffffffffffffffff60a08d01351115612e2b57600080fd5b612e3b8d60a08e01358e01612d79565b909650945060c08c0135935060808c8e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20011215612e7957600080fd5b60e08c01925067ffffffffffffffff6101608d01351115612e9957600080fd5b612eaa8d6101608e01358e01612d79565b81935080925050509295989b509295989b9093969950565b6000815180845260005b81811015612ee857602081850181015186830182015201612ecc565b81811115612efa576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b85815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061178b60a0830184612ec2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612fa557612fa5612f64565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612fe857612fe8612faa565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561303c5761303c612f64565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561307b5761307b612f64565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156130af576130af612f64565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156130f6576130f6612f64565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561313157613131612f64565b6000871292508782058712848416161561314d5761314d612f64565b8785058712818416161561316357613163612f64565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156131ab576131ab612f64565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156131df576131df612f64565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561321d5761321d612f64565b500290565b600067ffffffffffffffff80831681851680830382111561324557613245612f64565b01949350505050565b60006fffffffffffffffffffffffffffffffff8083168185168183048111821515161561327d5761327d612f64565b02949350505050565b60008261329557613295612faa565b500490565b6000604082840312156132ac57600080fd5b6040516040810181811067ffffffffffffffff821117156132cf576132cf612bfa565b604052825181526020928301519281019290925250919050565b600082198211156132fc576132fc612f64565b500190565b60006080828403121561331357600080fd5b6040516080810181811067ffffffffffffffff8211171561333657613336612bfa565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561339957613399612f64565b5060010190565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526133eb60c0830184612ec2565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061343957613439612faa565b8060ff84160691505092915050565b600060ff821660ff84168082101561346257613462612f64565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000602082840312156134ac57600080fd5b505191905056fea164736f6c634300080a000a",
}
......@@ -592,23 +592,23 @@ func (_OptimismPortal *OptimismPortalTransactorSession) DepositTransaction(_to c
// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36.
//
// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _l2Timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) payable returns()
func (_OptimismPortal *OptimismPortalTransactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _l2Timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) {
return _OptimismPortal.contract.Transact(opts, "finalizeWithdrawalTransaction", _nonce, _sender, _target, _value, _gasLimit, _data, _l2Timestamp, _outputRootProof, _withdrawalProof)
// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _l2BlockNumber, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) payable returns()
func (_OptimismPortal *OptimismPortalTransactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _l2BlockNumber *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) {
return _OptimismPortal.contract.Transact(opts, "finalizeWithdrawalTransaction", _nonce, _sender, _target, _value, _gasLimit, _data, _l2BlockNumber, _outputRootProof, _withdrawalProof)
}
// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36.
//
// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _l2Timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) payable returns()
func (_OptimismPortal *OptimismPortalSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _l2Timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) {
return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _l2Timestamp, _outputRootProof, _withdrawalProof)
// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _l2BlockNumber, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) payable returns()
func (_OptimismPortal *OptimismPortalSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _l2BlockNumber *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) {
return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _l2BlockNumber, _outputRootProof, _withdrawalProof)
}
// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0xeecf1c36.
//
// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _l2Timestamp, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) payable returns()
func (_OptimismPortal *OptimismPortalTransactorSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _l2Timestamp *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) {
return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _l2Timestamp, _outputRootProof, _withdrawalProof)
// Solidity: function finalizeWithdrawalTransaction(uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes _data, uint256 _l2BlockNumber, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes _withdrawalProof) payable returns()
func (_OptimismPortal *OptimismPortalTransactorSession) FinalizeWithdrawalTransaction(_nonce *big.Int, _sender common.Address, _target common.Address, _value *big.Int, _gasLimit *big.Int, _data []byte, _l2BlockNumber *big.Int, _outputRootProof WithdrawalVerifierOutputRootProof, _withdrawalProof []byte) (*types.Transaction, error) {
return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _nonce, _sender, _target, _value, _gasLimit, _data, _l2BlockNumber, _outputRootProof, _withdrawalProof)
}
// Receive is a paid mutator transaction binding the contract receive function.
......
......@@ -52,10 +52,11 @@ func deriveAccount(w accounts.Wallet, path string) accounts.Account {
type L2OOContractConfig struct {
SubmissionFrequency *big.Int
L2StartTime *big.Int
L2BlockTime *big.Int
L2StartingBlock *big.Int
GenesisL2Output [32]byte
HistoricalTotalBlocks *big.Int
L2StartingTimeStamp *big.Int
L2BlockTime *big.Int
}
type DepositContractConfig struct {
......@@ -82,9 +83,11 @@ type SystemConfig struct {
JWTFilePath string
JWTSecret [32]byte
Nodes map[string]*rollupNode.Config // Per node config. Don't use populate rollup.Config
Loggers map[string]log.Logger
RollupConfig rollup.Config // Shared rollup configs
Nodes map[string]*rollupNode.Config // Per node config. Don't use populate rollup.Config
Loggers map[string]log.Logger
ProposerLogger log.Logger
BatcherLogger log.Logger
RollupConfig rollup.Config // Shared rollup configs
L1BlockTime uint64
......@@ -392,7 +395,9 @@ func (cfg SystemConfig) start() (*System, error) {
sys.cfg.RollupConfig.Genesis = sys.RolupGenesis
sys.cfg.RollupConfig.BatchSenderAddress = batchSubmitterAddr
sys.cfg.RollupConfig.P2PSequencerAddress = p2pSignerAddr
sys.cfg.L2OOCfg.L2StartTime = new(big.Int).SetUint64(l2GenesisTime)
sys.cfg.L2OOCfg.L2StartingBlock = new(big.Int).SetUint64(l2GenesisID.Number)
sys.cfg.L2OOCfg.L2StartingTimeStamp = new(big.Int).SetUint64(l2Genesis.Timestamp)
sys.cfg.L2OOCfg.L2BlockTime = new(big.Int).SetUint64(2)
// Deploy Deposit Contract
deployerPrivKey, err := sys.wallet.PrivateKey(accounts.Account{
......@@ -414,10 +419,11 @@ func (cfg SystemConfig) start() (*System, error) {
opts,
l1Client,
sys.cfg.L2OOCfg.SubmissionFrequency,
sys.cfg.L2OOCfg.L2BlockTime,
sys.cfg.L2OOCfg.GenesisL2Output,
sys.cfg.L2OOCfg.HistoricalTotalBlocks,
sys.cfg.L2OOCfg.L2StartTime,
sys.cfg.L2OOCfg.L2StartingBlock,
sys.cfg.L2OOCfg.L2StartingTimeStamp,
sys.cfg.L2OOCfg.L2BlockTime,
l2OutputSubmitterAddr,
)
sys.cfg.DepositCFG.L2Oracle = sys.L2OOContractAddr
......@@ -554,7 +560,7 @@ func (cfg SystemConfig) start() (*System, error) {
LogTerminal: true,
Mnemonic: sys.cfg.Mnemonic,
L2OutputHDPath: sys.cfg.L2OutputHDPath,
}, "", log.New())
}, "", cfg.ProposerLogger)
if err != nil {
return nil, fmt.Errorf("unable to setup l2 output submitter: %w", err)
}
......@@ -590,7 +596,7 @@ func (cfg SystemConfig) start() (*System, error) {
SequencerHistoryDBFilename: sys.sequencerHistoryDBFileName,
SequencerGenesisHash: sys.RolupGenesis.L2.Hash.String(),
SequencerBatchInboxAddress: sys.cfg.RollupConfig.BatchInboxAddress.String(),
}, "", log.New())
}, "", cfg.BatcherLogger)
if err != nil {
return nil, fmt.Errorf("failed to setup batch submitter: %w", err)
}
......
......@@ -88,7 +88,6 @@ func defaultSystemConfig(t *testing.T) SystemConfig {
L2OOCfg: L2OOContractConfig{
// L2 Start time is set based off of the L2 Genesis time
SubmissionFrequency: big.NewInt(2),
L2BlockTime: big.NewInt(1),
HistoricalTotalBlocks: big.NewInt(0),
},
L2OutputHDPath: l2OutputHDPath,
......@@ -117,6 +116,8 @@ func defaultSystemConfig(t *testing.T) SystemConfig {
"verifier": testlog.Logger(t, log.LvlError).New("role", "verifier"),
"sequencer": testlog.Logger(t, log.LvlError).New("role", "sequencer"),
},
ProposerLogger: testlog.Logger(t, log.LvlCrit).New("role", "proposer"), // Proposer is noisy on shutdown
BatcherLogger: testlog.Logger(t, log.LvlCrit).New("role", "batcher"), // Batcher (txmgr really) is noisy on shutdown
RollupConfig: rollup.Config{
BlockTime: 1,
MaxSequencerDrift: 10,
......@@ -153,11 +154,11 @@ func TestL2OutputSubmitter(t *testing.T) {
require.Nil(t, err)
rollupClient := rollupclient.NewRollupClient(rollupRPCClient)
// StateRootOracle is already deployed
// OutputOracle is already deployed
l2OutputOracle, err := bindings.NewL2OutputOracleCaller(sys.L2OOContractAddr, l1Client)
require.Nil(t, err)
initialSroTimestamp, err := l2OutputOracle.LatestBlockTimestamp(&bind.CallOpts{})
initialOutputBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{})
require.Nil(t, err)
// Wait until the second output submission from L2. The output submitter submits outputs from the
......@@ -174,20 +175,15 @@ func TestL2OutputSubmitter(t *testing.T) {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
l2ooTimestamp, err := l2OutputOracle.LatestBlockTimestamp(&bind.CallOpts{})
l2ooBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{})
require.Nil(t, err)
// Wait for the L2 output oracle to have been changed from the initial
// timestamp set in the contract constructor.
if l2ooTimestamp.Cmp(initialSroTimestamp) > 0 {
if l2ooBlockNumber.Cmp(initialOutputBlockNumber) > 0 {
// Retrieve the l2 output committed at this updated timestamp.
committedL2Output, err := l2OutputOracle.GetL2Output(&bind.CallOpts{}, l2ooTimestamp)
require.Nil(t, err)
// Compute the committed L2 output's L2 block number.
l2ooBlockNumber, err := l2OutputOracle.ComputeL2BlockNumber(
&bind.CallOpts{}, l2ooTimestamp,
)
committedL2Output, err := l2OutputOracle.GetL2Output(&bind.CallOpts{}, l2ooBlockNumber)
require.NotEqual(t, [32]byte{}, committedL2Output.OutputRoot, "Empty L2 Output")
require.Nil(t, err)
// Fetch the corresponding L2 block and assert the committed L2
......@@ -765,19 +761,19 @@ func TestWithdrawals(t *testing.T) {
tx, err = l2withdrawer.InitiateWithdrawal(l2opts, fromAddr, big.NewInt(21000), nil)
require.Nil(t, err, "sending initiate withdraw tx")
receipt, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 5*time.Duration(cfg.L1BlockTime)*time.Second)
require.Nil(t, err, "withdrawal initiated on L2 sequencer")
require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed")
// Verify L2 balance after withdrawal
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
header, err := l2Seq.HeaderByNumber(ctx, receipt.BlockNumber)
header, err := l2Verif.HeaderByNumber(ctx, receipt.BlockNumber)
require.Nil(t, err)
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
endBalance, err = l2Seq.BalanceAt(ctx, fromAddr, nil)
endBalance, err = l2Verif.BalanceAt(ctx, fromAddr, nil)
require.Nil(t, err)
// Take fee into account
......@@ -793,25 +789,17 @@ func TestWithdrawals(t *testing.T) {
require.Nil(t, err)
// Wait for finalization and then create the Finalized Withdrawal Transaction
l2OutputOracle, err := bindings.NewL2OutputOracleCaller(sys.L2OOContractAddr, l1Client)
require.Nil(t, err)
ctx, cancel = context.WithTimeout(context.Background(), 10*time.Duration(cfg.L1BlockTime)*time.Second)
defer cancel()
timestamp, err := withdrawals.WaitForFinalizationPeriod(ctx, l1Client, sys.DepositContractAddr, header.Time)
require.Nil(t, err)
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
blockNumber, err := l2OutputOracle.ComputeL2BlockNumber(&bind.CallOpts{Context: ctx}, new(big.Int).SetUint64(timestamp))
blockNumber, err := withdrawals.WaitForFinalizationPeriod(ctx, l1Client, sys.DepositContractAddr, receipt.BlockNumber)
require.Nil(t, err)
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
header, err = l2Seq.HeaderByNumber(ctx, blockNumber)
header, err = l2Verif.HeaderByNumber(ctx, new(big.Int).SetUint64(blockNumber))
require.Nil(t, err)
rpc, err := rpc.Dial(sys.nodes["sequencer"].WSEndpoint())
rpc, err := rpc.Dial(sys.nodes["verifier"].WSEndpoint())
require.Nil(t, err)
l2client := withdrawals.NewClient(rpc)
......@@ -831,7 +819,7 @@ func TestWithdrawals(t *testing.T) {
params.Value,
params.GasLimit,
params.Data,
params.Timestamp,
params.BlockNumber,
params.OutputRootProof,
params.WithdrawalProof,
)
......
......@@ -20,13 +20,13 @@ import (
"github.com/ethereum/go-ethereum/rpc"
)
// WaitForFinalizationPeriod waits until the timestamp has been submitted to the L2 Output Oracle on L1 and
// then waits for the finalization period to be up.
// WaitForFinalizationPeriod waits until there is OutputProof for an L2 block number larger than the supplied l2BlockNumber
// and that the output is finalized.
// This functions polls and can block for a very long time if used on mainnet.
// This returns the timestamp to use for the proof generation.
func WaitForFinalizationPeriod(ctx context.Context, client *ethclient.Client, portalAddr common.Address, timestamp uint64) (uint64, error) {
// This returns the block number to use for the proof generation.
func WaitForFinalizationPeriod(ctx context.Context, client *ethclient.Client, portalAddr common.Address, l2BlockNumber *big.Int) (uint64, error) {
l2BlockNumber = new(big.Int).Set(l2BlockNumber) // Don't clobber caller owned l2BlockNumber
opts := &bind.CallOpts{Context: ctx}
timestampBig := new(big.Int).SetUint64(timestamp)
portal, err := bindings.NewOptimismPortalCaller(portalAddr, client)
if err != nil {
......@@ -40,21 +40,32 @@ func WaitForFinalizationPeriod(ctx context.Context, client *ethclient.Client, po
if err != nil {
return 0, err
}
submissionInterval, err := l2OO.SUBMISSIONINTERVAL(opts)
if err != nil {
return 0, err
}
// Convert blockNumber to submission interval boundary
rem := new(big.Int)
l2BlockNumber, rem = l2BlockNumber.DivMod(l2BlockNumber, submissionInterval, rem)
if rem.Cmp(common.Big0) != 0 {
l2BlockNumber = l2BlockNumber.Add(l2BlockNumber, common.Big1)
}
l2BlockNumber = l2BlockNumber.Mul(l2BlockNumber, submissionInterval)
finalizationPeriod, err := portal.FINALIZATIONPERIODSECONDS(opts)
if err != nil {
return 0, err
}
next, err := l2OO.LatestBlockTimestamp(opts)
latest, err := l2OO.LatestBlockNumber(opts)
if err != nil {
return 0, err
}
// Now poll
// Now poll for the output to be submitted on chain
var ticker *time.Ticker
diff := new(big.Int).Sub(timestampBig, next)
if diff.Cmp(big.NewInt(60)) > 0 {
diff := new(big.Int).Sub(l2BlockNumber, latest)
if diff.Cmp(big.NewInt(10)) > 0 {
ticker = time.NewTicker(time.Minute)
} else {
ticker = time.NewTicker(time.Second)
......@@ -64,12 +75,12 @@ loop:
for {
select {
case <-ticker.C:
next, err = l2OO.LatestBlockTimestamp(opts)
latest, err = l2OO.LatestBlockNumber(opts)
if err != nil {
return 0, err
}
// Already passed next
if next.Cmp(timestampBig) > 0 {
// Already passed the submitted block (likely just equals rather than >= here).
if latest.Cmp(l2BlockNumber) >= 0 {
break loop
}
case <-ctx.Done():
......@@ -78,10 +89,13 @@ loop:
}
// Now wait for it to be finalized
output, err := l2OO.GetL2Output(opts, next)
output, err := l2OO.GetL2Output(opts, l2BlockNumber)
if err != nil {
return 0, err
}
if output.OutputRoot == [32]byte{} {
return 0, errors.New("empty output root. likely no proposal at timestamp")
}
targetTimestamp := new(big.Int).Add(output.Timestamp, finalizationPeriod)
targetTime := time.Unix(targetTimestamp.Int64(), 0)
// Assume clock is relatively correct
......@@ -96,7 +110,7 @@ loop:
return 0, err
}
if header.Time > targetTimestamp.Uint64() {
return next.Uint64(), nil
return l2BlockNumber.Uint64(), nil
}
case <-ctx.Done():
return 0, ctx.Err()
......@@ -131,21 +145,21 @@ func NewClient(client *rpc.Client) *Client {
}
// FinalizedWithdrawalParameters is the set of paramets to pass to the FinalizedWithdrawal function
// FinalizedWithdrawalParameters is the set of parameters to pass to the FinalizedWithdrawal function
type FinalizedWithdrawalParameters struct {
Nonce *big.Int
Sender common.Address
Target common.Address
Value *big.Int
GasLimit *big.Int
Timestamp *big.Int
BlockNumber *big.Int
Data []byte
OutputRootProof bindings.WithdrawalVerifierOutputRootProof
WithdrawalProof []byte // RLP Encoded list of trie nodes to prove L2 storage
}
// FinalizeWithdrawalParameters queries L2 to generate all withdrawal parameters and proof necessary to finalize an withdrawal on L1.
// The header provided is very imporant. It should be a block (timestamp) for which there is a submitted output in the L2 Output Oracle
// The header provided is very important. It should be a block (timestamp) for which there is a submitted output in the L2 Output Oracle
// contract. If not, the withdrawal will fail as it the storage proof cannot be verified if there is no submitted state root.
func FinalizeWithdrawalParameters(ctx context.Context, l2client ProofClient, txHash common.Hash, header *types.Header) (FinalizedWithdrawalParameters, error) {
// Transaction receipt
......@@ -189,13 +203,13 @@ func FinalizeWithdrawalParameters(ctx context.Context, l2client ProofClient, txH
}
return FinalizedWithdrawalParameters{
Nonce: ev.Nonce,
Sender: ev.Sender,
Target: ev.Target,
Value: ev.Value,
GasLimit: ev.GasLimit,
Timestamp: new(big.Int).SetUint64(header.Time),
Data: ev.Data,
Nonce: ev.Nonce,
Sender: ev.Sender,
Target: ev.Target,
Value: ev.Value,
GasLimit: ev.GasLimit,
BlockNumber: new(big.Int).Set(header.Number),
Data: ev.Data,
OutputRootProof: bindings.WithdrawalVerifierOutputRootProof{
Version: [32]byte{}, // Empty for version 1
StateRoot: header.Root,
......
......@@ -95,58 +95,41 @@ func (d *Driver) GetBlockRange(
Context: ctx,
}
// Determine the next uncommitted L2 block number. We do so by transforming
// the timestamp of the latest committed L2 block into its block number and
// adding one.
l2ooTimestamp, err := d.l2ooContract.LatestBlockTimestamp(callOpts)
// Determine the last committed L2 Block Number
start, err := d.l2ooContract.LatestBlockNumber(callOpts)
if err != nil {
d.l.Error(name+" unable to get latest block timestamp", "err", err)
return nil, nil, err
}
start, err := d.l2ooContract.ComputeL2BlockNumber(callOpts, l2ooTimestamp)
if err != nil {
d.l.Error(name+" unable to compute latest l2 block number", "err", err)
d.l.Error(name+" unable to get latest block number", "err", err)
return nil, nil, err
}
start.Add(start, bigOne)
// Next we need to obtain the current timestamp and the next timestamp at
// which we will need to submit an L2 output. The former is done by simply
// adding the submission interval to the latest committed block's timestamp;
// the latter inspects the timestamp of the latest block.
nextTimestamp, err := d.l2ooContract.NextTimestamp(callOpts)
// Next determine the L2 block that we need to commit
nextBlockNumber, err := d.l2ooContract.NextBlockNumber(callOpts)
if err != nil {
d.l.Error(name+" unable to get next block timestamp", "err", err)
d.l.Error(name+" unable to get next block number", "err", err)
return nil, nil, err
}
latestHeader, err := d.cfg.L1Client.HeaderByNumber(ctx, nil)
latestHeader, err := d.cfg.L2Client.HeaderByNumber(ctx, nil)
if err != nil {
d.l.Error(name+" unable to retrieve latest header", "err", err)
return nil, nil, err
}
currentTimestamp := big.NewInt(int64(latestHeader.Time))
currentBlockNumber := big.NewInt(latestHeader.Number.Int64())
// If the submission window has yet to elapsed, we must wait before
// submitting our L2 output commitment. Return start as the end value which
// will signal that there is no work to be done.
if currentTimestamp.Cmp(nextTimestamp) < 0 {
// If we do not have the new L2 Block number
if currentBlockNumber.Cmp(nextBlockNumber) < 0 {
d.l.Info(name+" submission interval has not elapsed",
"currentTimestamp", currentTimestamp, "nextTimestamp", nextTimestamp)
"currentBlockNumber", currentBlockNumber, "nextBlockNumber", nextBlockNumber)
return start, start, nil
}
d.l.Info(name+" submission interval has elapsed",
"currentTimestamp", currentTimestamp, "nextTimestamp", nextTimestamp)
"currentBlockNumber", currentBlockNumber, "nextBlockNumber", nextBlockNumber)
// Otherwise the submission interval has elapsed. Transform the next
// expected timestamp into its L2 block number, and add one since end is
// exclusive.
end, err := d.l2ooContract.ComputeL2BlockNumber(callOpts, nextTimestamp)
if err != nil {
d.l.Error(name+" unable to compute next l2 block number", "err", err)
return nil, nil, err
}
end.Add(end, bigOne)
end := new(big.Int).Add(nextBlockNumber, bigOne)
return start, end, nil
}
......@@ -174,35 +157,11 @@ func (d *Driver) CraftTx(
return nil, err
}
// Fetch the next expected timestamp that we will submit along with the
// L2Output.
callOpts := &bind.CallOpts{
Pending: false,
Context: ctx,
}
timestamp, err := d.l2ooContract.NextTimestamp(callOpts)
if err != nil {
return nil, err
}
// Sanity check that we are submitting against the same expected timestamp.
expCheckpointBlock, err := d.l2ooContract.ComputeL2BlockNumber(
callOpts, timestamp,
)
if err != nil {
return nil, err
}
if nextCheckpointBlock.Cmp(expCheckpointBlock) != 0 {
return nil, fmt.Errorf("expected next checkpoint block to be %d, "+
"found %d", nextCheckpointBlock.Uint64(),
expCheckpointBlock.Uint64())
}
numElements := new(big.Int).Sub(start, end).Uint64()
d.l.Info(name+" checkpoint constructed", "start", start, "end", end,
"nonce", nonce, "blocks_committed", numElements, "checkpoint_block", nextCheckpointBlock)
header, err := d.cfg.L1Client.HeaderByNumber(ctx, nil)
l1Header, err := d.cfg.L1Client.HeaderByNumber(ctx, nil)
if err != nil {
return nil, fmt.Errorf("error resolving checkpoint block: %v", err)
}
......@@ -212,8 +171,8 @@ func (d *Driver) CraftTx(
return nil, fmt.Errorf("error resolving checkpoint block: %v", err)
}
if l2Header.Time != timestamp.Uint64() {
return nil, fmt.Errorf("invalid timestamp: next timestamp is %v, timestamp of block is %v", timestamp, l2Header.Time)
if l2Header.Number.Cmp(nextCheckpointBlock) != 0 {
return nil, fmt.Errorf("invalid blockNumber: next blockNumber is %v, blockNumber of block is %v", nextCheckpointBlock, l2Header.Number)
}
opts, err := bind.NewKeyedTransactorWithChainID(
......@@ -226,7 +185,7 @@ func (d *Driver) CraftTx(
opts.Nonce = nonce
opts.NoSend = true
return d.l2ooContract.AppendL2Output(opts, l2OutputRoot, timestamp, header.Hash(), header.Number)
return d.l2ooContract.AppendL2Output(opts, l2OutputRoot, nextCheckpointBlock, l1Header.Hash(), l1Header.Number)
}
// UpdateGasPrice signs an otherwise identical txn to the one provided but with
......
......@@ -38,7 +38,7 @@ L1StandardBridge_Test:test_depositERC20To() (gas: 454650)
L1StandardBridge_Test:test_depositETH() (gas: 247054)
L1StandardBridge_Test:test_depositETHTo() (gas: 204938)
L1StandardBridge_Test:test_donateETH() (gas: 17545)
L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 438817)
L1StandardBridge_Test:test_finalizeERC20Withdrawal() (gas: 438824)
L1StandardBridge_Test:test_finalizeETHWithdrawal() (gas: 48005)
L1StandardBridge_Test:test_initialize() (gas: 14885)
L1StandardBridge_Test:test_onlyEOADepositERC20() (gas: 12085)
......@@ -56,21 +56,21 @@ L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 119659)
L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 133096)
L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10588)
L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54859)
L2OutputOracleTest:testCannot_appendCurrentTimestamp() (gas: 18627)
L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 16756)
L2OutputOracleTest:testCannot_appendFutureTimestamp() (gas: 18708)
L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 16458)
L2OutputOracleTest:testCannot_appendUnexpectedTimestamp() (gas: 18893)
L2OutputOracleTest:testCannot_computePreHistoricalL2BlockNumber() (gas: 11093)
L2OutputOracleTest:testCannot_deleteL2Output_ifNotSequencer() (gas: 18793)
L2OutputOracleTest:testCannot_deleteWrongL2Output() (gas: 77352)
L2OutputOracleTest:test_appendingAnotherOutput() (gas: 68582)
L2OutputOracleTest:test_computeL2BlockNumber() (gas: 14755)
L2OutputOracleTest:test_constructor() (gas: 33752)
L2OutputOracleTest:test_deleteL2Output() (gas: 64338)
L2OutputOracleTest:test_getL2Output() (gas: 74601)
L2OutputOracleTest:test_latestBlockTimestamp() (gas: 68377)
L2OutputOracleTest:test_nextTimestamp() (gas: 9236)
L2OutputOracleTest:testCannot_appendEmptyOutput() (gas: 18442)
L2OutputOracleTest:testCannot_appendFutureTimetamp() (gas: 20072)
L2OutputOracleTest:testCannot_appendOnWrongFork() (gas: 20710)
L2OutputOracleTest:testCannot_appendOutputIfNotSequencer() (gas: 17829)
L2OutputOracleTest:testCannot_appendUnexpectedBlockNumber() (gas: 20313)
L2OutputOracleTest:testCannot_deleteL2Output_ifNotSequencer() (gas: 18805)
L2OutputOracleTest:testCannot_deleteWrongL2Output() (gas: 79498)
L2OutputOracleTest:test_appendWithBlockhashAndHeight() (gas: 69365)
L2OutputOracleTest:test_appendingAnotherOutput() (gas: 70714)
L2OutputOracleTest:test_computeL2Timestamp() (gas: 19230)
L2OutputOracleTest:test_constructor() (gas: 33908)
L2OutputOracleTest:test_deleteL2Output() (gas: 66081)
L2OutputOracleTest:test_getL2Output() (gas: 76274)
L2OutputOracleTest:test_latestBlockNumber() (gas: 70075)
L2OutputOracleTest:test_nextBlockNumber() (gas: 9279)
L2StandardBridge_Test:test_cannotWithdrawEthWithoutSendingIt() (gas: 21578)
L2StandardBridge_Test:test_finalizeDeposit() (gas: 93165)
L2StandardBridge_Test:test_finalizeDeposit_failsToCompleteOutboundTransfer() (gas: 140106)
......@@ -108,7 +108,7 @@ OptimismMintableTokenFactory_Test:test_initializeShouldRevert() (gas: 12696)
OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 11413)
OptimismPortal_Test:test_OptimismPortalContractCreationReverts() (gas: 9214)
OptimismPortal_Test:test_OptimismPortalReceiveEth() (gas: 121706)
OptimismPortal_Test:test_cannotVerifyRecentWithdrawal() (gas: 21863)
OptimismPortal_Test:test_cannotVerifyRecentWithdrawal() (gas: 21886)
OptimismPortal_Test:test_depositTransaction_NoValueContract() (gas: 70746)
OptimismPortal_Test:test_depositTransaction_NoValueEOA() (gas: 71114)
OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract() (gas: 70773)
......@@ -117,7 +117,7 @@ OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreat
OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 69947)
OptimismPortal_Test:test_depositTransaction_withEthValueFromContract() (gas: 77478)
OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA() (gas: 78049)
OptimismPortal_Test:test_invalidWithdrawalProof() (gas: 28541)
OptimismPortal_Test:test_invalidWithdrawalProof() (gas: 33702)
Proxy_Test:test_clashingFunctionSignatures() (gas: 101427)
Proxy_Test:test_implementationKey() (gas: 20942)
Proxy_Test:test_implementationProxyCallIfNotAdmin() (gas: 30021)
......@@ -163,5 +163,5 @@ ResourceMetering_Test:test_useMoreThanMaxReverts() (gas: 16024)
SequencerFeeVault_Test:test_constructor() (gas: 7611)
SequencerFeeVault_Test:test_minWithdrawalAmount() (gas: 5429)
SequencerFeeVault_Test:test_receive() (gas: 17280)
SequencerFeeVault_Test:test_revertWithdraw() (gas: 9245)
SequencerFeeVault_Test:test_withdraw() (gas: 147297)
SequencerFeeVault_Test:test_revertWithdraw() (gas: 9266)
SequencerFeeVault_Test:test_withdraw() (gas: 147300)
......@@ -6,124 +6,149 @@ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title L2OutputOracle
* @notice The L2 state is committed to in this contract
* The payable keyword is used on appendL2Output to save gas on the msg.value check.
* This contract should be deployed behind an upgradable proxy
* The payable keyword is used on appendL2Output to save gas on the msg.value check.
* This contract should be deployed behind an upgradable proxy
*/
// slither-disable-next-line locked-ether
contract L2OutputOracle is Ownable {
/**********
* Events *
**********/
/**
* @notice OutputProposal represents a commitment to the L2 state.
* The timestamp is the L1 timestamp that the output root is posted.
* This timestamp is used to verify that the finalization period
* has passed since the output root was submitted.
*/
struct OutputProposal {
bytes32 outputRoot;
uint256 timestamp;
}
/// @notice Emitted when an output is appended.
event l2OutputAppended(
/**
* @notice Emitted when an output is appended.
*
* @param _l2Output The output root.
* @param _l1Timestamp The L1 timestamp when appended.
* @param _l2BlockNumber The L2 block number of the output root.
*/
event L2OutputAppended(
bytes32 indexed _l2Output,
uint256 indexed _l1Timestamp,
uint256 indexed _l2timestamp
uint256 indexed _l2BlockNumber
);
/// @notice Emitted when an output is deleted.
event l2OutputDeleted(
/**
* @notice Emitted when an output is deleted.
*
* @param _l2Output The output root.
* @param _l1Timestamp The L1 timestamp when appended.
* @param _l2BlockNumber The L2 block number of the output root.
*/
event L2OutputDeleted(
bytes32 indexed _l2Output,
uint256 indexed _l1Timestamp,
uint256 indexed _l2timestamp
uint256 indexed _l2BlockNumber
);
/**********************
* Contract Variables *
**********************/
/// @notice The interval in seconds at which checkpoints must be submitted.
/**
* @notice The interval in L2 blocks at which checkpoints must be submitted.
*/
uint256 public immutable SUBMISSION_INTERVAL;
/// @notice The time between blocks on L2.
uint256 public immutable L2_BLOCK_TIME;
/// @notice The number of blocks in the chain before the first block in this contract.
/**
* @notice The number of blocks in the chain before the first block in this contract.
*/
uint256 public immutable HISTORICAL_TOTAL_BLOCKS;
/// @notice The timestamp of the first L2 block recorded in this contract.
uint256 public immutable STARTING_BLOCK_TIMESTAMP;
/**
* @notice The number of the first L2 block recorded in this contract.
*/
uint256 public immutable STARTING_BLOCK_NUMBER;
/// @notice The timestamp of the most recent L2 block recorded in this contract.
uint256 public latestBlockTimestamp;
/**
* @notice The timestamp of the first L2 block recorded in this contract.
*/
uint256 public immutable STARTING_TIMESTAMP;
/// @notice A mapping from L2 timestamps to the output root for the block with that timestamp.
mapping(uint256 => OutputProposal) internal l2Outputs;
/**
* @notice The time between L2 blocks in seconds.
*/
uint256 public immutable L2_BLOCK_TIME;
/// @notice OutputProposal represents a commitment to the L2 state.
/// The timestamp is the L1 timestamp that the output root is posted.
/// This timestamp is used to verify that the finalization period
/// has passed since the output root was submitted.
struct OutputProposal {
bytes32 outputRoot;
uint256 timestamp;
}
/**
* @notice The number of the most recent L2 block recorded in this contract.
*/
uint256 public latestBlockNumber;
/***************
* Constructor *
***************/
/**
* @notice A mapping from L2 block numbers to the respective output root. Note that these
* outputs should not be considered finalized until the finalization period (as defined
* in the Optimism Portal) has passed.
*/
mapping(uint256 => OutputProposal) internal l2Outputs;
/**
* @notice Initialize the L2OutputOracle contract.
* @param _submissionInterval The desired interval in seconds at which
* checkpoints must be submitted.
* @param _l2BlockTime The desired L2 inter-block time in seconds.
* @param _genesisL2Output The initial L2 output of the L2 chain.
*
* @param _submissionInterval The desired interval in seconds at which
* checkpoints must be submitted.
* @param _genesisL2Output The initial L2 output of the L2 chain.
* @param _historicalTotalBlocks The number of blocks that preceding the
* initialization of the L2 chain.
* @param _startingBlockTimestamp The timestamp to start L2 block at.
* @param _sequencer The address of the _sequencer.
* initialization of the L2 chain.
* @param _startingBlockNumber The number of the first L2 block.
* @param _startingTimestamp The timestamp of the first L2 block.
* @param _l2BlockTime The timestamp of the first L2 block.
* @param _sequencer The address of the sequencer.
*/
constructor(
uint256 _submissionInterval,
uint256 _l2BlockTime,
bytes32 _genesisL2Output,
uint256 _historicalTotalBlocks,
uint256 _startingBlockTimestamp,
uint256 _startingBlockNumber,
uint256 _startingTimestamp,
uint256 _l2BlockTime,
address _sequencer
) {
require(
_submissionInterval % _l2BlockTime == 0,
"Submission Interval must be a multiple of L2 Block Time"
_l2BlockTime < block.timestamp,
"Output Oracle: Initial L2 block time must be less than current time"
);
SUBMISSION_INTERVAL = _submissionInterval;
L2_BLOCK_TIME = _l2BlockTime;
// solhint-disable-next-line not-rely-on-time
l2Outputs[_startingBlockTimestamp] = OutputProposal(_genesisL2Output, block.timestamp);
HISTORICAL_TOTAL_BLOCKS = _historicalTotalBlocks;
// solhint-disable-next-line not-rely-on-time
latestBlockTimestamp = _startingBlockTimestamp;
// solhint-disable-next-line not-rely-on-time
STARTING_BLOCK_TIMESTAMP = _startingBlockTimestamp;
STARTING_BLOCK_NUMBER = _startingBlockNumber;
STARTING_TIMESTAMP = _startingTimestamp;
L2_BLOCK_TIME = _l2BlockTime;
l2Outputs[_startingBlockNumber] = OutputProposal(_genesisL2Output, block.timestamp);
latestBlockNumber = _startingBlockNumber;
_transferOwnership(_sequencer);
}
/*********************************
* External and Public Functions *
*********************************/
/**
* @notice Accepts an L2 outputRoot and the timestamp of the corresponding L2 block. The
* timestamp must be equal to the current value returned by `nextTimestamp()` in order to be
* accepted.
* This function may only be called by the Sequencer.
* @param _l2Output The L2 output of the checkpoint block.
* @param _l2timestamp The L2 block timestamp that resulted in _l2Output.
* @param _l1Blockhash A block hash which must be included in the current chain.
* @param _l1Blocknumber The block number with the specified block hash.
* timestamp must be equal to the current value returned by `nextTimestamp()` in order
* to be accepted.
* This function may only be called by the Sequencer.
*
* @param _l2Output The L2 output of the checkpoint block.
* @param _l2BlockNumber The L2 block number that resulted in _l2Output.
* @param _l1Blockhash A block hash which must be included in the current chain.
* @param _l1BlockNumber The block number with the specified block hash.
*/
function appendL2Output(
bytes32 _l2Output,
uint256 _l2timestamp,
uint256 _l2BlockNumber,
bytes32 _l1Blockhash,
uint256 _l1Blocknumber
uint256 _l1BlockNumber
) external payable onlyOwner {
require(_l2timestamp < block.timestamp, "Cannot append L2 output in future");
require(_l2timestamp == nextTimestamp(), "Timestamp not equal to next expected timestamp");
require(_l2Output != bytes32(0), "Cannot submit empty L2 output");
require(
_l2BlockNumber == nextBlockNumber(),
"OutputOracle: Block number must be equal to next expected block number."
);
require(
computeL2Timestamp(_l2BlockNumber) < block.timestamp,
"OutputOracle: Cannot append L2 output in future."
);
require(_l2Output != bytes32(0), "OutputOracle: Cannot submit empty L2 output.");
if (_l1Blockhash != bytes32(0)) {
// This check allows the sequencer to append an output based on a given L1 block,
......@@ -135,71 +160,74 @@ contract L2OutputOracle is Ownable {
// blockhash value, and delay submission until it is confident that the L1 block is
// finalized.
require(
blockhash(_l1Blocknumber) == _l1Blockhash,
"Blockhash does not match the hash at the expected height."
blockhash(_l1BlockNumber) == _l1Blockhash,
"OutputOracle: Blockhash does not match the hash at the expected height."
);
}
l2Outputs[_l2timestamp] = OutputProposal(_l2Output, block.timestamp);
latestBlockTimestamp = _l2timestamp;
l2Outputs[_l2BlockNumber] = OutputProposal(_l2Output, block.timestamp);
latestBlockNumber = _l2BlockNumber;
emit l2OutputAppended(_l2Output, block.timestamp, _l2timestamp);
emit L2OutputAppended(_l2Output, block.timestamp, _l2BlockNumber);
}
/**
* @notice Deletes the most recent output.
*
* @param _proposal Represents the output proposal to delete
*/
function deleteL2Output(OutputProposal memory _proposal) external onlyOwner {
OutputProposal memory outputToDelete = l2Outputs[latestBlockTimestamp];
OutputProposal memory outputToDelete = l2Outputs[latestBlockNumber];
require(
_proposal.outputRoot == outputToDelete.outputRoot,
"Can only delete the most recent output."
"OutputOracle: The output root to delete does not match the latest output proposal."
);
require(
_proposal.timestamp == outputToDelete.timestamp,
"OutputOracle: The timestamp to delete does not match the latest output proposal."
);
require(_proposal.timestamp == outputToDelete.timestamp, "");
emit l2OutputDeleted(
emit L2OutputDeleted(
outputToDelete.outputRoot,
outputToDelete.timestamp,
latestBlockTimestamp
latestBlockNumber
);
delete l2Outputs[latestBlockTimestamp];
latestBlockTimestamp = latestBlockTimestamp - SUBMISSION_INTERVAL;
delete l2Outputs[latestBlockNumber];
latestBlockNumber = latestBlockNumber - SUBMISSION_INTERVAL;
}
/**
* @notice Computes the timestamp of the next L2 block that needs to be checkpointed.
* @notice Computes the block number of the next L2 block that needs to be checkpointed.
*/
function nextTimestamp() public view returns (uint256) {
return latestBlockTimestamp + SUBMISSION_INTERVAL;
function nextBlockNumber() public view returns (uint256) {
return latestBlockNumber + SUBMISSION_INTERVAL;
}
/**
* @notice Returns the L2 output proposal given a target L2 block timestamp.
* Returns a null output proposal if none is found.
* @param _l2Timestamp The L2 block timestamp of the target block.
* @notice Returns the L2 output proposal given a target L2 block number.
* Returns a null output proposal if none is found.
*
* @param _l2BlockNumber The L2 block number of the target block.
*/
function getL2Output(uint256 _l2Timestamp) external view returns (OutputProposal memory) {
return l2Outputs[_l2Timestamp];
function getL2Output(uint256 _l2BlockNumber) external view returns (OutputProposal memory) {
return l2Outputs[_l2BlockNumber];
}
/**
* @notice Computes the L2 block number given a target L2 block timestamp.
* @param _l2timestamp The L2 block timestamp of the target block.
* @notice Returns the L2 timestamp corresponding to a given L2 block number.
* Returns a null output proposal if none is found.
*
* @param _l2BlockNumber The L2 block number of the target block.
*/
function computeL2BlockNumber(uint256 _l2timestamp) external view returns (uint256) {
function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) {
require(
_l2timestamp >= STARTING_BLOCK_TIMESTAMP,
"Timestamp prior to startingBlockTimestamp"
_l2BlockNumber >= STARTING_BLOCK_NUMBER,
"OutputOracle: Block number must be greater than or equal to the starting block number."
);
// For the first block recorded (ie. _l2timestamp = STARTING_BLOCK_TIMESTAMP), the
// L2BlockNumber should be HISTORICAL_TOTAL_BLOCKS + 1.
unchecked {
return
HISTORICAL_TOTAL_BLOCKS +
((_l2timestamp - STARTING_BLOCK_TIMESTAMP) / L2_BLOCK_TIME);
}
return
STARTING_TIMESTAMP + ((_l2BlockNumber - STARTING_BLOCK_NUMBER) * SUBMISSION_INTERVAL);
}
}
......@@ -150,7 +150,7 @@ contract OptimismPortal is ResourceMetering {
* @param _value ETH to send to the target.
* @param _gasLimit Minumum gas to be forwarded to the target.
* @param _data Data to send to the target.
* @param _l2Timestamp L2 timestamp of the outputRoot.
* @param _l2BlockNumber L2 block number of the outputRoot.
* @param _outputRootProof Inclusion proof of the withdrawer contracts storage root.
* @param _withdrawalProof Inclusion proof for the given withdrawal in the withdrawer contract.
*/
......@@ -161,7 +161,7 @@ contract OptimismPortal is ResourceMetering {
uint256 _value,
uint256 _gasLimit,
bytes calldata _data,
uint256 _l2Timestamp,
uint256 _l2BlockNumber,
WithdrawalVerifier.OutputRootProof calldata _outputRootProof,
bytes calldata _withdrawalProof
) external payable {
......@@ -179,7 +179,7 @@ contract OptimismPortal is ResourceMetering {
);
// Get the output root.
L2OutputOracle.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2Timestamp);
L2OutputOracle.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber);
// Ensure that enough time has passed since the proposal was submitted before allowing a
// withdrawal. Under the assumption that the fault proof mechanism is operating correctly,
......
......@@ -47,33 +47,35 @@ contract L2OutputOracle_Initializer is CommonTest {
L2OutputOracle oracle;
// Constructor arguments
address sequencer = 0x000000000000000000000000000000000000AbBa;
uint256 submissionInterval = 1800;
uint256 l2BlockTime = 2;
uint256 submissionInterval = 42;
bytes32 genesisL2Output = keccak256(abi.encode(0));
uint256 historicalTotalBlocks = 100;
// Cache of the initial L2 timestamp
uint256 startingBlockTimestamp;
uint256 historicalTotalBlocks = 199;
uint256 startingBlockNumber = 200;
uint256 startingTimestamp = 1000;
uint256 l2BlockTime = 2;
address sequencer = 0x000000000000000000000000000000000000AbBa;
// By default the first block has timestamp zero, which will cause underflows in the tests
uint256 initTime = 1000;
// Test data
uint256 initL1Time;
function setUp() public virtual {
_setUp();
// Move time forward so we have a non-zero starting timestamp
vm.warp(initTime);
// By default the first block has timestamp and number zero, which will cause underflows in the
// tests, so we'll move forward to these block values.
initL1Time = startingTimestamp + 1;
vm.warp(initL1Time);
vm.roll(startingBlockNumber);
// Deploy the L2OutputOracle and transfer owernship to the sequencer
oracle = new L2OutputOracle(
submissionInterval,
l2BlockTime,
genesisL2Output,
historicalTotalBlocks,
initTime,
startingBlockNumber,
startingTimestamp,
l2BlockTime,
sequencer
);
startingBlockTimestamp = block.timestamp;
}
}
......
......@@ -11,85 +11,79 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
super.setUp();
}
// advance the evm state to meet the L2OutputOracle's requirements for appendL2Output
function oracleWarpRoll(uint256 _nextBlockNumber) public {
vm.roll(_nextBlockNumber);
vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1);
}
function test_constructor() external {
assertEq(oracle.owner(), sequencer);
assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval);
assertEq(oracle.L2_BLOCK_TIME(), l2BlockTime);
assertEq(oracle.HISTORICAL_TOTAL_BLOCKS(), historicalTotalBlocks);
assertEq(oracle.latestBlockTimestamp(), startingBlockTimestamp);
assertEq(oracle.STARTING_BLOCK_TIMESTAMP(), startingBlockTimestamp);
assertEq(oracle.latestBlockNumber(), startingBlockNumber);
assertEq(oracle.STARTING_BLOCK_NUMBER(), startingBlockNumber);
assertEq(oracle.STARTING_TIMESTAMP(), startingTimestamp);
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(startingBlockTimestamp);
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(startingBlockNumber);
assertEq(proposal.outputRoot, genesisL2Output);
assertEq(proposal.timestamp, initTime);
assertEq(proposal.timestamp, initL1Time);
}
/****************
* Getter Tests *
****************/
// Test: latestBlockTimestamp() should return the correct value
function test_latestBlockTimestamp() external {
uint256 appendedTimestamp = oracle.nextTimestamp();
// Test: latestBlockNumber() should return the correct value
function test_latestBlockNumber() external {
uint256 appendedNumber = oracle.nextBlockNumber();
// Warp to after the timestamp we'll append
vm.warp(appendedTimestamp + 1);
// Roll to after the block number we'll append
oracleWarpRoll(appendedNumber);
vm.prank(sequencer);
oracle.appendL2Output(appendedOutput1, appendedTimestamp, 0, 0);
assertEq(oracle.latestBlockTimestamp(), appendedTimestamp);
oracle.appendL2Output(appendedOutput1, appendedNumber, 0, 0);
assertEq(oracle.latestBlockNumber(), appendedNumber);
}
// Test: getL2Output() should return the correct value
function test_getL2Output() external {
uint256 nextTimestamp = oracle.nextTimestamp();
vm.warp(nextTimestamp + 1);
uint256 nextBlockNumber = oracle.nextBlockNumber();
oracleWarpRoll(nextBlockNumber);
vm.prank(sequencer);
oracle.appendL2Output(appendedOutput1, nextTimestamp, 0, 0);
oracle.appendL2Output(appendedOutput1, nextBlockNumber, 0, 0);
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(nextTimestamp);
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(nextBlockNumber);
assertEq(proposal.outputRoot, appendedOutput1);
assertEq(proposal.timestamp, nextTimestamp + 1);
assertEq(proposal.timestamp, block.timestamp);
L2OutputOracle.OutputProposal memory proposal2 = oracle.getL2Output(0);
assertEq(proposal2.outputRoot, bytes32(0));
assertEq(proposal2.timestamp, 0);
}
// Test: nextTimestamp() should return the correct value
function test_nextTimestamp() external {
// Test: nextBlockNumber() should return the correct value
function test_nextBlockNumber() external {
assertEq(
oracle.nextTimestamp(),
oracle.nextBlockNumber(),
// The return value should match this arithmetic
oracle.latestBlockTimestamp() + oracle.SUBMISSION_INTERVAL()
oracle.latestBlockNumber() + oracle.SUBMISSION_INTERVAL()
);
}
// Test: computeL2BlockNumber() should return the correct value
function test_computeL2BlockNumber() external {
// Test with the timestamp of the very first appended block
uint256 argTimestamp = startingBlockTimestamp;
uint256 expected = historicalTotalBlocks;
assertEq(oracle.computeL2BlockNumber(argTimestamp), expected);
// Test with an integer multiple of the l2BlockTime
argTimestamp = startingBlockTimestamp + 20;
expected = historicalTotalBlocks + (20 / l2BlockTime);
assertEq(oracle.computeL2BlockNumber(argTimestamp), expected);
// Test with a remainder
argTimestamp = startingBlockTimestamp + 33;
expected = historicalTotalBlocks + (33 / l2BlockTime);
assertEq(oracle.computeL2BlockNumber(argTimestamp), expected);
}
function test_computeL2Timestamp() external {
// reverts if timestamp is too low
vm.expectRevert("OutputOracle: Block number must be greater than or equal to the starting block number.");
oracle.computeL2Timestamp(startingBlockNumber - 1);
// Test: computeL2BlockNumber() fails with a blockNumber from before the startingBlockTimestamp
function testCannot_computePreHistoricalL2BlockNumber() external {
bytes memory expectedError = "Timestamp prior to startingBlockTimestamp";
uint256 argTimestamp = startingBlockTimestamp - 1;
vm.expectRevert(expectedError);
oracle.computeL2BlockNumber(argTimestamp);
// returns the correct value...
// ... for the very first block
assertEq(oracle.computeL2Timestamp(startingBlockNumber), startingTimestamp);
// ... for the first block after the starting block
assertEq(oracle.computeL2Timestamp(startingBlockNumber + 1), startingTimestamp + submissionInterval);
// ... for some other block number
assertEq(oracle.computeL2Timestamp(startingBlockNumber + 96024), startingTimestamp + submissionInterval * 96024);
}
/*****************************
......@@ -100,37 +94,29 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
// specified.
function test_appendingAnotherOutput() public {
bytes32 appendedOutput2 = keccak256(abi.encode(2));
uint256 nextTimestamp = oracle.nextTimestamp();
uint256 appendedTimestamp = oracle.latestBlockTimestamp();
uint256 nextBlockNumber = oracle.nextBlockNumber();
oracleWarpRoll(nextBlockNumber);
uint256 appendedNumber = oracle.latestBlockNumber();
// Ensure the submissionInterval is enforced
assertEq(nextTimestamp, appendedTimestamp + submissionInterval);
assertEq(nextBlockNumber, appendedNumber + submissionInterval);
vm.warp(nextTimestamp + 1);
vm.roll(nextBlockNumber + 1);
vm.prank(sequencer);
oracle.appendL2Output(appendedOutput2, nextTimestamp, 0, 0);
oracle.appendL2Output(appendedOutput2, nextBlockNumber, 0, 0);
}
// Test: appendL2Output succeeds when given valid input, and when a block hash and number are
// specified for reorg protection.
// This tests is disabled (w/ skip_ prefix) because all blocks in Foundry currently have a
// blockhash of zero.
function skip_test_appendWithBlockhashAndHeight() external {
// Move ahead to block 100 so that we can reference historical blocks
vm.roll(100);
function test_appendWithBlockhashAndHeight() external {
// Get the number and hash of a previous block in the chain
uint256 l1BlockNumber = block.number - 1;
bytes32 l1BlockHash = blockhash(l1BlockNumber);
uint256 prevL1BlockNumber = block.number - 1;
bytes32 prevL1BlockHash = blockhash(prevL1BlockNumber);
uint256 nextTimestamp = oracle.nextTimestamp();
vm.warp(nextTimestamp + 1);
uint256 nextBlockNumber = oracle.nextBlockNumber();
oracleWarpRoll(nextBlockNumber);
vm.prank(sequencer);
// Changing the l1BlockNumber argument should break this tests, however it does not
// per the comment preceding this test.
oracle.appendL2Output(nonZeroHash, nextTimestamp, l1BlockHash, l1BlockNumber);
oracle.appendL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber);
}
/***************************
......@@ -139,49 +125,55 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
// Test: appendL2Output fails if called by a party that is not the sequencer.
function testCannot_appendOutputIfNotSequencer() external {
uint256 nextTimestamp = oracle.nextTimestamp();
uint256 nextBlockNumber = oracle.nextBlockNumber();
oracleWarpRoll(nextBlockNumber);
vm.prank(address(128));
vm.warp(nextTimestamp + 1);
vm.expectRevert("Ownable: caller is not the owner");
oracle.appendL2Output(nonZeroHash, nextTimestamp, 0, 0);
oracle.appendL2Output(nonZeroHash, nextBlockNumber, 0, 0);
}
// Test: appendL2Output fails given a zero blockhash.
function testCannot_appendEmptyOutput() external {
bytes32 outputToAppend = bytes32(0);
uint256 nextTimestamp = oracle.nextTimestamp();
vm.warp(nextTimestamp + 1);
uint256 nextBlockNumber = oracle.nextBlockNumber();
oracleWarpRoll(nextBlockNumber);
vm.prank(sequencer);
vm.expectRevert("Cannot submit empty L2 output");
oracle.appendL2Output(outputToAppend, nextTimestamp, 0, 0);
vm.expectRevert("OutputOracle: Cannot submit empty L2 output.");
oracle.appendL2Output(outputToAppend, nextBlockNumber, 0, 0);
}
// Test: appendL2Output fails if the timestamp doesn't match the next expected timestamp.
function testCannot_appendUnexpectedTimestamp() external {
uint256 nextTimestamp = oracle.nextTimestamp();
vm.warp(nextTimestamp + 1);
// Test: appendL2Output fails if the block number doesn't match the next expected number.
function testCannot_appendUnexpectedBlockNumber() external {
uint256 nextBlockNumber = oracle.nextBlockNumber();
oracleWarpRoll(nextBlockNumber);
vm.prank(sequencer);
vm.expectRevert("Timestamp not equal to next expected timestamp");
oracle.appendL2Output(nonZeroHash, nextTimestamp - 1, 0, 0);
vm.expectRevert("OutputOracle: Block number must be equal to next expected block number.");
oracle.appendL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0);
}
// Test: appendL2Output fails if the timestamp is equal to the current L1 timestamp.
function testCannot_appendCurrentTimestamp() external {
uint256 nextTimestamp = oracle.nextTimestamp();
vm.warp(nextTimestamp + 1);
// Test: appendL2Output fails if it would have a timestamp in the future.
function testCannot_appendFutureTimetamp() external {
uint256 nextBlockNumber = oracle.nextBlockNumber();
uint256 nextTimestamp = oracle.computeL2Timestamp(nextBlockNumber);
vm.warp(nextTimestamp);
vm.prank(sequencer);
vm.expectRevert("Cannot append L2 output in future");
oracle.appendL2Output(nonZeroHash, block.timestamp, 0, 0);
vm.expectRevert("OutputOracle: Cannot append L2 output in future.");
oracle.appendL2Output(nonZeroHash, nextBlockNumber, 0, 0);
}
// Test: appendL2Output fails if the timestamp is in the future.
function testCannot_appendFutureTimestamp() external {
uint256 nextTimestamp = oracle.nextTimestamp();
vm.warp(nextTimestamp + 1);
// Test: appendL2Output fails if a non-existent L1 block hash and number are provided for reorg
// protection.
function testCannot_appendOnWrongFork() external {
uint256 nextBlockNumber = oracle.nextBlockNumber();
oracleWarpRoll(nextBlockNumber);
vm.prank(sequencer);
vm.expectRevert("Cannot append L2 output in future");
oracle.appendL2Output(nonZeroHash, block.timestamp + 1, 0, 0);
vm.expectRevert("OutputOracle: Blockhash does not match the hash at the expected height.");
oracle.appendL2Output(
nonZeroHash,
nextBlockNumber,
bytes32(uint256(0x01)),
block.number - 1
);
}
// Test: appendL2Output fails when given valid input, but the block hash and number do not
......@@ -196,56 +188,57 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
uint256 l1BlockNumber = block.number - 1;
bytes32 l1BlockHash = blockhash(l1BlockNumber);
uint256 nextTimestamp = oracle.nextTimestamp();
vm.warp(nextTimestamp + 1);
uint256 nextBlockNumber = oracle.nextBlockNumber();
oracleWarpRoll(nextBlockNumber);
vm.prank(sequencer);
// This will fail when foundry no longer returns zerod block hashes
oracle.appendL2Output(nonZeroHash, nextTimestamp, l1BlockHash, l1BlockNumber - 1);
oracle.appendL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1);
}
/****************
* Delete Tests *
****************/
event l2OutputDeleted(
event L2OutputDeleted(
bytes32 indexed _l2Output,
uint256 indexed _l1Timestamp,
uint256 indexed _l2timestamp
uint256 indexed _l2BlockNumber
);
function test_deleteL2Output() external {
test_appendingAnotherOutput();
uint256 latestBlockTimestamp = oracle.latestBlockTimestamp();
L2OutputOracle.OutputProposal memory proposalToDelete = oracle.getL2Output(latestBlockTimestamp);
L2OutputOracle.OutputProposal memory newLatestOutput = oracle.getL2Output(latestBlockTimestamp - submissionInterval);
uint256 latestBlockNumber = oracle.latestBlockNumber();
L2OutputOracle.OutputProposal memory proposalToDelete = oracle.getL2Output(latestBlockNumber);
L2OutputOracle.OutputProposal memory newLatestOutput = oracle.getL2Output(latestBlockNumber - submissionInterval);
vm.prank(sequencer);
vm.expectEmit(true, true, false, false);
emit l2OutputDeleted(
emit L2OutputDeleted(
proposalToDelete.outputRoot,
proposalToDelete.timestamp,
latestBlockTimestamp
latestBlockNumber
);
oracle.deleteL2Output(proposalToDelete);
// validate latestBlockTimestamp has been reduced
uint256 latestBlockTimestampAfter = oracle.latestBlockTimestamp();
// validate latestBlockNumber has been reduced
uint256 latestBlockNumberAfter = oracle.latestBlockNumber();
assertEq(
latestBlockTimestamp - submissionInterval,
latestBlockTimestampAfter
latestBlockNumber - submissionInterval,
latestBlockNumberAfter
);
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(latestBlockTimestampAfter);
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(latestBlockNumberAfter);
// validate that the new latest output is as expected.
assertEq(newLatestOutput.outputRoot, proposal.outputRoot);
assertEq(newLatestOutput.timestamp, proposal.timestamp);
}
function testCannot_deleteL2Output_ifNotSequencer() external {
uint256 latestBlockTimestamp = oracle.latestBlockTimestamp();
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(latestBlockTimestamp);
uint256 latestBlockNumber = oracle.latestBlockNumber();
L2OutputOracle.OutputProposal memory proposal = oracle.getL2Output(latestBlockNumber);
vm.expectRevert("Ownable: caller is not the owner");
oracle.deleteL2Output(proposal);
......@@ -254,11 +247,11 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
function testCannot_deleteWrongL2Output() external {
test_appendingAnotherOutput();
uint256 previousBlockTimestamp = oracle.latestBlockTimestamp() - submissionInterval;
L2OutputOracle.OutputProposal memory proposalToDelete = oracle.getL2Output(previousBlockTimestamp);
uint256 previousBlockNumber = oracle.latestBlockNumber() - submissionInterval;
L2OutputOracle.OutputProposal memory proposalToDelete = oracle.getL2Output(previousBlockNumber);
vm.prank(sequencer);
vm.expectRevert("Can only delete the most recent output.");
vm.expectRevert("OutputOracle: The output root to delete does not match the latest output proposal.");
oracle.deleteL2Output(proposalToDelete);
}
}
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import { CommonTest } from "./CommonTest.t.sol";
import { L2OutputOracle_Initializer } from "./CommonTest.t.sol";
import { AddressAliasHelper } from "../libraries/AddressAliasHelper.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { OptimismPortal } from "../L1/OptimismPortal.sol";
import { WithdrawalVerifier } from "../libraries/Lib_WithdrawalVerifier.sol";
contract OptimismPortal_Test is CommonTest {
contract OptimismPortal_Test is L2OutputOracle_Initializer {
event TransactionDeposited(
address indexed from,
address indexed to,
......@@ -20,19 +20,11 @@ contract OptimismPortal_Test is CommonTest {
);
// Dependencies
L2OutputOracle oracle;
// L2OutputOracle oracle;
OptimismPortal op;
function setUp() external {
_setUp();
oracle = new L2OutputOracle(
1800,
2,
keccak256(abi.encode(0)),
100,
1,
address(666)
);
function setUp() public override {
L2OutputOracle_Initializer.setUp();
op = new OptimismPortal(oracle, 7 days);
}
......@@ -44,15 +36,7 @@ contract OptimismPortal_Test is CommonTest {
function test_OptimismPortalReceiveEth() external {
vm.expectEmit(true, true, false, true);
emit TransactionDeposited(
alice,
alice,
100,
100,
100_000,
false,
hex""
);
emit TransactionDeposited(alice, alice, 100, 100, 100_000, false, hex"");
// give alice money and send as an eoa
vm.deal(alice, 2**64);
......@@ -254,47 +238,35 @@ contract OptimismPortal_Test is CommonTest {
// function test_verifyWithdrawal() external {}
function test_cannotVerifyRecentWithdrawal() external {
WithdrawalVerifier.OutputRootProof memory outputRootProof = WithdrawalVerifier.OutputRootProof({
version: bytes32(0),
stateRoot: bytes32(0),
withdrawerStorageRoot: bytes32(0),
latestBlockhash: bytes32(0)
});
WithdrawalVerifier.OutputRootProof memory outputRootProof = WithdrawalVerifier
.OutputRootProof({
version: bytes32(0),
stateRoot: bytes32(0),
withdrawerStorageRoot: bytes32(0),
latestBlockhash: bytes32(0)
});
vm.expectRevert("OptimismPortal: proposal is not yet finalized");
op.finalizeWithdrawalTransaction(
0,
alice,
alice,
0,
0,
hex"",
0,
outputRootProof,
hex""
);
op.finalizeWithdrawalTransaction(0, alice, alice, 0, 0, hex"", 0, outputRootProof, hex"");
}
function test_invalidWithdrawalProof() external {
WithdrawalVerifier.OutputRootProof memory outputRootProof = WithdrawalVerifier.OutputRootProof({
version: bytes32(0),
stateRoot: bytes32(0),
withdrawerStorageRoot: bytes32(0),
latestBlockhash: bytes32(0)
});
vm.warp(oracle.nextTimestamp() + op.FINALIZATION_PERIOD_SECONDS());
vm.expectRevert("OptimismPortal: invalid output root proof");
op.finalizeWithdrawalTransaction(
0,
alice,
alice,
0,
0,
hex"",
0,
outputRootProof,
hex""
WithdrawalVerifier.OutputRootProof memory outputRootProof = WithdrawalVerifier
.OutputRootProof({
version: bytes32(0),
stateRoot: bytes32(0),
withdrawerStorageRoot: bytes32(0),
latestBlockhash: bytes32(0)
});
vm.warp(
oracle.getL2Output(
oracle.latestBlockNumber()
).timestamp
+ op.FINALIZATION_PERIOD_SECONDS()
);
vm.expectRevert("OptimismPortal: invalid output root proof");
op.finalizeWithdrawalTransaction(0, alice, alice, 0, 0, hex"", 0, outputRootProof, hex"");
}
}
......@@ -91,28 +91,28 @@ where:
## L2 Output Oracle Smart Contract
L2 blocks are produced at a constant rate of `L2_BLOCK_TIME` (2 seconds).
A new L2 output MUST be appended to the chain once per `SUBMISSION_INTERVAL` (1800 seconds). Note that this interval is\
based on L2 time. It is OK to have L2 outputs submitted at larger or small intervals.
A new L2 output MUST be appended to the chain once per `SUBMISSION_INTERVAL` which is based on a number of blocks.
The exact number is yet to be determined, and will depend on the design of the fault proving game.
The L2 Output Oracle contract implements the following interface:
```js
/**
* Accepts an L2 output checkpoint and the timestamp of the corresponding L2
* block. The timestamp must be equal to the current value returned by
* `nextTimestamp()` in order to be accepted.
* @notice Accepts an L2 outputRoot and the timestamp of the corresponding L2 block. The
* timestamp must be equal to the current value returned by `nextTimestamp()` in order to be
* accepted.
* This function may only be called by the Sequencer.
* @param _l2Output The L2 output of the checkpoint block.
* @param _l2timestamp The L2 block timestamp that resulted in _l2Output.
* @param _l1Blockhash A block hash which must be included in the current chain.
* @param _l1Blocknumber The block number with the specified block hash.
*/
function appendL2Output(
bytes32 _l2Output,
uint256 _l2timestamp,
bytes32 _l1Blockhash,
uint256 _l1Blocknumber
)
* @param _l2Output The L2 output of the checkpoint block.
* @param _l2BlockNumber The L2 block number that resulted in _l2Output.
* @param _l1Blockhash A block hash which must be included in the current chain.
* @param _l1BlockNumber The block number with the specified block hash.
*/
function appendL2Output(
bytes32 _l2Output,
uint256 _l2BlockNumber,
bytes32 _l1Blockhash,
uint256 _l1BlockNumber
)
/**
* @notice Deletes the most recent output.
......@@ -122,15 +122,9 @@ function appendL2Output(
function deleteL2Output(bytes32 _l2Output) external
/**
* Computes the timestamp of the next L2 block that needs to be checkpointed.
*/
function nextTimestamp() public view returns (uint256)
/**
* Computes the L2 block number given a target L2 block timestamp.
* @param _timestamp The L2 block timestamp of the target block.
* @notice Computes the block number of the next L2 block that needs to be checkpointed.
*/
function computeL2BlockNumber(uint256 _timestamp) public view returns (uint256)
function nextBlockNumber() public view returns (uint256) {
```
## Security Considerations
......
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