diff --git a/.eslintrc.js b/.eslintrc.js index 046c9205bf..c91d204f89 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,10 +1,16 @@ +// eslint-disable-next-line no-undef module.exports = { root: true, env: { browser: true, es6: true, }, - ignorePatterns: ['dist', 'coverage', 'packages/contracts/hardhat'], + ignorePatterns: [ + 'dist', + 'coverage', + 'packages/contracts/hardhat', + 'test/**/*.ts', + ], extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a742865aa3..21506aba19 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -80,6 +80,7 @@ You'll need the following: - [Yarn](https://classic.yarnpkg.com/en/docs/install) - [Docker](https://docs.docker.com/get-docker/) - [Docker Compose](https://docs.docker.com/compose/install/) +- [Go](https://go.dev/dl/) - [Foundry](https://getfoundry.sh) ### Setup diff --git a/bindings/bindings/kromaportal.go b/bindings/bindings/kromaportal.go index 2abdc8ef34..e4ca3c1bcd 100644 --- a/bindings/bindings/kromaportal.go +++ b/bindings/bindings/kromaportal.go @@ -31,8 +31,8 @@ var ( // KromaPortalMetaData contains all meta data concerning the KromaPortal contract. var KromaPortalMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_guardian\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_paused\",\"type\":\"bool\"},{\"internalType\":\"contractZKMerkleTrie\",\"name\":\"_zkMerkleTrie\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"opaqueData\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"WithdrawalProven\",\"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\":\"GUARDIAN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"MAXIMUM_BASE_FEE\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"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\":[],\"name\":\"ZK_MERKLE_TRIE\",\"outputs\":[{\"internalType\":\"contractZKMerkleTrie\",\"name\":\"\",\"type\":\"address\"}],\"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\":[{\"components\":[{\"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\":\"structTypes.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_paused\",\"type\":\"bool\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"name\":\"isOutputFinalized\",\"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\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"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\":\"structTypes.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"nextBlockHash\",\"type\":\"bytes32\"}],\"internalType\":\"structTypes.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"_withdrawalProof\",\"type\":\"bytes[]\"}],\"name\":\"proveWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"provenWithdrawals\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2OutputIndex\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x6101406040523480156200001257600080fd5b506040516200376f3803806200376f833981016040819052620000359162000296565b60006080819052600160a05260c0526001600160a01b0380851660e052838116610100528116610120526200006a8262000074565b5050505062000302565b600054610100900460ff1615808015620000955750600054600160ff909116105b80620000c55750620000b230620001cb60201b62001af91760201c565b158015620000c5575060005460ff166001145b6200012e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000152576000805461ff0019166101001790555b603280546001600160a01b03191661dead1790556035805483151560ff1990911617905562000180620001da565b8015620001c7576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620002475760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000125565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b6001600160a01b03811681146200029357600080fd5b50565b60008060008060808587031215620002ad57600080fd5b8451620002ba816200027d565b6020860151909450620002cd816200027d565b60408601519093508015158114620002e457600080fd5b6060860151909250620002f7816200027d565b939692955090935050565b60805160a05160c05160e05161010051610120516133de62000391600039600081816102af0152610bfa01526000818161038c01528181610dd9015261105c0152600081816101c1015281816108ed01528181610ab401528181610fb80152818161130901528181611547015261203801526000610f2301526000610efa01526000610ed101526133de6000f3fe6080604052600436106101835760003560e01c8063724c184c116100d6578063ca3e99ba1161007f578063d53a822f11610059578063d53a822f14610523578063e965084c14610543578063e9e05c42146105cf57600080fd5b8063ca3e99ba14610458578063cd7c97891461046d578063cff0ab961461048257600080fd5b80638c3152e9116100b05780638c3152e9146103db5780639bf62d82146103fb578063a14238e71461042857600080fd5b8063724c184c1461037a5780638456cb59146103ae578063867ead13146103c357600080fd5b80635865b6071161013857806364b792081161011257806364b792081461032d5780636bb0291e146103455780636dbffb781461035a57600080fd5b80635865b6071461029d5780635c1f2827146102d15780635c975abb1461030357600080fd5b806313620abd1161016957806313620abd1461022d5780633f4ba83a1461026657806354fd4d501461027b57600080fd5b80621c2ff6146101af5780630757b2441461020d57600080fd5b366101aa576101a83334620186a06000604051806020016040528060008152506105dd565b005b600080fd5b3480156101bb57600080fd5b506101e37f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021957600080fd5b506101a8610228366004612a2b565b6107c3565b34801561023957600080fd5b50610245633b9aca0081565b6040516fffffffffffffffffffffffffffffffff9091168152602001610204565b34801561027257600080fd5b506101a8610dc1565b34801561028757600080fd5b50610290610eca565b6040516102049190612b82565b3480156102a957600080fd5b506101e37f000000000000000000000000000000000000000000000000000000000000000081565b3480156102dd57600080fd5b506102f56fffffffffffffffffffffffffffffffff81565b604051908152602001610204565b34801561030f57600080fd5b5060355461031d9060ff1681565b6040519015158152602001610204565b34801561033957600080fd5b506102f56301312d0081565b34801561035157600080fd5b506102f5600a81565b34801561036657600080fd5b5061031d610375366004612b95565b610f6d565b34801561038657600080fd5b506101e37f000000000000000000000000000000000000000000000000000000000000000081565b3480156103ba57600080fd5b506101a8611044565b3480156103cf57600080fd5b506102f5633b9aca0081565b3480156103e757600080fd5b506101a86103f6366004612bae565b611149565b34801561040757600080fd5b506032546101e39073ffffffffffffffffffffffffffffffffffffffff1681565b34801561043457600080fd5b5061031d610443366004612b95565b60336020526000908152604090205460ff1681565b34801561046457600080fd5b506102f5611914565b34801561047957600080fd5b506102f5600881565b34801561048e57600080fd5b506001546104ea906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff9283166020850152911690820152606001610204565b34801561052f57600080fd5b506101a861053e366004612bf4565b611926565b34801561054f57600080fd5b506105a161055e366004612b95565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff9283166020850152911690820152606001610204565b6101a86105dd366004612c11565b8260005a905083156106785773ffffffffffffffffffffffffffffffffffffffff8716156106785760405162461bcd60e51b815260206004820152603d60248201527f4b726f6d61506f7274616c3a206d7573742073656e6420746f2061646472657360448201527f73283029207768656e206372656174696e67206120636f6e747261637400000060648201526084015b60405180910390fd5b6152088567ffffffffffffffff1610156106fa5760405162461bcd60e51b815260206004820152603560248201527f4b726f6d61506f7274616c3a20676173206c696d6974206d75737420636f766560448201527f7220696e737472696e7369632067617320636f73740000000000000000000000606482015260840161066f565b3332811461071b575033731111000000000000000000000000000000001111015b60003488888888604051602001610736959493929190612c99565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516107a69190612b82565b60405180910390a450506107ba8282611b15565b50505050505050565b60355460ff16156108165760405162461bcd60e51b815260206004820152601360248201527f4b726f6d61506f7274616c3a2070617573656400000000000000000000000000604482015260640161066f565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036108bb5760405162461bcd60e51b815260206004820152603c60248201527f4b726f6d61506f7274616c3a20796f752063616e6e6f742073656e64206d657360448201527f736167657320746f2074686520706f7274616c20636f6e747261637400000000606482015260840161066f565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610949573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096d9190612d1e565b51905061098761098236869003860186612d83565b611df4565b81146109fb5760405162461bcd60e51b815260206004820152602660248201527f4b726f6d61506f7274616c3a20696e76616c6964206f757470757420726f6f7460448201527f2070726f6f660000000000000000000000000000000000000000000000000000606482015260840161066f565b6000610a0687611eaa565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610b385750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610b10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b349190612d1e565b5114155b610baa5760405162461bcd60e51b815260206004820152603460248201527f4b726f6d61506f7274616c3a207769746864726177616c20686173682068617360448201527f20616c7265616479206265656e2070726f76656e000000000000000000000000606482015260840161066f565b60408051602080820185905260008284015282518083038401815260608301808552815191909201207f12e64a7200000000000000000000000000000000000000000000000000000000909152917f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16916312e64a7291610c4c9185918b918b918e013590606401612e3c565b602060405180830381865afa158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d9190612f3d565b610cff5760405162461bcd60e51b815260206004820152602f60248201527f4b726f6d61506f7274616c3a20696e76616c6964207769746864726177616c2060448201527f696e636c7573696f6e2070726f6f660000000000000000000000000000000000606482015260840161066f565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e6c5760405162461bcd60e51b815260206004820152602660248201527f4b726f6d61506f7274616c3a206f6e6c7920677561726469616e2063616e207560448201527f6e70617573650000000000000000000000000000000000000000000000000000606482015260840161066f565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6060610ef57f0000000000000000000000000000000000000000000000000000000000000000611ef7565b610f1e7f0000000000000000000000000000000000000000000000000000000000000000611ef7565b610f477f0000000000000000000000000000000000000000000000000000000000000000611ef7565b604051602001610f5993929190612f5a565b604051602081830303815290604052905090565b6040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810182905260009061103e9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015610fff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110239190612d1e565b602001516fffffffffffffffffffffffffffffffff16612034565b92915050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146110ee5760405162461bcd60e51b8152602060048201526024808201527f4b726f6d61506f7274616c3a206f6e6c7920677561726469616e2063616e207060448201527f6175736500000000000000000000000000000000000000000000000000000000606482015260840161066f565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610ec0565b60355460ff161561119c5760405162461bcd60e51b815260206004820152601360248201527f4b726f6d61506f7274616c3a2070617573656400000000000000000000000000604482015260640161066f565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461122b5760405162461bcd60e51b815260206004820152603c60248201527f4b726f6d61506f7274616c3a2063616e206f6e6c792074726967676572206f6e60448201527f65207769746864726177616c20706572207472616e73616374696f6e00000000606482015260840161066f565b600061123682611eaa565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036113075760405162461bcd60e51b815260206004820152602f60248201527f4b726f6d61506f7274616c3a207769746864726177616c20686173206e6f742060448201527f6265656e2070726f76656e207965740000000000000000000000000000000000606482015260840161066f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611372573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113969190612fd0565b81602001516fffffffffffffffffffffffffffffffff1610156114475760405162461bcd60e51b815260206004820152604860248201527f4b726f6d61506f7274616c3a207769746864726177616c2074696d657374616d60448201527f70206c657373207468616e204c32204f7261636c65207374617274696e67207460648201527f696d657374616d70000000000000000000000000000000000000000000000000608482015260a40161066f565b61146681602001516fffffffffffffffffffffffffffffffff16612034565b6114fe5760405162461bcd60e51b815260206004820152604260248201527f4b726f6d61506f7274616c3a2070726f76656e207769746864726177616c206660448201527f696e616c697a6174696f6e20706572696f6420686173206e6f7420656c61707360648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a40161066f565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c79190612d1e565b82518151919250146116675760405162461bcd60e51b815260206004820152604660248201527f4b726f6d61506f7274616c3a206f757470757420726f6f742070726f76656e2060448201527f6973206e6f74207468652073616d652061732063757272656e74206f7574707560648201527f7420726f6f740000000000000000000000000000000000000000000000000000608482015260a40161066f565b61168681602001516fffffffffffffffffffffffffffffffff16612034565b61171e5760405162461bcd60e51b815260206004820152604260248201527f4b726f6d61506f7274616c3a20636865636b706f696e74206f7574707574206660448201527f696e616c697a6174696f6e20706572696f6420686173206e6f7420656c61707360648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a40161066f565b60008381526033602052604090205460ff16156117a35760405162461bcd60e51b815260206004820152603260248201527f4b726f6d61506f7274616c3a207769746864726177616c2068617320616c726560448201527f616479206265656e2066696e616c697a65640000000000000000000000000000606482015260840161066f565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a0880151611845939291906120d7565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906118aa90841515815260200190565b60405180910390a2801580156118c05750326001145b1561190d5760405162461bcd60e51b815260206004820152601e60248201527f4b726f6d61506f7274616c3a207769746864726177616c206661696c65640000604482015260640161066f565b5050505050565b611923600a6301312d00613047565b81565b600054610100900460ff16158080156119465750600054600160ff909116105b806119605750303b158015611960575060005460ff166001145b6119d25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161066f565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611a3057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055603580548315157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116179055611a92612131565b8015611af557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611b4b907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436130af565b90508015611c83576000611b64600a6301312d00613047565b600154611b8f9190700100000000000000000000000000000000900467ffffffffffffffff166130c6565b905060006008611ba4600a6301312d00613047565b611bae919061313a565b600154611bce9084906fffffffffffffffffffffffffffffffff1661313a565b611bd89190613047565b600154909150600090611c1d90611c029084906fffffffffffffffffffffffffffffffff166131f6565b633b9aca006fffffffffffffffffffffffffffffffff6121fa565b90506001841115611c4457611c41611c02826008611c3c6001896130af565b61220f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054849190601090611cb6908490700100000000000000000000000000000000900467ffffffffffffffff1661326a565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506301312d00600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611d795760405162461bcd60e51b815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d69740000606482015260840161066f565b600154600090611da5906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8616613296565b90506000611db748633b9aca00612264565b611dc190836132d3565b905060005a611dd090866130af565b905080821115611dec57611dec611de782846130af565b61227d565b505050505050565b8051600090611e065761103e826122ab565b81517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611e375761103e826122ea565b60405162461bcd60e51b815260206004820152602a60248201527f48617368696e673a20756e6b6e6f776e206f757470757420726f6f742070726f60448201527f6f662076657273696f6e00000000000000000000000000000000000000000000606482015260840161066f565b919050565b80516020808301516040808501516060860151608087015160a08801519351600097611eda9790969591016132e7565b604051602081830303815290604052805190602001209050919050565b606081600003611f3a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611f645780611f4e8161333e565b9150611f5d9050600a836132d3565b9150611f3e565b60008167ffffffffffffffff811115611f7f57611f7f612888565b6040519080825280601f01601f191660200182016040528015611fa9576020820181803683370190505b5090505b841561202c57611fbe6001836130af565b9150611fcb600a86613376565b611fd690603061338a565b60f81b818381518110611feb57611feb6133a2565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612025600a866132d3565b9450611fad565b949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c59190612fd0565b6120cf908361338a565b421192915050565b600080603f60c88601604002045a101561211a576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080845160208601878a5af19695505050505050565b600054610100900460ff166121ae5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161066f565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b600061202c612209858561232d565b8361233d565b6000670de0b6b3a76400006122506122278583613047565b61223990670de0b6b3a76400006130c6565b61224b85670de0b6b3a764000061313a565b61234c565b61225a908661313a565b61202c9190613047565b6000818310156122745781612276565b825b9392505050565b6000805a90505b825a61229090836130af565b10156122a65761229f8261333e565b9150612284565b505050565b60008160000151826020015183604001518460600151604051602001611eda949392919093845260208401929092526040830152606082015260800190565b80516020808301516040808501516060808701516080808901518551978801989098529386019490945284015282015260a081019190915260009060c001611eda565b6000818312156122745781612276565b60008183126122745781612276565b6000612276670de0b6b3a7640000836123648661237d565b61236e919061313a565b6123789190613047565b6125a7565b60008082136123ce5760405162461bcd60e51b815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161066f565b600060606123db846127cc565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136125d857506000919050565b680755bf798b4a1bf1e582126126305760405162461bcd60e51b815260206004820152600c60248201527f4558505f4f564552464c4f570000000000000000000000000000000000000000604482015260640161066f565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080821161281d5760405162461bcd60e51b815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161066f565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114611ea557600080fd5b600082601f8301126128ec57600080fd5b813567ffffffffffffffff8082111561290757612907612888565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561294d5761294d612888565b8160405283815286602085880101111561296657600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060c0828403121561299857600080fd5b60405160c0810167ffffffffffffffff82821081831117156129bc576129bc612888565b81604052829350843583526129d3602086016128b7565b60208401526129e4604086016128b7565b6040840152606085013560608401526080850135608084015260a0850135915080821115612a1157600080fd5b50612a1e858286016128db565b60a0830152505092915050565b6000806000806000858703610100811215612a4557600080fd5b863567ffffffffffffffff80821115612a5d57600080fd5b612a698a838b01612986565b97506020890135965060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215612aa257600080fd5b60408901955060e0890135925080831115612abc57600080fd5b828901925089601f840112612ad057600080fd5b8235915080821115612ae157600080fd5b508860208260051b8401011115612af757600080fd5b959894975092955050506020019190565b60005b83811015612b23578181015183820152602001612b0b565b83811115612b32576000848401525b50505050565b60008151808452612b50816020860160208601612b08565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122766020830184612b38565b600060208284031215612ba757600080fd5b5035919050565b600060208284031215612bc057600080fd5b813567ffffffffffffffff811115612bd757600080fd5b61202c84828501612986565b8015158114612bf157600080fd5b50565b600060208284031215612c0657600080fd5b813561227681612be3565b600080600080600060a08688031215612c2957600080fd5b612c32866128b7565b945060208601359350604086013567ffffffffffffffff8082168214612c5757600080fd5b909350606087013590612c6982612be3565b90925060808701359080821115612c7f57600080fd5b50612c8c888289016128db565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251612ced816049850160208701612b08565b919091016049019695505050505050565b80516fffffffffffffffffffffffffffffffff81168114611ea557600080fd5b600060608284031215612d3057600080fd5b6040516060810181811067ffffffffffffffff82111715612d5357612d53612888565b60405282518152612d6660208401612cfe565b6020820152612d7760408401612cfe565b60408201529392505050565b600060a08284031215612d9557600080fd5b60405160a0810181811067ffffffffffffffff82111715612db857612db8612888565b806040525082358152602083013560208201526040830135604082015260608301356060820152608083013560808201528091505092915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8481526000602060808184015280608084015260018060a085015260c0840160c060408601528087825260e08601905060e08860051b87010191508860005b89811015612f25577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2088850301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18c3603018112612edc57600080fd5b8b01868101903567ffffffffffffffff811115612ef857600080fd5b803603821315612f0757600080fd5b612f12868284612df3565b9550505091850191908501908401612e7b565b50505080935050505082606083015295945050505050565b600060208284031215612f4f57600080fd5b815161227681612be3565b60008451612f6c818460208901612b08565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612fa8816001850160208a01612b08565b60019201918201528351612fc3816002840160208801612b08565b0160020195945050505050565b600060208284031215612fe257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008261305657613056612fe9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156130aa576130aa613018565b500590565b6000828210156130c1576130c1613018565b500390565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561310057613100613018565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561313457613134613018565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561317b5761317b613018565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156131b6576131b6613018565b600087129250878205871284841616156131d2576131d2613018565b878505871281841616156131e8576131e8613018565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561323057613230613018565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561326457613264613018565b50500190565b600067ffffffffffffffff80831681851680830382111561328d5761328d613018565b01949350505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156132ce576132ce613018565b500290565b6000826132e2576132e2612fe9565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261333260c0830184612b38565b98975050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361336f5761336f613018565b5060010190565b60008261338557613385612fe9565b500690565b6000821982111561339d5761339d613018565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_guardian\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_paused\",\"type\":\"bool\"},{\"internalType\":\"contractSystemConfig\",\"name\":\"_config\",\"type\":\"address\"},{\"internalType\":\"contractZKMerkleTrie\",\"name\":\"_zkMerkleTrie\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"opaqueData\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"WithdrawalProven\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"GUARDIAN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SYSTEM_CONFIG\",\"outputs\":[{\"internalType\":\"contractSystemConfig\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ZK_MERKLE_TRIE\",\"outputs\":[{\"internalType\":\"contractZKMerkleTrie\",\"name\":\"\",\"type\":\"address\"}],\"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\":[{\"components\":[{\"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\":\"structTypes.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_paused\",\"type\":\"bool\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"name\":\"isOutputFinalized\",\"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\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"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\":\"structTypes.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"nextBlockHash\",\"type\":\"bytes32\"}],\"internalType\":\"structTypes.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"_withdrawalProof\",\"type\":\"bytes[]\"}],\"name\":\"proveWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"provenWithdrawals\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2OutputIndex\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x6101606040523480156200001257600080fd5b506040516200383a3803806200383a83398101604081905262000035916200029e565b60006080819052600160a05260c0526001600160a01b0380861660e052848116610120528281166101005281166101405262000071836200007c565b505050505062000322565b600054610100900460ff16158080156200009d5750600054600160ff909116105b80620000cd5750620000ba30620001d360201b620019d41760201c565b158015620000cd575060005460ff166001145b620001365760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200015a576000805461ff0019166101001790555b603280546001600160a01b03191661dead1790556035805483151560ff1990911617905562000188620001e2565b8015620001cf576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff166200024f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200012d565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b6001600160a01b03811681146200029b57600080fd5b50565b600080600080600060a08688031215620002b757600080fd5b8551620002c48162000285565b6020870151909550620002d78162000285565b60408701519094508015158114620002ee57600080fd5b6060870151909350620003018162000285565b6080870151909250620003148162000285565b809150509295509295909350565b60805160a05160c05160e051610100516101205161014051613477620003c3600039600081816102040152610ae701526000818161028201528181610cc60152610f490152600081816104a8015261213d01526000818161014f015281816107da015281816109a101528181610ea5015281816111f6015281816114340152611f4701526000610e1001526000610de701526000610dbe01526134776000f3fe6080604052600436106101115760003560e01c80638456cb59116100a5578063cff0ab9611610074578063e965084c11610059578063e965084c146103f7578063e9e05c4214610483578063f04987501461049657600080fd5b8063cff0ab9614610336578063d53a822f146103d757600080fd5b80638456cb59146102a45780638c3152e9146102b95780639bf62d82146102d9578063a14238e71461030657600080fd5b80635865b607116100e15780635865b607146101f25780635c975abb146102265780636dbffb7814610250578063724c184c1461027057600080fd5b80621c2ff61461013d5780630757b2441461019b5780633f4ba83a146101bb57806354fd4d50146101d057600080fd5b36610138576101363334620186a06000604051806020016040528060008152506104ca565b005b600080fd5b34801561014957600080fd5b506101717f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101a757600080fd5b506101366101b6366004612a00565b6106b0565b3480156101c757600080fd5b50610136610cae565b3480156101dc57600080fd5b506101e5610db7565b6040516101929190612b57565b3480156101fe57600080fd5b506101717f000000000000000000000000000000000000000000000000000000000000000081565b34801561023257600080fd5b506035546102409060ff1681565b6040519015158152602001610192565b34801561025c57600080fd5b5061024061026b366004612b6a565b610e5a565b34801561027c57600080fd5b506101717f000000000000000000000000000000000000000000000000000000000000000081565b3480156102b057600080fd5b50610136610f31565b3480156102c557600080fd5b506101366102d4366004612b83565b611036565b3480156102e557600080fd5b506032546101719073ffffffffffffffffffffffffffffffffffffffff1681565b34801561031257600080fd5b50610240610321366004612b6a565b60336020526000908152604090205460ff1681565b34801561034257600080fd5b5060015461039e906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff9283166020850152911690820152606001610192565b3480156103e357600080fd5b506101366103f2366004612bc9565b611801565b34801561040357600080fd5b50610455610412366004612b6a565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff9283166020850152911690820152606001610192565b610136610491366004612be6565b6104ca565b3480156104a257600080fd5b506101717f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156105655773ffffffffffffffffffffffffffffffffffffffff8716156105655760405162461bcd60e51b815260206004820152603d60248201527f4b726f6d61506f7274616c3a206d7573742073656e6420746f2061646472657360448201527f73283029207768656e206372656174696e67206120636f6e747261637400000060648201526084015b60405180910390fd5b6152088567ffffffffffffffff1610156105e75760405162461bcd60e51b815260206004820152603560248201527f4b726f6d61506f7274616c3a20676173206c696d6974206d75737420636f766560448201527f7220696e737472696e7369632067617320636f73740000000000000000000000606482015260840161055c565b33328114610608575033731111000000000000000000000000000000001111015b60003488888888604051602001610623959493929190612c6e565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516106939190612b57565b60405180910390a450506106a782826119f0565b50505050505050565b60355460ff16156107035760405162461bcd60e51b815260206004820152601360248201527f4b726f6d61506f7274616c3a2070617573656400000000000000000000000000604482015260640161055c565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036107a85760405162461bcd60e51b815260206004820152603c60248201527f4b726f6d61506f7274616c3a20796f752063616e6e6f742073656e64206d657360448201527f736167657320746f2074686520706f7274616c20636f6e747261637400000000606482015260840161055c565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610836573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085a9190612cf3565b51905061087461086f36869003860186612d58565b611d03565b81146108e85760405162461bcd60e51b815260206004820152602660248201527f4b726f6d61506f7274616c3a20696e76616c6964206f757470757420726f6f7460448201527f2070726f6f660000000000000000000000000000000000000000000000000000606482015260840161055c565b60006108f387611db9565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610a255750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156109fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a219190612cf3565b5114155b610a975760405162461bcd60e51b815260206004820152603460248201527f4b726f6d61506f7274616c3a207769746864726177616c20686173682068617360448201527f20616c7265616479206265656e2070726f76656e000000000000000000000000606482015260840161055c565b60408051602080820185905260008284015282518083038401815260608301808552815191909201207f12e64a7200000000000000000000000000000000000000000000000000000000909152917f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16916312e64a7291610b399185918b918b918e013590606401612e11565b602060405180830381865afa158015610b56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7a9190612f12565b610bec5760405162461bcd60e51b815260206004820152602f60248201527f4b726f6d61506f7274616c3a20696e76616c6964207769746864726177616c2060448201527f696e636c7573696f6e2070726f6f660000000000000000000000000000000000606482015260840161055c565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610d595760405162461bcd60e51b815260206004820152602660248201527f4b726f6d61506f7274616c3a206f6e6c7920677561726469616e2063616e207560448201527f6e70617573650000000000000000000000000000000000000000000000000000606482015260840161055c565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6060610de27f0000000000000000000000000000000000000000000000000000000000000000611e06565b610e0b7f0000000000000000000000000000000000000000000000000000000000000000611e06565b610e347f0000000000000000000000000000000000000000000000000000000000000000611e06565b604051602001610e4693929190612f2f565b604051602081830303815290604052905090565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090610f2b9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015610eec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f109190612cf3565b602001516fffffffffffffffffffffffffffffffff16611f43565b92915050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610fdb5760405162461bcd60e51b8152602060048201526024808201527f4b726f6d61506f7274616c3a206f6e6c7920677561726469616e2063616e207060448201527f6175736500000000000000000000000000000000000000000000000000000000606482015260840161055c565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610dad565b60355460ff16156110895760405162461bcd60e51b815260206004820152601360248201527f4b726f6d61506f7274616c3a2070617573656400000000000000000000000000604482015260640161055c565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146111185760405162461bcd60e51b815260206004820152603c60248201527f4b726f6d61506f7274616c3a2063616e206f6e6c792074726967676572206f6e60448201527f65207769746864726177616c20706572207472616e73616374696f6e00000000606482015260840161055c565b600061112382611db9565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036111f45760405162461bcd60e51b815260206004820152602f60248201527f4b726f6d61506f7274616c3a207769746864726177616c20686173206e6f742060448201527f6265656e2070726f76656e207965740000000000000000000000000000000000606482015260840161055c565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa15801561125f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112839190612fa5565b81602001516fffffffffffffffffffffffffffffffff1610156113345760405162461bcd60e51b815260206004820152604860248201527f4b726f6d61506f7274616c3a207769746864726177616c2074696d657374616d60448201527f70206c657373207468616e204c32204f7261636c65207374617274696e67207460648201527f696d657374616d70000000000000000000000000000000000000000000000000608482015260a40161055c565b61135381602001516fffffffffffffffffffffffffffffffff16611f43565b6113eb5760405162461bcd60e51b815260206004820152604260248201527f4b726f6d61506f7274616c3a2070726f76656e207769746864726177616c206660448201527f696e616c697a6174696f6e20706572696f6420686173206e6f7420656c61707360648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a40161055c565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015611490573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b49190612cf3565b82518151919250146115545760405162461bcd60e51b815260206004820152604660248201527f4b726f6d61506f7274616c3a206f757470757420726f6f742070726f76656e2060448201527f6973206e6f74207468652073616d652061732063757272656e74206f7574707560648201527f7420726f6f740000000000000000000000000000000000000000000000000000608482015260a40161055c565b61157381602001516fffffffffffffffffffffffffffffffff16611f43565b61160b5760405162461bcd60e51b815260206004820152604260248201527f4b726f6d61506f7274616c3a20636865636b706f696e74206f7574707574206660448201527f696e616c697a6174696f6e20706572696f6420686173206e6f7420656c61707360648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a40161055c565b60008381526033602052604090205460ff16156116905760405162461bcd60e51b815260206004820152603260248201527f4b726f6d61506f7274616c3a207769746864726177616c2068617320616c726560448201527f616479206265656e2066696e616c697a65640000000000000000000000000000606482015260840161055c565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a088015161173293929190611fe6565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061179790841515815260200190565b60405180910390a2801580156117ad5750326001145b156117fa5760405162461bcd60e51b815260206004820152601e60248201527f4b726f6d61506f7274616c3a207769746864726177616c206661696c65640000604482015260640161055c565b5050505050565b600054610100900460ff16158080156118215750600054600160ff909116105b8061183b5750303b15801561183b575060005460ff166001145b6118ad5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161055c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561190b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055603580548315157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617905561196d612040565b80156119d057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611a26907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643612fed565b90506000611a32612109565b90506000816020015160ff16826000015163ffffffff16611a539190613033565b90508215611b8a57600154600090611a8a908390700100000000000000000000000000000000900467ffffffffffffffff1661309b565b90506000836040015160ff1683611aa1919061310f565b600154611ac19084906fffffffffffffffffffffffffffffffff1661310f565b611acb9190613033565b600154909150600090611b1c90611af59084906fffffffffffffffffffffffffffffffff166131cb565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff166121cf565b90506001861115611b4b57611b48611af582876040015160ff1660018a611b439190612fed565b6121e4565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611bbd908490700100000000000000000000000000000000900467ffffffffffffffff1661323f565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611c865760405162461bcd60e51b815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d69740000606482015260840161055c565b600154600090611cb2906fffffffffffffffffffffffffffffffff1667ffffffffffffffff881661326b565b90506000611cc448633b9aca00612239565b611cce90836132a8565b905060005a611cdd9088612fed565b905080821115611cf957611cf9611cf48284612fed565b612252565b5050505050505050565b8051600090611d1557610f2b82612280565b81517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611d4657610f2b826122bf565b60405162461bcd60e51b815260206004820152602a60248201527f48617368696e673a20756e6b6e6f776e206f757470757420726f6f742070726f60448201527f6f662076657273696f6e00000000000000000000000000000000000000000000606482015260840161055c565b919050565b80516020808301516040808501516060860151608087015160a08801519351600097611de99790969591016132bc565b604051602081830303815290604052805190602001209050919050565b606081600003611e4957505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611e735780611e5d81613313565b9150611e6c9050600a836132a8565b9150611e4d565b60008167ffffffffffffffff811115611e8e57611e8e61285d565b6040519080825280601f01601f191660200182016040528015611eb8576020820181803683370190505b5090505b8415611f3b57611ecd600183612fed565b9150611eda600a8661334b565b611ee590603061335f565b60f81b818381518110611efa57611efa613377565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611f34600a866132a8565b9450611ebc565b949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd49190612fa5565b611fde908361335f565b421192915050565b600080603f60c88601604002045a1015612029576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080845160208601878a5af19695505050505050565b600054610100900460ff166120bd5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161055c565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca91906133cb565b905090565b6000611f3b6121de8585612302565b83612312565b6000670de0b6b3a76400006122256121fc8583613033565b61220e90670de0b6b3a764000061309b565b61222085670de0b6b3a764000061310f565b612321565b61222f908661310f565b611f3b9190613033565b600081831015612249578161224b565b825b9392505050565b6000805a90505b825a6122659083612fed565b101561227b5761227482613313565b9150612259565b505050565b60008160000151826020015183604001518460600151604051602001611de9949392919093845260208401929092526040830152606082015260800190565b80516020808301516040808501516060808701516080808901518551978801989098529386019490945284015282015260a081019190915260009060c001611de9565b600081831215612249578161224b565b6000818312612249578161224b565b600061224b670de0b6b3a76400008361233986612352565b612343919061310f565b61234d9190613033565b61257c565b60008082136123a35760405162461bcd60e51b815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161055c565b600060606123b0846127a1565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136125ad57506000919050565b680755bf798b4a1bf1e582126126055760405162461bcd60e51b815260206004820152600c60248201527f4558505f4f564552464c4f570000000000000000000000000000000000000000604482015260640161055c565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b60008082116127f25760405162461bcd60e51b815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161055c565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114611db457600080fd5b600082601f8301126128c157600080fd5b813567ffffffffffffffff808211156128dc576128dc61285d565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156129225761292261285d565b8160405283815286602085880101111561293b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060c0828403121561296d57600080fd5b60405160c0810167ffffffffffffffff82821081831117156129915761299161285d565b81604052829350843583526129a86020860161288c565b60208401526129b96040860161288c565b6040840152606085013560608401526080850135608084015260a08501359150808211156129e657600080fd5b506129f3858286016128b0565b60a0830152505092915050565b6000806000806000858703610100811215612a1a57600080fd5b863567ffffffffffffffff80821115612a3257600080fd5b612a3e8a838b0161295b565b97506020890135965060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215612a7757600080fd5b60408901955060e0890135925080831115612a9157600080fd5b828901925089601f840112612aa557600080fd5b8235915080821115612ab657600080fd5b508860208260051b8401011115612acc57600080fd5b959894975092955050506020019190565b60005b83811015612af8578181015183820152602001612ae0565b83811115612b07576000848401525b50505050565b60008151808452612b25816020860160208601612add565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061224b6020830184612b0d565b600060208284031215612b7c57600080fd5b5035919050565b600060208284031215612b9557600080fd5b813567ffffffffffffffff811115612bac57600080fd5b611f3b8482850161295b565b8015158114612bc657600080fd5b50565b600060208284031215612bdb57600080fd5b813561224b81612bb8565b600080600080600060a08688031215612bfe57600080fd5b612c078661288c565b945060208601359350604086013567ffffffffffffffff8082168214612c2c57600080fd5b909350606087013590612c3e82612bb8565b90925060808701359080821115612c5457600080fd5b50612c61888289016128b0565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251612cc2816049850160208701612add565b919091016049019695505050505050565b80516fffffffffffffffffffffffffffffffff81168114611db457600080fd5b600060608284031215612d0557600080fd5b6040516060810181811067ffffffffffffffff82111715612d2857612d2861285d565b60405282518152612d3b60208401612cd3565b6020820152612d4c60408401612cd3565b60408201529392505050565b600060a08284031215612d6a57600080fd5b60405160a0810181811067ffffffffffffffff82111715612d8d57612d8d61285d565b806040525082358152602083013560208201526040830135604082015260608301356060820152608083013560808201528091505092915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8481526000602060808184015280608084015260018060a085015260c0840160c060408601528087825260e08601905060e08860051b87010191508860005b89811015612efa577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2088850301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18c3603018112612eb157600080fd5b8b01868101903567ffffffffffffffff811115612ecd57600080fd5b803603821315612edc57600080fd5b612ee7868284612dc8565b9550505091850191908501908401612e50565b50505080935050505082606083015295945050505050565b600060208284031215612f2457600080fd5b815161224b81612bb8565b60008451612f41818460208901612add565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612f7d816001850160208a01612add565b60019201918201528351612f98816002840160208801612add565b0160020195945050505050565b600060208284031215612fb757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612fff57612fff612fbe565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261304257613042613004565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561309657613096612fbe565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156130d5576130d5612fbe565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561310957613109612fbe565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561315057613150612fbe565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561318b5761318b612fbe565b600087129250878205871284841616156131a7576131a7612fbe565b878505871281841616156131bd576131bd612fbe565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561320557613205612fbe565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561323957613239612fbe565b50500190565b600067ffffffffffffffff80831681851680830382111561326257613262612fbe565b01949350505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156132a3576132a3612fbe565b500290565b6000826132b7576132b7613004565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261330760c0830184612b0d565b98975050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361334457613344612fbe565b5060010190565b60008261335a5761335a613004565b500690565b6000821982111561337257613372612fbe565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805163ffffffff81168114611db457600080fd5b805160ff81168114611db457600080fd5b600060c082840312156133dd57600080fd5b60405160c0810181811067ffffffffffffffff821117156134005761340061285d565b60405261340c836133a6565b815261341a602084016133ba565b602082015261342b604084016133ba565b604082015261343c606084016133a6565b606082015261344d608084016133a6565b608082015261345e60a08401612cd3565b60a0820152939250505056fea164736f6c634300080f000a", } // KromaPortalABI is the input ABI used to generate the binding from. @@ -44,7 +44,7 @@ var KromaPortalABI = KromaPortalMetaData.ABI var KromaPortalBin = KromaPortalMetaData.Bin // DeployKromaPortal deploys a new Ethereum contract, binding an instance of KromaPortal to it. -func DeployKromaPortal(auth *bind.TransactOpts, backend bind.ContractBackend, _l2Oracle common.Address, _guardian common.Address, _paused bool, _zkMerkleTrie common.Address) (common.Address, *types.Transaction, *KromaPortal, error) { +func DeployKromaPortal(auth *bind.TransactOpts, backend bind.ContractBackend, _l2Oracle common.Address, _guardian common.Address, _paused bool, _config common.Address, _zkMerkleTrie common.Address) (common.Address, *types.Transaction, *KromaPortal, error) { parsed, err := KromaPortalMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -53,7 +53,7 @@ func DeployKromaPortal(auth *bind.TransactOpts, backend bind.ContractBackend, _l return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(KromaPortalBin), backend, _l2Oracle, _guardian, _paused, _zkMerkleTrie) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(KromaPortalBin), backend, _l2Oracle, _guardian, _paused, _config, _zkMerkleTrie) if err != nil { return common.Address{}, nil, nil, err } @@ -202,68 +202,6 @@ func (_KromaPortal *KromaPortalTransactorRaw) Transact(opts *bind.TransactOpts, return _KromaPortal.Contract.contract.Transact(opts, method, params...) } -// BASEFEEMAXCHANGEDENOMINATOR is a free data retrieval call binding the contract method 0xcd7c9789. -// -// Solidity: function BASE_FEE_MAX_CHANGE_DENOMINATOR() view returns(int256) -func (_KromaPortal *KromaPortalCaller) BASEFEEMAXCHANGEDENOMINATOR(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _KromaPortal.contract.Call(opts, &out, "BASE_FEE_MAX_CHANGE_DENOMINATOR") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// BASEFEEMAXCHANGEDENOMINATOR is a free data retrieval call binding the contract method 0xcd7c9789. -// -// Solidity: function BASE_FEE_MAX_CHANGE_DENOMINATOR() view returns(int256) -func (_KromaPortal *KromaPortalSession) BASEFEEMAXCHANGEDENOMINATOR() (*big.Int, error) { - return _KromaPortal.Contract.BASEFEEMAXCHANGEDENOMINATOR(&_KromaPortal.CallOpts) -} - -// BASEFEEMAXCHANGEDENOMINATOR is a free data retrieval call binding the contract method 0xcd7c9789. -// -// Solidity: function BASE_FEE_MAX_CHANGE_DENOMINATOR() view returns(int256) -func (_KromaPortal *KromaPortalCallerSession) BASEFEEMAXCHANGEDENOMINATOR() (*big.Int, error) { - return _KromaPortal.Contract.BASEFEEMAXCHANGEDENOMINATOR(&_KromaPortal.CallOpts) -} - -// ELASTICITYMULTIPLIER is a free data retrieval call binding the contract method 0x6bb0291e. -// -// Solidity: function ELASTICITY_MULTIPLIER() view returns(int256) -func (_KromaPortal *KromaPortalCaller) ELASTICITYMULTIPLIER(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _KromaPortal.contract.Call(opts, &out, "ELASTICITY_MULTIPLIER") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// ELASTICITYMULTIPLIER is a free data retrieval call binding the contract method 0x6bb0291e. -// -// Solidity: function ELASTICITY_MULTIPLIER() view returns(int256) -func (_KromaPortal *KromaPortalSession) ELASTICITYMULTIPLIER() (*big.Int, error) { - return _KromaPortal.Contract.ELASTICITYMULTIPLIER(&_KromaPortal.CallOpts) -} - -// ELASTICITYMULTIPLIER is a free data retrieval call binding the contract method 0x6bb0291e. -// -// Solidity: function ELASTICITY_MULTIPLIER() view returns(int256) -func (_KromaPortal *KromaPortalCallerSession) ELASTICITYMULTIPLIER() (*big.Int, error) { - return _KromaPortal.Contract.ELASTICITYMULTIPLIER(&_KromaPortal.CallOpts) -} - // GUARDIAN is a free data retrieval call binding the contract method 0x724c184c. // // Solidity: function GUARDIAN() view returns(address) @@ -295,37 +233,6 @@ func (_KromaPortal *KromaPortalCallerSession) GUARDIAN() (common.Address, error) return _KromaPortal.Contract.GUARDIAN(&_KromaPortal.CallOpts) } -// INITIALBASEFEE is a free data retrieval call binding the contract method 0x13620abd. -// -// Solidity: function INITIAL_BASE_FEE() view returns(uint128) -func (_KromaPortal *KromaPortalCaller) INITIALBASEFEE(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _KromaPortal.contract.Call(opts, &out, "INITIAL_BASE_FEE") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// INITIALBASEFEE is a free data retrieval call binding the contract method 0x13620abd. -// -// Solidity: function INITIAL_BASE_FEE() view returns(uint128) -func (_KromaPortal *KromaPortalSession) INITIALBASEFEE() (*big.Int, error) { - return _KromaPortal.Contract.INITIALBASEFEE(&_KromaPortal.CallOpts) -} - -// INITIALBASEFEE is a free data retrieval call binding the contract method 0x13620abd. -// -// Solidity: function INITIAL_BASE_FEE() view returns(uint128) -func (_KromaPortal *KromaPortalCallerSession) INITIALBASEFEE() (*big.Int, error) { - return _KromaPortal.Contract.INITIALBASEFEE(&_KromaPortal.CallOpts) -} - // L2ORACLE is a free data retrieval call binding the contract method 0x001c2ff6. // // Solidity: function L2_ORACLE() view returns(address) @@ -357,128 +264,35 @@ func (_KromaPortal *KromaPortalCallerSession) L2ORACLE() (common.Address, error) return _KromaPortal.Contract.L2ORACLE(&_KromaPortal.CallOpts) } -// MAXIMUMBASEFEE is a free data retrieval call binding the contract method 0x5c1f2827. -// -// Solidity: function MAXIMUM_BASE_FEE() view returns(int256) -func (_KromaPortal *KromaPortalCaller) MAXIMUMBASEFEE(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _KromaPortal.contract.Call(opts, &out, "MAXIMUM_BASE_FEE") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// MAXIMUMBASEFEE is a free data retrieval call binding the contract method 0x5c1f2827. -// -// Solidity: function MAXIMUM_BASE_FEE() view returns(int256) -func (_KromaPortal *KromaPortalSession) MAXIMUMBASEFEE() (*big.Int, error) { - return _KromaPortal.Contract.MAXIMUMBASEFEE(&_KromaPortal.CallOpts) -} - -// MAXIMUMBASEFEE is a free data retrieval call binding the contract method 0x5c1f2827. -// -// Solidity: function MAXIMUM_BASE_FEE() view returns(int256) -func (_KromaPortal *KromaPortalCallerSession) MAXIMUMBASEFEE() (*big.Int, error) { - return _KromaPortal.Contract.MAXIMUMBASEFEE(&_KromaPortal.CallOpts) -} - -// MAXRESOURCELIMIT is a free data retrieval call binding the contract method 0x64b79208. -// -// Solidity: function MAX_RESOURCE_LIMIT() view returns(int256) -func (_KromaPortal *KromaPortalCaller) MAXRESOURCELIMIT(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _KromaPortal.contract.Call(opts, &out, "MAX_RESOURCE_LIMIT") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// MAXRESOURCELIMIT is a free data retrieval call binding the contract method 0x64b79208. -// -// Solidity: function MAX_RESOURCE_LIMIT() view returns(int256) -func (_KromaPortal *KromaPortalSession) MAXRESOURCELIMIT() (*big.Int, error) { - return _KromaPortal.Contract.MAXRESOURCELIMIT(&_KromaPortal.CallOpts) -} - -// MAXRESOURCELIMIT is a free data retrieval call binding the contract method 0x64b79208. -// -// Solidity: function MAX_RESOURCE_LIMIT() view returns(int256) -func (_KromaPortal *KromaPortalCallerSession) MAXRESOURCELIMIT() (*big.Int, error) { - return _KromaPortal.Contract.MAXRESOURCELIMIT(&_KromaPortal.CallOpts) -} - -// MINIMUMBASEFEE is a free data retrieval call binding the contract method 0x867ead13. -// -// Solidity: function MINIMUM_BASE_FEE() view returns(int256) -func (_KromaPortal *KromaPortalCaller) MINIMUMBASEFEE(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _KromaPortal.contract.Call(opts, &out, "MINIMUM_BASE_FEE") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// MINIMUMBASEFEE is a free data retrieval call binding the contract method 0x867ead13. +// SYSTEMCONFIG is a free data retrieval call binding the contract method 0xf0498750. // -// Solidity: function MINIMUM_BASE_FEE() view returns(int256) -func (_KromaPortal *KromaPortalSession) MINIMUMBASEFEE() (*big.Int, error) { - return _KromaPortal.Contract.MINIMUMBASEFEE(&_KromaPortal.CallOpts) -} - -// MINIMUMBASEFEE is a free data retrieval call binding the contract method 0x867ead13. -// -// Solidity: function MINIMUM_BASE_FEE() view returns(int256) -func (_KromaPortal *KromaPortalCallerSession) MINIMUMBASEFEE() (*big.Int, error) { - return _KromaPortal.Contract.MINIMUMBASEFEE(&_KromaPortal.CallOpts) -} - -// TARGETRESOURCELIMIT is a free data retrieval call binding the contract method 0xca3e99ba. -// -// Solidity: function TARGET_RESOURCE_LIMIT() view returns(int256) -func (_KromaPortal *KromaPortalCaller) TARGETRESOURCELIMIT(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function SYSTEM_CONFIG() view returns(address) +func (_KromaPortal *KromaPortalCaller) SYSTEMCONFIG(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _KromaPortal.contract.Call(opts, &out, "TARGET_RESOURCE_LIMIT") + err := _KromaPortal.contract.Call(opts, &out, "SYSTEM_CONFIG") if err != nil { - return *new(*big.Int), err + return *new(common.Address), err } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) return out0, err } -// TARGETRESOURCELIMIT is a free data retrieval call binding the contract method 0xca3e99ba. +// SYSTEMCONFIG is a free data retrieval call binding the contract method 0xf0498750. // -// Solidity: function TARGET_RESOURCE_LIMIT() view returns(int256) -func (_KromaPortal *KromaPortalSession) TARGETRESOURCELIMIT() (*big.Int, error) { - return _KromaPortal.Contract.TARGETRESOURCELIMIT(&_KromaPortal.CallOpts) +// Solidity: function SYSTEM_CONFIG() view returns(address) +func (_KromaPortal *KromaPortalSession) SYSTEMCONFIG() (common.Address, error) { + return _KromaPortal.Contract.SYSTEMCONFIG(&_KromaPortal.CallOpts) } -// TARGETRESOURCELIMIT is a free data retrieval call binding the contract method 0xca3e99ba. +// SYSTEMCONFIG is a free data retrieval call binding the contract method 0xf0498750. // -// Solidity: function TARGET_RESOURCE_LIMIT() view returns(int256) -func (_KromaPortal *KromaPortalCallerSession) TARGETRESOURCELIMIT() (*big.Int, error) { - return _KromaPortal.Contract.TARGETRESOURCELIMIT(&_KromaPortal.CallOpts) +// Solidity: function SYSTEM_CONFIG() view returns(address) +func (_KromaPortal *KromaPortalCallerSession) SYSTEMCONFIG() (common.Address, error) { + return _KromaPortal.Contract.SYSTEMCONFIG(&_KromaPortal.CallOpts) } // ZKMERKLETRIE is a free data retrieval call binding the contract method 0x5865b607. diff --git a/bindings/bindings/kromaportal_more.go b/bindings/bindings/kromaportal_more.go index 0443bc5af2..c52a8516e3 100644 --- a/bindings/bindings/kromaportal_more.go +++ b/bindings/bindings/kromaportal_more.go @@ -13,7 +13,7 @@ const KromaPortalStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\" var KromaPortalStorageLayout = new(solc.StorageLayout) -var KromaPortalDeployedBin = "0x6080604052600436106101835760003560e01c8063724c184c116100d6578063ca3e99ba1161007f578063d53a822f11610059578063d53a822f14610523578063e965084c14610543578063e9e05c42146105cf57600080fd5b8063ca3e99ba14610458578063cd7c97891461046d578063cff0ab961461048257600080fd5b80638c3152e9116100b05780638c3152e9146103db5780639bf62d82146103fb578063a14238e71461042857600080fd5b8063724c184c1461037a5780638456cb59146103ae578063867ead13146103c357600080fd5b80635865b6071161013857806364b792081161011257806364b792081461032d5780636bb0291e146103455780636dbffb781461035a57600080fd5b80635865b6071461029d5780635c1f2827146102d15780635c975abb1461030357600080fd5b806313620abd1161016957806313620abd1461022d5780633f4ba83a1461026657806354fd4d501461027b57600080fd5b80621c2ff6146101af5780630757b2441461020d57600080fd5b366101aa576101a83334620186a06000604051806020016040528060008152506105dd565b005b600080fd5b3480156101bb57600080fd5b506101e37f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021957600080fd5b506101a8610228366004612a2b565b6107c3565b34801561023957600080fd5b50610245633b9aca0081565b6040516fffffffffffffffffffffffffffffffff9091168152602001610204565b34801561027257600080fd5b506101a8610dc1565b34801561028757600080fd5b50610290610eca565b6040516102049190612b82565b3480156102a957600080fd5b506101e37f000000000000000000000000000000000000000000000000000000000000000081565b3480156102dd57600080fd5b506102f56fffffffffffffffffffffffffffffffff81565b604051908152602001610204565b34801561030f57600080fd5b5060355461031d9060ff1681565b6040519015158152602001610204565b34801561033957600080fd5b506102f56301312d0081565b34801561035157600080fd5b506102f5600a81565b34801561036657600080fd5b5061031d610375366004612b95565b610f6d565b34801561038657600080fd5b506101e37f000000000000000000000000000000000000000000000000000000000000000081565b3480156103ba57600080fd5b506101a8611044565b3480156103cf57600080fd5b506102f5633b9aca0081565b3480156103e757600080fd5b506101a86103f6366004612bae565b611149565b34801561040757600080fd5b506032546101e39073ffffffffffffffffffffffffffffffffffffffff1681565b34801561043457600080fd5b5061031d610443366004612b95565b60336020526000908152604090205460ff1681565b34801561046457600080fd5b506102f5611914565b34801561047957600080fd5b506102f5600881565b34801561048e57600080fd5b506001546104ea906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff9283166020850152911690820152606001610204565b34801561052f57600080fd5b506101a861053e366004612bf4565b611926565b34801561054f57600080fd5b506105a161055e366004612b95565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff9283166020850152911690820152606001610204565b6101a86105dd366004612c11565b8260005a905083156106785773ffffffffffffffffffffffffffffffffffffffff8716156106785760405162461bcd60e51b815260206004820152603d60248201527f4b726f6d61506f7274616c3a206d7573742073656e6420746f2061646472657360448201527f73283029207768656e206372656174696e67206120636f6e747261637400000060648201526084015b60405180910390fd5b6152088567ffffffffffffffff1610156106fa5760405162461bcd60e51b815260206004820152603560248201527f4b726f6d61506f7274616c3a20676173206c696d6974206d75737420636f766560448201527f7220696e737472696e7369632067617320636f73740000000000000000000000606482015260840161066f565b3332811461071b575033731111000000000000000000000000000000001111015b60003488888888604051602001610736959493929190612c99565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516107a69190612b82565b60405180910390a450506107ba8282611b15565b50505050505050565b60355460ff16156108165760405162461bcd60e51b815260206004820152601360248201527f4b726f6d61506f7274616c3a2070617573656400000000000000000000000000604482015260640161066f565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036108bb5760405162461bcd60e51b815260206004820152603c60248201527f4b726f6d61506f7274616c3a20796f752063616e6e6f742073656e64206d657360448201527f736167657320746f2074686520706f7274616c20636f6e747261637400000000606482015260840161066f565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610949573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096d9190612d1e565b51905061098761098236869003860186612d83565b611df4565b81146109fb5760405162461bcd60e51b815260206004820152602660248201527f4b726f6d61506f7274616c3a20696e76616c6964206f757470757420726f6f7460448201527f2070726f6f660000000000000000000000000000000000000000000000000000606482015260840161066f565b6000610a0687611eaa565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610b385750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610b10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b349190612d1e565b5114155b610baa5760405162461bcd60e51b815260206004820152603460248201527f4b726f6d61506f7274616c3a207769746864726177616c20686173682068617360448201527f20616c7265616479206265656e2070726f76656e000000000000000000000000606482015260840161066f565b60408051602080820185905260008284015282518083038401815260608301808552815191909201207f12e64a7200000000000000000000000000000000000000000000000000000000909152917f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16916312e64a7291610c4c9185918b918b918e013590606401612e3c565b602060405180830381865afa158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d9190612f3d565b610cff5760405162461bcd60e51b815260206004820152602f60248201527f4b726f6d61506f7274616c3a20696e76616c6964207769746864726177616c2060448201527f696e636c7573696f6e2070726f6f660000000000000000000000000000000000606482015260840161066f565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e6c5760405162461bcd60e51b815260206004820152602660248201527f4b726f6d61506f7274616c3a206f6e6c7920677561726469616e2063616e207560448201527f6e70617573650000000000000000000000000000000000000000000000000000606482015260840161066f565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6060610ef57f0000000000000000000000000000000000000000000000000000000000000000611ef7565b610f1e7f0000000000000000000000000000000000000000000000000000000000000000611ef7565b610f477f0000000000000000000000000000000000000000000000000000000000000000611ef7565b604051602001610f5993929190612f5a565b604051602081830303815290604052905090565b6040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810182905260009061103e9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015610fff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110239190612d1e565b602001516fffffffffffffffffffffffffffffffff16612034565b92915050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146110ee5760405162461bcd60e51b8152602060048201526024808201527f4b726f6d61506f7274616c3a206f6e6c7920677561726469616e2063616e207060448201527f6175736500000000000000000000000000000000000000000000000000000000606482015260840161066f565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610ec0565b60355460ff161561119c5760405162461bcd60e51b815260206004820152601360248201527f4b726f6d61506f7274616c3a2070617573656400000000000000000000000000604482015260640161066f565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461122b5760405162461bcd60e51b815260206004820152603c60248201527f4b726f6d61506f7274616c3a2063616e206f6e6c792074726967676572206f6e60448201527f65207769746864726177616c20706572207472616e73616374696f6e00000000606482015260840161066f565b600061123682611eaa565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036113075760405162461bcd60e51b815260206004820152602f60248201527f4b726f6d61506f7274616c3a207769746864726177616c20686173206e6f742060448201527f6265656e2070726f76656e207965740000000000000000000000000000000000606482015260840161066f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611372573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113969190612fd0565b81602001516fffffffffffffffffffffffffffffffff1610156114475760405162461bcd60e51b815260206004820152604860248201527f4b726f6d61506f7274616c3a207769746864726177616c2074696d657374616d60448201527f70206c657373207468616e204c32204f7261636c65207374617274696e67207460648201527f696d657374616d70000000000000000000000000000000000000000000000000608482015260a40161066f565b61146681602001516fffffffffffffffffffffffffffffffff16612034565b6114fe5760405162461bcd60e51b815260206004820152604260248201527f4b726f6d61506f7274616c3a2070726f76656e207769746864726177616c206660448201527f696e616c697a6174696f6e20706572696f6420686173206e6f7420656c61707360648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a40161066f565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c79190612d1e565b82518151919250146116675760405162461bcd60e51b815260206004820152604660248201527f4b726f6d61506f7274616c3a206f757470757420726f6f742070726f76656e2060448201527f6973206e6f74207468652073616d652061732063757272656e74206f7574707560648201527f7420726f6f740000000000000000000000000000000000000000000000000000608482015260a40161066f565b61168681602001516fffffffffffffffffffffffffffffffff16612034565b61171e5760405162461bcd60e51b815260206004820152604260248201527f4b726f6d61506f7274616c3a20636865636b706f696e74206f7574707574206660448201527f696e616c697a6174696f6e20706572696f6420686173206e6f7420656c61707360648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a40161066f565b60008381526033602052604090205460ff16156117a35760405162461bcd60e51b815260206004820152603260248201527f4b726f6d61506f7274616c3a207769746864726177616c2068617320616c726560448201527f616479206265656e2066696e616c697a65640000000000000000000000000000606482015260840161066f565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a0880151611845939291906120d7565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906118aa90841515815260200190565b60405180910390a2801580156118c05750326001145b1561190d5760405162461bcd60e51b815260206004820152601e60248201527f4b726f6d61506f7274616c3a207769746864726177616c206661696c65640000604482015260640161066f565b5050505050565b611923600a6301312d00613047565b81565b600054610100900460ff16158080156119465750600054600160ff909116105b806119605750303b158015611960575060005460ff166001145b6119d25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161066f565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611a3057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055603580548315157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116179055611a92612131565b8015611af557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611b4b907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436130af565b90508015611c83576000611b64600a6301312d00613047565b600154611b8f9190700100000000000000000000000000000000900467ffffffffffffffff166130c6565b905060006008611ba4600a6301312d00613047565b611bae919061313a565b600154611bce9084906fffffffffffffffffffffffffffffffff1661313a565b611bd89190613047565b600154909150600090611c1d90611c029084906fffffffffffffffffffffffffffffffff166131f6565b633b9aca006fffffffffffffffffffffffffffffffff6121fa565b90506001841115611c4457611c41611c02826008611c3c6001896130af565b61220f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054849190601090611cb6908490700100000000000000000000000000000000900467ffffffffffffffff1661326a565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506301312d00600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611d795760405162461bcd60e51b815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d69740000606482015260840161066f565b600154600090611da5906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8616613296565b90506000611db748633b9aca00612264565b611dc190836132d3565b905060005a611dd090866130af565b905080821115611dec57611dec611de782846130af565b61227d565b505050505050565b8051600090611e065761103e826122ab565b81517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611e375761103e826122ea565b60405162461bcd60e51b815260206004820152602a60248201527f48617368696e673a20756e6b6e6f776e206f757470757420726f6f742070726f60448201527f6f662076657273696f6e00000000000000000000000000000000000000000000606482015260840161066f565b919050565b80516020808301516040808501516060860151608087015160a08801519351600097611eda9790969591016132e7565b604051602081830303815290604052805190602001209050919050565b606081600003611f3a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611f645780611f4e8161333e565b9150611f5d9050600a836132d3565b9150611f3e565b60008167ffffffffffffffff811115611f7f57611f7f612888565b6040519080825280601f01601f191660200182016040528015611fa9576020820181803683370190505b5090505b841561202c57611fbe6001836130af565b9150611fcb600a86613376565b611fd690603061338a565b60f81b818381518110611feb57611feb6133a2565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612025600a866132d3565b9450611fad565b949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c59190612fd0565b6120cf908361338a565b421192915050565b600080603f60c88601604002045a101561211a576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080845160208601878a5af19695505050505050565b600054610100900460ff166121ae5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161066f565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b600061202c612209858561232d565b8361233d565b6000670de0b6b3a76400006122506122278583613047565b61223990670de0b6b3a76400006130c6565b61224b85670de0b6b3a764000061313a565b61234c565b61225a908661313a565b61202c9190613047565b6000818310156122745781612276565b825b9392505050565b6000805a90505b825a61229090836130af565b10156122a65761229f8261333e565b9150612284565b505050565b60008160000151826020015183604001518460600151604051602001611eda949392919093845260208401929092526040830152606082015260800190565b80516020808301516040808501516060808701516080808901518551978801989098529386019490945284015282015260a081019190915260009060c001611eda565b6000818312156122745781612276565b60008183126122745781612276565b6000612276670de0b6b3a7640000836123648661237d565b61236e919061313a565b6123789190613047565b6125a7565b60008082136123ce5760405162461bcd60e51b815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161066f565b600060606123db846127cc565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136125d857506000919050565b680755bf798b4a1bf1e582126126305760405162461bcd60e51b815260206004820152600c60248201527f4558505f4f564552464c4f570000000000000000000000000000000000000000604482015260640161066f565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080821161281d5760405162461bcd60e51b815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161066f565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114611ea557600080fd5b600082601f8301126128ec57600080fd5b813567ffffffffffffffff8082111561290757612907612888565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561294d5761294d612888565b8160405283815286602085880101111561296657600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060c0828403121561299857600080fd5b60405160c0810167ffffffffffffffff82821081831117156129bc576129bc612888565b81604052829350843583526129d3602086016128b7565b60208401526129e4604086016128b7565b6040840152606085013560608401526080850135608084015260a0850135915080821115612a1157600080fd5b50612a1e858286016128db565b60a0830152505092915050565b6000806000806000858703610100811215612a4557600080fd5b863567ffffffffffffffff80821115612a5d57600080fd5b612a698a838b01612986565b97506020890135965060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215612aa257600080fd5b60408901955060e0890135925080831115612abc57600080fd5b828901925089601f840112612ad057600080fd5b8235915080821115612ae157600080fd5b508860208260051b8401011115612af757600080fd5b959894975092955050506020019190565b60005b83811015612b23578181015183820152602001612b0b565b83811115612b32576000848401525b50505050565b60008151808452612b50816020860160208601612b08565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122766020830184612b38565b600060208284031215612ba757600080fd5b5035919050565b600060208284031215612bc057600080fd5b813567ffffffffffffffff811115612bd757600080fd5b61202c84828501612986565b8015158114612bf157600080fd5b50565b600060208284031215612c0657600080fd5b813561227681612be3565b600080600080600060a08688031215612c2957600080fd5b612c32866128b7565b945060208601359350604086013567ffffffffffffffff8082168214612c5757600080fd5b909350606087013590612c6982612be3565b90925060808701359080821115612c7f57600080fd5b50612c8c888289016128db565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251612ced816049850160208701612b08565b919091016049019695505050505050565b80516fffffffffffffffffffffffffffffffff81168114611ea557600080fd5b600060608284031215612d3057600080fd5b6040516060810181811067ffffffffffffffff82111715612d5357612d53612888565b60405282518152612d6660208401612cfe565b6020820152612d7760408401612cfe565b60408201529392505050565b600060a08284031215612d9557600080fd5b60405160a0810181811067ffffffffffffffff82111715612db857612db8612888565b806040525082358152602083013560208201526040830135604082015260608301356060820152608083013560808201528091505092915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8481526000602060808184015280608084015260018060a085015260c0840160c060408601528087825260e08601905060e08860051b87010191508860005b89811015612f25577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2088850301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18c3603018112612edc57600080fd5b8b01868101903567ffffffffffffffff811115612ef857600080fd5b803603821315612f0757600080fd5b612f12868284612df3565b9550505091850191908501908401612e7b565b50505080935050505082606083015295945050505050565b600060208284031215612f4f57600080fd5b815161227681612be3565b60008451612f6c818460208901612b08565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612fa8816001850160208a01612b08565b60019201918201528351612fc3816002840160208801612b08565b0160020195945050505050565b600060208284031215612fe257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008261305657613056612fe9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156130aa576130aa613018565b500590565b6000828210156130c1576130c1613018565b500390565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561310057613100613018565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561313457613134613018565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561317b5761317b613018565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156131b6576131b6613018565b600087129250878205871284841616156131d2576131d2613018565b878505871281841616156131e8576131e8613018565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561323057613230613018565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561326457613264613018565b50500190565b600067ffffffffffffffff80831681851680830382111561328d5761328d613018565b01949350505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156132ce576132ce613018565b500290565b6000826132e2576132e2612fe9565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261333260c0830184612b38565b98975050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361336f5761336f613018565b5060010190565b60008261338557613385612fe9565b500690565b6000821982111561339d5761339d613018565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" +var KromaPortalDeployedBin = "0x6080604052600436106101115760003560e01c80638456cb59116100a5578063cff0ab9611610074578063e965084c11610059578063e965084c146103f7578063e9e05c4214610483578063f04987501461049657600080fd5b8063cff0ab9614610336578063d53a822f146103d757600080fd5b80638456cb59146102a45780638c3152e9146102b95780639bf62d82146102d9578063a14238e71461030657600080fd5b80635865b607116100e15780635865b607146101f25780635c975abb146102265780636dbffb7814610250578063724c184c1461027057600080fd5b80621c2ff61461013d5780630757b2441461019b5780633f4ba83a146101bb57806354fd4d50146101d057600080fd5b36610138576101363334620186a06000604051806020016040528060008152506104ca565b005b600080fd5b34801561014957600080fd5b506101717f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101a757600080fd5b506101366101b6366004612a00565b6106b0565b3480156101c757600080fd5b50610136610cae565b3480156101dc57600080fd5b506101e5610db7565b6040516101929190612b57565b3480156101fe57600080fd5b506101717f000000000000000000000000000000000000000000000000000000000000000081565b34801561023257600080fd5b506035546102409060ff1681565b6040519015158152602001610192565b34801561025c57600080fd5b5061024061026b366004612b6a565b610e5a565b34801561027c57600080fd5b506101717f000000000000000000000000000000000000000000000000000000000000000081565b3480156102b057600080fd5b50610136610f31565b3480156102c557600080fd5b506101366102d4366004612b83565b611036565b3480156102e557600080fd5b506032546101719073ffffffffffffffffffffffffffffffffffffffff1681565b34801561031257600080fd5b50610240610321366004612b6a565b60336020526000908152604090205460ff1681565b34801561034257600080fd5b5060015461039e906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff9283166020850152911690820152606001610192565b3480156103e357600080fd5b506101366103f2366004612bc9565b611801565b34801561040357600080fd5b50610455610412366004612b6a565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff9283166020850152911690820152606001610192565b610136610491366004612be6565b6104ca565b3480156104a257600080fd5b506101717f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156105655773ffffffffffffffffffffffffffffffffffffffff8716156105655760405162461bcd60e51b815260206004820152603d60248201527f4b726f6d61506f7274616c3a206d7573742073656e6420746f2061646472657360448201527f73283029207768656e206372656174696e67206120636f6e747261637400000060648201526084015b60405180910390fd5b6152088567ffffffffffffffff1610156105e75760405162461bcd60e51b815260206004820152603560248201527f4b726f6d61506f7274616c3a20676173206c696d6974206d75737420636f766560448201527f7220696e737472696e7369632067617320636f73740000000000000000000000606482015260840161055c565b33328114610608575033731111000000000000000000000000000000001111015b60003488888888604051602001610623959493929190612c6e565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516106939190612b57565b60405180910390a450506106a782826119f0565b50505050505050565b60355460ff16156107035760405162461bcd60e51b815260206004820152601360248201527f4b726f6d61506f7274616c3a2070617573656400000000000000000000000000604482015260640161055c565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036107a85760405162461bcd60e51b815260206004820152603c60248201527f4b726f6d61506f7274616c3a20796f752063616e6e6f742073656e64206d657360448201527f736167657320746f2074686520706f7274616c20636f6e747261637400000000606482015260840161055c565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610836573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085a9190612cf3565b51905061087461086f36869003860186612d58565b611d03565b81146108e85760405162461bcd60e51b815260206004820152602660248201527f4b726f6d61506f7274616c3a20696e76616c6964206f757470757420726f6f7460448201527f2070726f6f660000000000000000000000000000000000000000000000000000606482015260840161055c565b60006108f387611db9565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610a255750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156109fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a219190612cf3565b5114155b610a975760405162461bcd60e51b815260206004820152603460248201527f4b726f6d61506f7274616c3a207769746864726177616c20686173682068617360448201527f20616c7265616479206265656e2070726f76656e000000000000000000000000606482015260840161055c565b60408051602080820185905260008284015282518083038401815260608301808552815191909201207f12e64a7200000000000000000000000000000000000000000000000000000000909152917f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16916312e64a7291610b399185918b918b918e013590606401612e11565b602060405180830381865afa158015610b56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7a9190612f12565b610bec5760405162461bcd60e51b815260206004820152602f60248201527f4b726f6d61506f7274616c3a20696e76616c6964207769746864726177616c2060448201527f696e636c7573696f6e2070726f6f660000000000000000000000000000000000606482015260840161055c565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610d595760405162461bcd60e51b815260206004820152602660248201527f4b726f6d61506f7274616c3a206f6e6c7920677561726469616e2063616e207560448201527f6e70617573650000000000000000000000000000000000000000000000000000606482015260840161055c565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6060610de27f0000000000000000000000000000000000000000000000000000000000000000611e06565b610e0b7f0000000000000000000000000000000000000000000000000000000000000000611e06565b610e347f0000000000000000000000000000000000000000000000000000000000000000611e06565b604051602001610e4693929190612f2f565b604051602081830303815290604052905090565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090610f2b9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015610eec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f109190612cf3565b602001516fffffffffffffffffffffffffffffffff16611f43565b92915050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610fdb5760405162461bcd60e51b8152602060048201526024808201527f4b726f6d61506f7274616c3a206f6e6c7920677561726469616e2063616e207060448201527f6175736500000000000000000000000000000000000000000000000000000000606482015260840161055c565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610dad565b60355460ff16156110895760405162461bcd60e51b815260206004820152601360248201527f4b726f6d61506f7274616c3a2070617573656400000000000000000000000000604482015260640161055c565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146111185760405162461bcd60e51b815260206004820152603c60248201527f4b726f6d61506f7274616c3a2063616e206f6e6c792074726967676572206f6e60448201527f65207769746864726177616c20706572207472616e73616374696f6e00000000606482015260840161055c565b600061112382611db9565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036111f45760405162461bcd60e51b815260206004820152602f60248201527f4b726f6d61506f7274616c3a207769746864726177616c20686173206e6f742060448201527f6265656e2070726f76656e207965740000000000000000000000000000000000606482015260840161055c565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa15801561125f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112839190612fa5565b81602001516fffffffffffffffffffffffffffffffff1610156113345760405162461bcd60e51b815260206004820152604860248201527f4b726f6d61506f7274616c3a207769746864726177616c2074696d657374616d60448201527f70206c657373207468616e204c32204f7261636c65207374617274696e67207460648201527f696d657374616d70000000000000000000000000000000000000000000000000608482015260a40161055c565b61135381602001516fffffffffffffffffffffffffffffffff16611f43565b6113eb5760405162461bcd60e51b815260206004820152604260248201527f4b726f6d61506f7274616c3a2070726f76656e207769746864726177616c206660448201527f696e616c697a6174696f6e20706572696f6420686173206e6f7420656c61707360648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a40161055c565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015611490573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b49190612cf3565b82518151919250146115545760405162461bcd60e51b815260206004820152604660248201527f4b726f6d61506f7274616c3a206f757470757420726f6f742070726f76656e2060448201527f6973206e6f74207468652073616d652061732063757272656e74206f7574707560648201527f7420726f6f740000000000000000000000000000000000000000000000000000608482015260a40161055c565b61157381602001516fffffffffffffffffffffffffffffffff16611f43565b61160b5760405162461bcd60e51b815260206004820152604260248201527f4b726f6d61506f7274616c3a20636865636b706f696e74206f7574707574206660448201527f696e616c697a6174696f6e20706572696f6420686173206e6f7420656c61707360648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a40161055c565b60008381526033602052604090205460ff16156116905760405162461bcd60e51b815260206004820152603260248201527f4b726f6d61506f7274616c3a207769746864726177616c2068617320616c726560448201527f616479206265656e2066696e616c697a65640000000000000000000000000000606482015260840161055c565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a088015161173293929190611fe6565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061179790841515815260200190565b60405180910390a2801580156117ad5750326001145b156117fa5760405162461bcd60e51b815260206004820152601e60248201527f4b726f6d61506f7274616c3a207769746864726177616c206661696c65640000604482015260640161055c565b5050505050565b600054610100900460ff16158080156118215750600054600160ff909116105b8061183b5750303b15801561183b575060005460ff166001145b6118ad5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161055c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561190b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055603580548315157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617905561196d612040565b80156119d057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611a26907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643612fed565b90506000611a32612109565b90506000816020015160ff16826000015163ffffffff16611a539190613033565b90508215611b8a57600154600090611a8a908390700100000000000000000000000000000000900467ffffffffffffffff1661309b565b90506000836040015160ff1683611aa1919061310f565b600154611ac19084906fffffffffffffffffffffffffffffffff1661310f565b611acb9190613033565b600154909150600090611b1c90611af59084906fffffffffffffffffffffffffffffffff166131cb565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff166121cf565b90506001861115611b4b57611b48611af582876040015160ff1660018a611b439190612fed565b6121e4565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611bbd908490700100000000000000000000000000000000900467ffffffffffffffff1661323f565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611c865760405162461bcd60e51b815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d69740000606482015260840161055c565b600154600090611cb2906fffffffffffffffffffffffffffffffff1667ffffffffffffffff881661326b565b90506000611cc448633b9aca00612239565b611cce90836132a8565b905060005a611cdd9088612fed565b905080821115611cf957611cf9611cf48284612fed565b612252565b5050505050505050565b8051600090611d1557610f2b82612280565b81517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611d4657610f2b826122bf565b60405162461bcd60e51b815260206004820152602a60248201527f48617368696e673a20756e6b6e6f776e206f757470757420726f6f742070726f60448201527f6f662076657273696f6e00000000000000000000000000000000000000000000606482015260840161055c565b919050565b80516020808301516040808501516060860151608087015160a08801519351600097611de99790969591016132bc565b604051602081830303815290604052805190602001209050919050565b606081600003611e4957505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611e735780611e5d81613313565b9150611e6c9050600a836132a8565b9150611e4d565b60008167ffffffffffffffff811115611e8e57611e8e61285d565b6040519080825280601f01601f191660200182016040528015611eb8576020820181803683370190505b5090505b8415611f3b57611ecd600183612fed565b9150611eda600a8661334b565b611ee590603061335f565b60f81b818381518110611efa57611efa613377565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611f34600a866132a8565b9450611ebc565b949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd49190612fa5565b611fde908361335f565b421192915050565b600080603f60c88601604002045a1015612029576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080845160208601878a5af19695505050505050565b600054610100900460ff166120bd5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161055c565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa1580156121a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ca91906133cb565b905090565b6000611f3b6121de8585612302565b83612312565b6000670de0b6b3a76400006122256121fc8583613033565b61220e90670de0b6b3a764000061309b565b61222085670de0b6b3a764000061310f565b612321565b61222f908661310f565b611f3b9190613033565b600081831015612249578161224b565b825b9392505050565b6000805a90505b825a6122659083612fed565b101561227b5761227482613313565b9150612259565b505050565b60008160000151826020015183604001518460600151604051602001611de9949392919093845260208401929092526040830152606082015260800190565b80516020808301516040808501516060808701516080808901518551978801989098529386019490945284015282015260a081019190915260009060c001611de9565b600081831215612249578161224b565b6000818312612249578161224b565b600061224b670de0b6b3a76400008361233986612352565b612343919061310f565b61234d9190613033565b61257c565b60008082136123a35760405162461bcd60e51b815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161055c565b600060606123b0846127a1565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136125ad57506000919050565b680755bf798b4a1bf1e582126126055760405162461bcd60e51b815260206004820152600c60248201527f4558505f4f564552464c4f570000000000000000000000000000000000000000604482015260640161055c565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b60008082116127f25760405162461bcd60e51b815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161055c565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114611db457600080fd5b600082601f8301126128c157600080fd5b813567ffffffffffffffff808211156128dc576128dc61285d565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156129225761292261285d565b8160405283815286602085880101111561293b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060c0828403121561296d57600080fd5b60405160c0810167ffffffffffffffff82821081831117156129915761299161285d565b81604052829350843583526129a86020860161288c565b60208401526129b96040860161288c565b6040840152606085013560608401526080850135608084015260a08501359150808211156129e657600080fd5b506129f3858286016128b0565b60a0830152505092915050565b6000806000806000858703610100811215612a1a57600080fd5b863567ffffffffffffffff80821115612a3257600080fd5b612a3e8a838b0161295b565b97506020890135965060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215612a7757600080fd5b60408901955060e0890135925080831115612a9157600080fd5b828901925089601f840112612aa557600080fd5b8235915080821115612ab657600080fd5b508860208260051b8401011115612acc57600080fd5b959894975092955050506020019190565b60005b83811015612af8578181015183820152602001612ae0565b83811115612b07576000848401525b50505050565b60008151808452612b25816020860160208601612add565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061224b6020830184612b0d565b600060208284031215612b7c57600080fd5b5035919050565b600060208284031215612b9557600080fd5b813567ffffffffffffffff811115612bac57600080fd5b611f3b8482850161295b565b8015158114612bc657600080fd5b50565b600060208284031215612bdb57600080fd5b813561224b81612bb8565b600080600080600060a08688031215612bfe57600080fd5b612c078661288c565b945060208601359350604086013567ffffffffffffffff8082168214612c2c57600080fd5b909350606087013590612c3e82612bb8565b90925060808701359080821115612c5457600080fd5b50612c61888289016128b0565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251612cc2816049850160208701612add565b919091016049019695505050505050565b80516fffffffffffffffffffffffffffffffff81168114611db457600080fd5b600060608284031215612d0557600080fd5b6040516060810181811067ffffffffffffffff82111715612d2857612d2861285d565b60405282518152612d3b60208401612cd3565b6020820152612d4c60408401612cd3565b60408201529392505050565b600060a08284031215612d6a57600080fd5b60405160a0810181811067ffffffffffffffff82111715612d8d57612d8d61285d565b806040525082358152602083013560208201526040830135604082015260608301356060820152608083013560808201528091505092915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8481526000602060808184015280608084015260018060a085015260c0840160c060408601528087825260e08601905060e08860051b87010191508860005b89811015612efa577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2088850301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18c3603018112612eb157600080fd5b8b01868101903567ffffffffffffffff811115612ecd57600080fd5b803603821315612edc57600080fd5b612ee7868284612dc8565b9550505091850191908501908401612e50565b50505080935050505082606083015295945050505050565b600060208284031215612f2457600080fd5b815161224b81612bb8565b60008451612f41818460208901612add565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612f7d816001850160208a01612add565b60019201918201528351612f98816002840160208801612add565b0160020195945050505050565b600060208284031215612fb757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612fff57612fff612fbe565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261304257613042613004565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561309657613096612fbe565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156130d5576130d5612fbe565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561310957613109612fbe565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561315057613150612fbe565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561318b5761318b612fbe565b600087129250878205871284841616156131a7576131a7612fbe565b878505871281841616156131bd576131bd612fbe565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561320557613205612fbe565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561323957613239612fbe565b50500190565b600067ffffffffffffffff80831681851680830382111561326257613262612fbe565b01949350505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156132a3576132a3612fbe565b500290565b6000826132b7576132b7613004565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261330760c0830184612b0d565b98975050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361334457613344612fbe565b5060010190565b60008261335a5761335a613004565b500690565b6000821982111561337257613372612fbe565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805163ffffffff81168114611db457600080fd5b805160ff81168114611db457600080fd5b600060c082840312156133dd57600080fd5b60405160c0810181811067ffffffffffffffff821117156134005761340061285d565b60405261340c836133a6565b815261341a602084016133ba565b602082015261342b604084016133ba565b604082015261343c606084016133a6565b606082015261344d608084016133a6565b608082015261345e60a08401612cd3565b60a0820152939250505056fea164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(KromaPortalStorageLayoutJSON), KromaPortalStorageLayout); err != nil { diff --git a/bindings/bindings/systemconfig.go b/bindings/bindings/systemconfig.go index 898dd34e3d..4b2ebee58d 100644 --- a/bindings/bindings/systemconfig.go +++ b/bindings/bindings/systemconfig.go @@ -29,10 +29,20 @@ var ( _ = abi.ConvertType ) +// ResourceMeteringResourceConfig is an auto generated low-level Go binding around an user-defined struct. +type ResourceMeteringResourceConfig struct { + MaxResourceLimit uint32 + ElasticityMultiplier uint8 + BaseFeeMaxChangeDenominator uint8 + MinimumBaseFee uint32 + SystemTxMaxGas uint32 + MaximumBaseFee *big.Int +} + // SystemConfigMetaData contains all meta data concerning the SystemConfig contract. var SystemConfigMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"enumSystemConfig.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"ConfigUpdate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"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\":\"MINIMUM_GAS_LIMIT\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UNSAFE_BLOCK_SIGNER_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batcherHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"overhead\",\"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\":[],\"name\":\"scalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"}],\"name\":\"setBatcherHash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"}],\"name\":\"setGasConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"}],\"name\":\"setGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"}],\"name\":\"setUnsafeBlockSigner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unsafeBlockSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620015403803806200154083398101604081905262000034916200047b565b60006080819052600160a05260c052620000538686868686866200005f565b505050505050620004f0565b600054610100900460ff1615808015620000805750600054600160ff909116105b80620000b057506200009d306200025360201b620009021760201c565b158015620000b0575060005460ff166001145b620001195760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200013d576000805461ff0019166101001790555b627a12006001600160401b03841610156200019b5760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640162000110565b620001a562000262565b620001b087620002ca565b606586905560668590556067849055606880546001600160401b0319166001600160401b03851617905562000203827f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0855565b80156200024a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6001600160a01b03163b151590565b600054610100900460ff16620002be5760405162461bcd60e51b815260206004820152602b60248201526000805160206200152083398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000110565b620002c862000349565b565b620002d4620003b0565b6001600160a01b0381166200033b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000110565b62000346816200040c565b50565b600054610100900460ff16620003a55760405162461bcd60e51b815260206004820152602b60248201526000805160206200152083398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000110565b620002c8336200040c565b6033546001600160a01b03163314620002c85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000110565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200047657600080fd5b919050565b60008060008060008060c087890312156200049557600080fd5b620004a0876200045e565b6020880151604089015160608a015160808b0151939950919750955093506001600160401b0381168114620004d457600080fd5b9150620004e460a088016200045e565b90509295509295509295565b60805160a05160c0516110006200052060003960006103c80152600061039f0152600061037601526110006000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c80638f974d7f116100b2578063e81b2c6d11610081578063f45e65d811610066578063f45e65d814610286578063f68016b71461028f578063ffa1ad74146102a357600080fd5b8063e81b2c6d1461026a578063f2fde38b1461027357600080fd5b80638f974d7f1461021e578063935f029e14610231578063b40a817c14610244578063c9b26f611461025757600080fd5b80634f16540b116100ee5780634f16540b146101bc57806354fd4d50146101e3578063715018a6146101f85780638da5cb5b1461020057600080fd5b80630c18c1621461012057806318d139181461013c5780631fd19ee11461015157806329477e8614610199575b600080fd5b61012960655481565b6040519081526020015b60405180910390f35b61014f61014a366004610cb6565b6102ab565b005b7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08545b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610133565b6101a3627a120081565b60405167ffffffffffffffff9091168152602001610133565b6101297f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b6101eb61036f565b6040516101339190610d52565b61014f610412565b60335473ffffffffffffffffffffffffffffffffffffffff16610174565b61014f61022c366004610d7d565b610426565b61014f61023f366004610ddc565b6106aa565b61014f610252366004610dfe565b610743565b61014f610265366004610e19565b61081b565b61012960675481565b61014f610281366004610cb6565b61084b565b61012960665481565b6068546101a39067ffffffffffffffff1681565b610129600081565b6102b361091e565b6102db817f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0855565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516103639190610d52565b60405180910390a35050565b606061039a7f000000000000000000000000000000000000000000000000000000000000000061099f565b6103c37f000000000000000000000000000000000000000000000000000000000000000061099f565b6103ec7f000000000000000000000000000000000000000000000000000000000000000061099f565b6040516020016103fe93929190610e32565b604051602081830303815290604052905090565b61041a61091e565b6104246000610adc565b565b600054610100900460ff16158080156104465750600054600160ff909116105b806104605750303b158015610460575060005460ff166001145b6104f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561054f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b627a120067ffffffffffffffff841610156105c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016104e8565b6105ce610b53565b6105d78761084b565b606586905560668590556067849055606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85161790557f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0882905580156106a157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6106b261091e565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516107369190610d52565b60405180910390a3505050565b61074b61091e565b627a120067ffffffffffffffff821610156107c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016104e8565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610332565b61082361091e565b6067819055604080516020808201849052825180830390910181529082019091526000610332565b61085361091e565b73ffffffffffffffffffffffffffffffffffffffff81166108f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016104e8565b6108ff81610adc565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610424576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104e8565b6060816000036109e257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610a0c57806109f681610ed7565b9150610a059050600a83610f3e565b91506109e6565b60008167ffffffffffffffff811115610a2757610a27610f52565b6040519080825280601f01601f191660200182016040528015610a51576020820181803683370190505b5090505b8415610ad457610a66600183610f81565b9150610a73600a86610f98565b610a7e906030610fac565b60f81b818381518110610a9357610a93610fc4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610acd600a86610f3e565b9450610a55565b949350505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610bea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104e8565b610424600054610100900460ff16610c84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104e8565b61042433610adc565b803573ffffffffffffffffffffffffffffffffffffffff81168114610cb157600080fd5b919050565b600060208284031215610cc857600080fd5b610cd182610c8d565b9392505050565b60005b83811015610cf3578181015183820152602001610cdb565b83811115610d02576000848401525b50505050565b60008151808452610d20816020860160208601610cd8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610cd16020830184610d08565b803567ffffffffffffffff81168114610cb157600080fd5b60008060008060008060c08789031215610d9657600080fd5b610d9f87610c8d565b9550602087013594506040870135935060608701359250610dc260808801610d65565b9150610dd060a08801610c8d565b90509295509295509295565b60008060408385031215610def57600080fd5b50508035926020909101359150565b600060208284031215610e1057600080fd5b610cd182610d65565b600060208284031215610e2b57600080fd5b5035919050565b60008451610e44818460208901610cd8565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610e80816001850160208a01610cd8565b60019201918201528351610e9b816002840160208801610cd8565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610f0857610f08610ea8565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610f4d57610f4d610f0f565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015610f9357610f93610ea8565b500390565b600082610fa757610fa7610f0f565b500690565b60008219821115610fbf57610fbf610ea8565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}],\"internalType\":\"structResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"enumSystemConfig.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"ConfigUpdate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"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\":\"UNSAFE_BLOCK_SIGNER_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batcherHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}],\"internalType\":\"structResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"overhead\",\"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\":[],\"name\":\"resourceConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}],\"internalType\":\"structResourceMetering.ResourceConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"scalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"}],\"name\":\"setBatcherHash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"}],\"name\":\"setGasConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"}],\"name\":\"setGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}],\"internalType\":\"structResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\"}],\"name\":\"setResourceConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"}],\"name\":\"setUnsafeBlockSigner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unsafeBlockSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b50604051620021903803806200219083398101604081905262000034916200084f565b60006080819052600160a05260c052620000548787878787878762000061565b5050505050505062000a4f565b600054610100900460ff1615808015620000825750600054600160ff909116105b80620000b257506200009f306200027060201b62000a771760201c565b158015620000b2575060005460ff166001145b6200011b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200013f576000805461ff0019166101001790555b620001496200027f565b6200015488620002e7565b606587905560668690556067859055606880546001600160401b0319166001600160401b038616179055620001a7837f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0855565b620001b28262000366565b620001bc620006b1565b6001600160401b0316846001600160401b031610156200021f5760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640162000112565b801562000266576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6001600160a01b03163b151590565b600054610100900460ff16620002db5760405162461bcd60e51b815260206004820152602b60248201526000805160206200217083398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000112565b620002e5620006de565b565b620002f162000745565b6001600160a01b038116620003585760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000112565b6200036381620007a1565b50565b8060a001516001600160801b0316816060015163ffffffff161115620003f55760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840162000112565b6000816040015160ff16116200045c5760405162461bcd60e51b815260206004820152602560248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f722063616e6e6f74604482015264020626520360dc1b606482015260840162000112565b606854608082015182516001600160401b03909216916200047e91906200099e565b63ffffffff161115620004d45760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640162000112565b6000816020015160ff1611620005455760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201526e06965722063616e6e6f74206265203608c1b606482015260840162000112565b8051602082015163ffffffff82169160ff9091169062000567908290620009c9565b620005739190620009fb565b63ffffffff1614620005ee5760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840162000112565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff96871664ffffffffff199095169490941764010000000060ff948516021764ffffffffff60281b191665010000000000939092169290920263ffffffff60301b19161766010000000000009185169190910217600160501b600160f01b0319166a01000000000000000000009390941692909202600160701b600160f01b03191692909217600160701b6001600160801b0390921691909102179055565b606954600090620006d99063ffffffff6a010000000000000000000082048116911662000a2a565b905090565b600054610100900460ff166200073a5760405162461bcd60e51b815260206004820152602b60248201526000805160206200217083398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000112565b620002e533620007a1565b6033546001600160a01b03163314620002e55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000112565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200080b57600080fd5b919050565b805163ffffffff811681146200080b57600080fd5b805160ff811681146200080b57600080fd5b80516001600160801b03811681146200080b57600080fd5b60008060008060008060008789036101808112156200086d57600080fd5b6200087889620007f3565b60208a015160408b015160608c015160808d0151939b50919950975095506001600160401b038082168214620008ad57600080fd5b819550620008be60a08c01620007f3565b945060c060bf1984011215620008d357600080fd5b604051925060c08301915082821081831117156200090157634e487b7160e01b600052604160045260246000fd5b506040526200091360c08a0162000810565b81526200092360e08a0162000825565b6020820152620009376101008a0162000825565b60408201526200094b6101208a0162000810565b60608201526200095f6101408a0162000810565b6080820152620009736101608a0162000837565b60a08201528091505092959891949750929550565b634e487b7160e01b600052601160045260246000fd5b600063ffffffff808316818516808303821115620009c057620009c062000988565b01949350505050565b600063ffffffff80841680620009ef57634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b600063ffffffff8083168185168183048111821515161562000a215762000a2162000988565b02949350505050565b60006001600160401b03828116848216808303821115620009c057620009c062000988565b60805160a05160c0516116f162000a7f600039600061056e015260006105450152600061051c01526116f16000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063b40a817c116100cd578063f2fde38b11610081578063f68016b711610066578063f68016b7146103f7578063f975e9251461040b578063ffa1ad741461041e57600080fd5b8063f2fde38b146103db578063f45e65d8146103ee57600080fd5b8063c9b26f61116100b2578063c9b26f611461028b578063cc731b021461029e578063e81b2c6d146103d257600080fd5b8063b40a817c14610265578063c71973f61461027857600080fd5b80634f16540b11610124578063715018a611610109578063715018a61461022c5780638da5cb5b14610234578063935f029e1461025257600080fd5b80634f16540b146101f057806354fd4d501461021757600080fd5b80630c18c1621461015657806318d13918146101725780631fd19ee1146101875780634add321d146101cf575b600080fd5b61015f60655481565b6040519081526020015b60405180910390f35b6101856101803660046111cf565b610426565b005b7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08545b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610169565b6101d76104ea565b60405167ffffffffffffffff9091168152602001610169565b61015f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b61021f610515565b604051610169919061126b565b6101856105b8565b60335473ffffffffffffffffffffffffffffffffffffffff166101aa565b61018561026036600461127e565b6105cc565b6101856102733660046112b8565b610665565b610185610286366004611410565b610736565b61018561029936600461142c565b61074a565b6103626040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516101699190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61015f60675481565b6101856103e93660046111cf565b61077a565b61015f60665481565b6068546101d79067ffffffffffffffff1681565b610185610419366004611445565b610814565b61015f600081565b61042e610a93565b610456817f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0855565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516104de919061126b565b60405180910390a35050565b6069546000906105109063ffffffff6a01000000000000000000008204811691166114e7565b905090565b60606105407f0000000000000000000000000000000000000000000000000000000000000000610afa565b6105697f0000000000000000000000000000000000000000000000000000000000000000610afa565b6105927f0000000000000000000000000000000000000000000000000000000000000000610afa565b6040516020016105a493929190611513565b604051602081830303815290604052905090565b6105c0610a93565b6105ca6000610c37565b565b6105d4610a93565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610658919061126b565b60405180910390a3505050565b61066d610a93565b6106756104ea565b67ffffffffffffffff168167ffffffffffffffff1610156106dd5760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064015b60405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff831690811790915560408051602080820193909352815180820390930183528101905260026104ad565b61073e610a93565b61074781610cae565b50565b610752610a93565b60678190556040805160208082018490528251808303909101815290820190915260006104ad565b610782610a93565b73ffffffffffffffffffffffffffffffffffffffff811661080b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106d4565b61074781610c37565b600054610100900460ff16158080156108345750600054600160ff909116105b8061084e5750303b15801561084e575060005460ff166001145b6108c05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106d4565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561091e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6109266110a0565b61092f8861077a565b606587905560668690556067859055606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff86161790557f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0883905561099f82610cae565b6109a76104ea565b67ffffffffffffffff168467ffffffffffffffff161015610a0a5760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016106d4565b8015610a6d57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff1633146105ca5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106d4565b606081600003610b3d57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610b675780610b5181611589565b9150610b609050600a836115f0565b9150610b41565b60008167ffffffffffffffff811115610b8257610b826112d3565b6040519080825280601f01601f191660200182016040528015610bac576020820181803683370190505b5090505b8415610c2f57610bc1600183611604565b9150610bce600a8661161b565b610bd990603061162f565b60f81b818381518110610bee57610bee611647565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610c28600a866115f0565b9450610bb0565b949350505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115610d445760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d61782062617365000000000000000000000060648201526084016106d4565b6000816040015160ff1611610dc15760405162461bcd60e51b815260206004820152602560248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f722063616e6e6f7460448201527f206265203000000000000000000000000000000000000000000000000000000060648201526084016106d4565b6068546080820151825167ffffffffffffffff90921691610de29190611676565b63ffffffff161115610e365760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016106d4565b6000816020015160ff1611610eb35760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f742062652030000000000000000000000000000000000060648201526084016106d4565b8051602082015163ffffffff82169160ff90911690610ed3908290611695565b610edd91906116b8565b63ffffffff1614610f565760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d697400000000000000000060648201526084016106d4565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b600054610100900460ff1661111d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106d4565b6105ca600054610100900460ff1661119d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106d4565b6105ca33610c37565b803573ffffffffffffffffffffffffffffffffffffffff811681146111ca57600080fd5b919050565b6000602082840312156111e157600080fd5b6111ea826111a6565b9392505050565b60005b8381101561120c5781810151838201526020016111f4565b8381111561121b576000848401525b50505050565b600081518084526112398160208601602086016111f1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111ea6020830184611221565b6000806040838503121561129157600080fd5b50508035926020909101359150565b803567ffffffffffffffff811681146111ca57600080fd5b6000602082840312156112ca57600080fd5b6111ea826112a0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b803563ffffffff811681146111ca57600080fd5b803560ff811681146111ca57600080fd5b80356fffffffffffffffffffffffffffffffff811681146111ca57600080fd5b600060c0828403121561135957600080fd5b60405160c0810181811067ffffffffffffffff821117156113a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806113b283611302565b81526113c060208401611316565b60208201526113d160408401611316565b60408201526113e260608401611302565b60608201526113f360808401611302565b608082015261140460a08401611327565b60a08201525092915050565b600060c0828403121561142257600080fd5b6111ea8383611347565b60006020828403121561143e57600080fd5b5035919050565b6000806000806000806000610180888a03121561146157600080fd5b61146a886111a6565b965060208801359550604088013594506060880135935061148d608089016112a0565b925061149b60a089016111a6565b91506114aa8960c08a01611347565b905092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851680830382111561150a5761150a6114b8565b01949350505050565b600084516115258184602089016111f1565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611561816001850160208a016111f1565b6001920191820152835161157c8160028401602088016111f1565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036115ba576115ba6114b8565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826115ff576115ff6115c1565b500490565b600082821015611616576116166114b8565b500390565b60008261162a5761162a6115c1565b500690565b60008219821115611642576116426114b8565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff80831681851680830382111561150a5761150a6114b8565b600063ffffffff808416806116ac576116ac6115c1565b92169190910492915050565b600063ffffffff808316818516818304811182151516156116db576116db6114b8565b0294935050505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", } // SystemConfigABI is the input ABI used to generate the binding from. @@ -44,7 +54,7 @@ var SystemConfigABI = SystemConfigMetaData.ABI var SystemConfigBin = SystemConfigMetaData.Bin // DeploySystemConfig deploys a new Ethereum contract, binding an instance of SystemConfig to it. -func DeploySystemConfig(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address, _overhead *big.Int, _scalar *big.Int, _batcherHash [32]byte, _gasLimit uint64, _unsafeBlockSigner common.Address) (common.Address, *types.Transaction, *SystemConfig, error) { +func DeploySystemConfig(auth *bind.TransactOpts, backend bind.ContractBackend, _owner common.Address, _overhead *big.Int, _scalar *big.Int, _batcherHash [32]byte, _gasLimit uint64, _unsafeBlockSigner common.Address, _config ResourceMeteringResourceConfig) (common.Address, *types.Transaction, *SystemConfig, error) { parsed, err := SystemConfigMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -53,7 +63,7 @@ func DeploySystemConfig(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(SystemConfigBin), backend, _owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(SystemConfigBin), backend, _owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner, _config) if err != nil { return common.Address{}, nil, nil, err } @@ -202,37 +212,6 @@ func (_SystemConfig *SystemConfigTransactorRaw) Transact(opts *bind.TransactOpts return _SystemConfig.Contract.contract.Transact(opts, method, params...) } -// MINIMUMGASLIMIT is a free data retrieval call binding the contract method 0x29477e86. -// -// Solidity: function MINIMUM_GAS_LIMIT() view returns(uint64) -func (_SystemConfig *SystemConfigCaller) MINIMUMGASLIMIT(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _SystemConfig.contract.Call(opts, &out, "MINIMUM_GAS_LIMIT") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -// MINIMUMGASLIMIT is a free data retrieval call binding the contract method 0x29477e86. -// -// Solidity: function MINIMUM_GAS_LIMIT() view returns(uint64) -func (_SystemConfig *SystemConfigSession) MINIMUMGASLIMIT() (uint64, error) { - return _SystemConfig.Contract.MINIMUMGASLIMIT(&_SystemConfig.CallOpts) -} - -// MINIMUMGASLIMIT is a free data retrieval call binding the contract method 0x29477e86. -// -// Solidity: function MINIMUM_GAS_LIMIT() view returns(uint64) -func (_SystemConfig *SystemConfigCallerSession) MINIMUMGASLIMIT() (uint64, error) { - return _SystemConfig.Contract.MINIMUMGASLIMIT(&_SystemConfig.CallOpts) -} - // UNSAFEBLOCKSIGNERSLOT is a free data retrieval call binding the contract method 0x4f16540b. // // Solidity: function UNSAFE_BLOCK_SIGNER_SLOT() view returns(bytes32) @@ -357,6 +336,37 @@ func (_SystemConfig *SystemConfigCallerSession) GasLimit() (uint64, error) { return _SystemConfig.Contract.GasLimit(&_SystemConfig.CallOpts) } +// MinimumGasLimit is a free data retrieval call binding the contract method 0x4add321d. +// +// Solidity: function minimumGasLimit() view returns(uint64) +func (_SystemConfig *SystemConfigCaller) MinimumGasLimit(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _SystemConfig.contract.Call(opts, &out, "minimumGasLimit") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// MinimumGasLimit is a free data retrieval call binding the contract method 0x4add321d. +// +// Solidity: function minimumGasLimit() view returns(uint64) +func (_SystemConfig *SystemConfigSession) MinimumGasLimit() (uint64, error) { + return _SystemConfig.Contract.MinimumGasLimit(&_SystemConfig.CallOpts) +} + +// MinimumGasLimit is a free data retrieval call binding the contract method 0x4add321d. +// +// Solidity: function minimumGasLimit() view returns(uint64) +func (_SystemConfig *SystemConfigCallerSession) MinimumGasLimit() (uint64, error) { + return _SystemConfig.Contract.MinimumGasLimit(&_SystemConfig.CallOpts) +} + // Overhead is a free data retrieval call binding the contract method 0x0c18c162. // // Solidity: function overhead() view returns(uint256) @@ -419,6 +429,37 @@ func (_SystemConfig *SystemConfigCallerSession) Owner() (common.Address, error) return _SystemConfig.Contract.Owner(&_SystemConfig.CallOpts) } +// ResourceConfig is a free data retrieval call binding the contract method 0xcc731b02. +// +// Solidity: function resourceConfig() view returns((uint32,uint8,uint8,uint32,uint32,uint128)) +func (_SystemConfig *SystemConfigCaller) ResourceConfig(opts *bind.CallOpts) (ResourceMeteringResourceConfig, error) { + var out []interface{} + err := _SystemConfig.contract.Call(opts, &out, "resourceConfig") + + if err != nil { + return *new(ResourceMeteringResourceConfig), err + } + + out0 := *abi.ConvertType(out[0], new(ResourceMeteringResourceConfig)).(*ResourceMeteringResourceConfig) + + return out0, err + +} + +// ResourceConfig is a free data retrieval call binding the contract method 0xcc731b02. +// +// Solidity: function resourceConfig() view returns((uint32,uint8,uint8,uint32,uint32,uint128)) +func (_SystemConfig *SystemConfigSession) ResourceConfig() (ResourceMeteringResourceConfig, error) { + return _SystemConfig.Contract.ResourceConfig(&_SystemConfig.CallOpts) +} + +// ResourceConfig is a free data retrieval call binding the contract method 0xcc731b02. +// +// Solidity: function resourceConfig() view returns((uint32,uint8,uint8,uint32,uint32,uint128)) +func (_SystemConfig *SystemConfigCallerSession) ResourceConfig() (ResourceMeteringResourceConfig, error) { + return _SystemConfig.Contract.ResourceConfig(&_SystemConfig.CallOpts) +} + // Scalar is a free data retrieval call binding the contract method 0xf45e65d8. // // Solidity: function scalar() view returns(uint256) @@ -512,25 +553,25 @@ func (_SystemConfig *SystemConfigCallerSession) Version() (string, error) { return _SystemConfig.Contract.Version(&_SystemConfig.CallOpts) } -// Initialize is a paid mutator transaction binding the contract method 0x8f974d7f. +// Initialize is a paid mutator transaction binding the contract method 0xf975e925. // -// Solidity: function initialize(address _owner, uint256 _overhead, uint256 _scalar, bytes32 _batcherHash, uint64 _gasLimit, address _unsafeBlockSigner) returns() -func (_SystemConfig *SystemConfigTransactor) Initialize(opts *bind.TransactOpts, _owner common.Address, _overhead *big.Int, _scalar *big.Int, _batcherHash [32]byte, _gasLimit uint64, _unsafeBlockSigner common.Address) (*types.Transaction, error) { - return _SystemConfig.contract.Transact(opts, "initialize", _owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner) +// Solidity: function initialize(address _owner, uint256 _overhead, uint256 _scalar, bytes32 _batcherHash, uint64 _gasLimit, address _unsafeBlockSigner, (uint32,uint8,uint8,uint32,uint32,uint128) _config) returns() +func (_SystemConfig *SystemConfigTransactor) Initialize(opts *bind.TransactOpts, _owner common.Address, _overhead *big.Int, _scalar *big.Int, _batcherHash [32]byte, _gasLimit uint64, _unsafeBlockSigner common.Address, _config ResourceMeteringResourceConfig) (*types.Transaction, error) { + return _SystemConfig.contract.Transact(opts, "initialize", _owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner, _config) } -// Initialize is a paid mutator transaction binding the contract method 0x8f974d7f. +// Initialize is a paid mutator transaction binding the contract method 0xf975e925. // -// Solidity: function initialize(address _owner, uint256 _overhead, uint256 _scalar, bytes32 _batcherHash, uint64 _gasLimit, address _unsafeBlockSigner) returns() -func (_SystemConfig *SystemConfigSession) Initialize(_owner common.Address, _overhead *big.Int, _scalar *big.Int, _batcherHash [32]byte, _gasLimit uint64, _unsafeBlockSigner common.Address) (*types.Transaction, error) { - return _SystemConfig.Contract.Initialize(&_SystemConfig.TransactOpts, _owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner) +// Solidity: function initialize(address _owner, uint256 _overhead, uint256 _scalar, bytes32 _batcherHash, uint64 _gasLimit, address _unsafeBlockSigner, (uint32,uint8,uint8,uint32,uint32,uint128) _config) returns() +func (_SystemConfig *SystemConfigSession) Initialize(_owner common.Address, _overhead *big.Int, _scalar *big.Int, _batcherHash [32]byte, _gasLimit uint64, _unsafeBlockSigner common.Address, _config ResourceMeteringResourceConfig) (*types.Transaction, error) { + return _SystemConfig.Contract.Initialize(&_SystemConfig.TransactOpts, _owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner, _config) } -// Initialize is a paid mutator transaction binding the contract method 0x8f974d7f. +// Initialize is a paid mutator transaction binding the contract method 0xf975e925. // -// Solidity: function initialize(address _owner, uint256 _overhead, uint256 _scalar, bytes32 _batcherHash, uint64 _gasLimit, address _unsafeBlockSigner) returns() -func (_SystemConfig *SystemConfigTransactorSession) Initialize(_owner common.Address, _overhead *big.Int, _scalar *big.Int, _batcherHash [32]byte, _gasLimit uint64, _unsafeBlockSigner common.Address) (*types.Transaction, error) { - return _SystemConfig.Contract.Initialize(&_SystemConfig.TransactOpts, _owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner) +// Solidity: function initialize(address _owner, uint256 _overhead, uint256 _scalar, bytes32 _batcherHash, uint64 _gasLimit, address _unsafeBlockSigner, (uint32,uint8,uint8,uint32,uint32,uint128) _config) returns() +func (_SystemConfig *SystemConfigTransactorSession) Initialize(_owner common.Address, _overhead *big.Int, _scalar *big.Int, _batcherHash [32]byte, _gasLimit uint64, _unsafeBlockSigner common.Address, _config ResourceMeteringResourceConfig) (*types.Transaction, error) { + return _SystemConfig.Contract.Initialize(&_SystemConfig.TransactOpts, _owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner, _config) } // RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. @@ -617,6 +658,27 @@ func (_SystemConfig *SystemConfigTransactorSession) SetGasLimit(_gasLimit uint64 return _SystemConfig.Contract.SetGasLimit(&_SystemConfig.TransactOpts, _gasLimit) } +// SetResourceConfig is a paid mutator transaction binding the contract method 0xc71973f6. +// +// Solidity: function setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128) _config) returns() +func (_SystemConfig *SystemConfigTransactor) SetResourceConfig(opts *bind.TransactOpts, _config ResourceMeteringResourceConfig) (*types.Transaction, error) { + return _SystemConfig.contract.Transact(opts, "setResourceConfig", _config) +} + +// SetResourceConfig is a paid mutator transaction binding the contract method 0xc71973f6. +// +// Solidity: function setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128) _config) returns() +func (_SystemConfig *SystemConfigSession) SetResourceConfig(_config ResourceMeteringResourceConfig) (*types.Transaction, error) { + return _SystemConfig.Contract.SetResourceConfig(&_SystemConfig.TransactOpts, _config) +} + +// SetResourceConfig is a paid mutator transaction binding the contract method 0xc71973f6. +// +// Solidity: function setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128) _config) returns() +func (_SystemConfig *SystemConfigTransactorSession) SetResourceConfig(_config ResourceMeteringResourceConfig) (*types.Transaction, error) { + return _SystemConfig.Contract.SetResourceConfig(&_SystemConfig.TransactOpts, _config) +} + // SetUnsafeBlockSigner is a paid mutator transaction binding the contract method 0x18d13918. // // Solidity: function setUnsafeBlockSigner(address _unsafeBlockSigner) returns() diff --git a/bindings/bindings/systemconfig_more.go b/bindings/bindings/systemconfig_more.go index dde3c8db40..927aa24cd6 100644 --- a/bindings/bindings/systemconfig_more.go +++ b/bindings/bindings/systemconfig_more.go @@ -9,11 +9,11 @@ import ( "github.com/kroma-network/kroma/bindings/solc" ) -const SystemConfigStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)1010_storage\"},{\"astId\":1003,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":1004,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)1009_storage\"},{\"astId\":1005,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"overhead\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_uint256\"},{\"astId\":1006,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"scalar\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_uint256\"},{\"astId\":1007,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"batcherHash\",\"offset\":0,\"slot\":\"103\",\"type\":\"t_bytes32\"},{\"astId\":1008,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"gasLimit\",\"offset\":0,\"slot\":\"104\",\"type\":\"t_uint64\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)1009_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_array(t_uint256)1010_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}" +const SystemConfigStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)1011_storage\"},{\"astId\":1003,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":1004,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)1010_storage\"},{\"astId\":1005,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"overhead\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_uint256\"},{\"astId\":1006,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"scalar\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_uint256\"},{\"astId\":1007,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"batcherHash\",\"offset\":0,\"slot\":\"103\",\"type\":\"t_bytes32\"},{\"astId\":1008,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"gasLimit\",\"offset\":0,\"slot\":\"104\",\"type\":\"t_uint64\"},{\"astId\":1009,\"contract\":\"contracts/L1/SystemConfig.sol:SystemConfig\",\"label\":\"_resourceConfig\",\"offset\":0,\"slot\":\"105\",\"type\":\"t_struct(ResourceConfig)1012_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)1010_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_array(t_uint256)1011_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_struct(ResourceConfig)1012_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ResourceMetering.ResourceConfig\",\"numberOfBytes\":\"32\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint32\":{\"encoding\":\"inplace\",\"label\":\"uint32\",\"numberOfBytes\":\"4\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}" var SystemConfigStorageLayout = new(solc.StorageLayout) -var SystemConfigDeployedBin = "0x608060405234801561001057600080fd5b506004361061011b5760003560e01c80638f974d7f116100b2578063e81b2c6d11610081578063f45e65d811610066578063f45e65d814610286578063f68016b71461028f578063ffa1ad74146102a357600080fd5b8063e81b2c6d1461026a578063f2fde38b1461027357600080fd5b80638f974d7f1461021e578063935f029e14610231578063b40a817c14610244578063c9b26f611461025757600080fd5b80634f16540b116100ee5780634f16540b146101bc57806354fd4d50146101e3578063715018a6146101f85780638da5cb5b1461020057600080fd5b80630c18c1621461012057806318d139181461013c5780631fd19ee11461015157806329477e8614610199575b600080fd5b61012960655481565b6040519081526020015b60405180910390f35b61014f61014a366004610cb6565b6102ab565b005b7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08545b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610133565b6101a3627a120081565b60405167ffffffffffffffff9091168152602001610133565b6101297f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b6101eb61036f565b6040516101339190610d52565b61014f610412565b60335473ffffffffffffffffffffffffffffffffffffffff16610174565b61014f61022c366004610d7d565b610426565b61014f61023f366004610ddc565b6106aa565b61014f610252366004610dfe565b610743565b61014f610265366004610e19565b61081b565b61012960675481565b61014f610281366004610cb6565b61084b565b61012960665481565b6068546101a39067ffffffffffffffff1681565b610129600081565b6102b361091e565b6102db817f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0855565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516103639190610d52565b60405180910390a35050565b606061039a7f000000000000000000000000000000000000000000000000000000000000000061099f565b6103c37f000000000000000000000000000000000000000000000000000000000000000061099f565b6103ec7f000000000000000000000000000000000000000000000000000000000000000061099f565b6040516020016103fe93929190610e32565b604051602081830303815290604052905090565b61041a61091e565b6104246000610adc565b565b600054610100900460ff16158080156104465750600054600160ff909116105b806104605750303b158015610460575060005460ff166001145b6104f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561054f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b627a120067ffffffffffffffff841610156105c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016104e8565b6105ce610b53565b6105d78761084b565b606586905560668590556067849055606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85161790557f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0882905580156106a157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6106b261091e565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516107369190610d52565b60405180910390a3505050565b61074b61091e565b627a120067ffffffffffffffff821610156107c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016104e8565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610332565b61082361091e565b6067819055604080516020808201849052825180830390910181529082019091526000610332565b61085361091e565b73ffffffffffffffffffffffffffffffffffffffff81166108f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016104e8565b6108ff81610adc565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610424576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104e8565b6060816000036109e257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610a0c57806109f681610ed7565b9150610a059050600a83610f3e565b91506109e6565b60008167ffffffffffffffff811115610a2757610a27610f52565b6040519080825280601f01601f191660200182016040528015610a51576020820181803683370190505b5090505b8415610ad457610a66600183610f81565b9150610a73600a86610f98565b610a7e906030610fac565b60f81b818381518110610a9357610a93610fc4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610acd600a86610f3e565b9450610a55565b949350505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610bea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104e8565b610424600054610100900460ff16610c84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104e8565b61042433610adc565b803573ffffffffffffffffffffffffffffffffffffffff81168114610cb157600080fd5b919050565b600060208284031215610cc857600080fd5b610cd182610c8d565b9392505050565b60005b83811015610cf3578181015183820152602001610cdb565b83811115610d02576000848401525b50505050565b60008151808452610d20816020860160208601610cd8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610cd16020830184610d08565b803567ffffffffffffffff81168114610cb157600080fd5b60008060008060008060c08789031215610d9657600080fd5b610d9f87610c8d565b9550602087013594506040870135935060608701359250610dc260808801610d65565b9150610dd060a08801610c8d565b90509295509295509295565b60008060408385031215610def57600080fd5b50508035926020909101359150565b600060208284031215610e1057600080fd5b610cd182610d65565b600060208284031215610e2b57600080fd5b5035919050565b60008451610e44818460208901610cd8565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610e80816001850160208a01610cd8565b60019201918201528351610e9b816002840160208801610cd8565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610f0857610f08610ea8565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610f4d57610f4d610f0f565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015610f9357610f93610ea8565b500390565b600082610fa757610fa7610f0f565b500690565b60008219821115610fbf57610fbf610ea8565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" +var SystemConfigDeployedBin = "0x608060405234801561001057600080fd5b50600436106101515760003560e01c8063b40a817c116100cd578063f2fde38b11610081578063f68016b711610066578063f68016b7146103f7578063f975e9251461040b578063ffa1ad741461041e57600080fd5b8063f2fde38b146103db578063f45e65d8146103ee57600080fd5b8063c9b26f61116100b2578063c9b26f611461028b578063cc731b021461029e578063e81b2c6d146103d257600080fd5b8063b40a817c14610265578063c71973f61461027857600080fd5b80634f16540b11610124578063715018a611610109578063715018a61461022c5780638da5cb5b14610234578063935f029e1461025257600080fd5b80634f16540b146101f057806354fd4d501461021757600080fd5b80630c18c1621461015657806318d13918146101725780631fd19ee1146101875780634add321d146101cf575b600080fd5b61015f60655481565b6040519081526020015b60405180910390f35b6101856101803660046111cf565b610426565b005b7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08545b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610169565b6101d76104ea565b60405167ffffffffffffffff9091168152602001610169565b61015f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b61021f610515565b604051610169919061126b565b6101856105b8565b60335473ffffffffffffffffffffffffffffffffffffffff166101aa565b61018561026036600461127e565b6105cc565b6101856102733660046112b8565b610665565b610185610286366004611410565b610736565b61018561029936600461142c565b61074a565b6103626040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516101699190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61015f60675481565b6101856103e93660046111cf565b61077a565b61015f60665481565b6068546101d79067ffffffffffffffff1681565b610185610419366004611445565b610814565b61015f600081565b61042e610a93565b610456817f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0855565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516104de919061126b565b60405180910390a35050565b6069546000906105109063ffffffff6a01000000000000000000008204811691166114e7565b905090565b60606105407f0000000000000000000000000000000000000000000000000000000000000000610afa565b6105697f0000000000000000000000000000000000000000000000000000000000000000610afa565b6105927f0000000000000000000000000000000000000000000000000000000000000000610afa565b6040516020016105a493929190611513565b604051602081830303815290604052905090565b6105c0610a93565b6105ca6000610c37565b565b6105d4610a93565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610658919061126b565b60405180910390a3505050565b61066d610a93565b6106756104ea565b67ffffffffffffffff168167ffffffffffffffff1610156106dd5760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064015b60405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff831690811790915560408051602080820193909352815180820390930183528101905260026104ad565b61073e610a93565b61074781610cae565b50565b610752610a93565b60678190556040805160208082018490528251808303909101815290820190915260006104ad565b610782610a93565b73ffffffffffffffffffffffffffffffffffffffff811661080b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106d4565b61074781610c37565b600054610100900460ff16158080156108345750600054600160ff909116105b8061084e5750303b15801561084e575060005460ff166001145b6108c05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106d4565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561091e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6109266110a0565b61092f8861077a565b606587905560668690556067859055606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff86161790557f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0883905561099f82610cae565b6109a76104ea565b67ffffffffffffffff168467ffffffffffffffff161015610a0a5760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016106d4565b8015610a6d57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff1633146105ca5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106d4565b606081600003610b3d57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610b675780610b5181611589565b9150610b609050600a836115f0565b9150610b41565b60008167ffffffffffffffff811115610b8257610b826112d3565b6040519080825280601f01601f191660200182016040528015610bac576020820181803683370190505b5090505b8415610c2f57610bc1600183611604565b9150610bce600a8661161b565b610bd990603061162f565b60f81b818381518110610bee57610bee611647565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610c28600a866115f0565b9450610bb0565b949350505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115610d445760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d61782062617365000000000000000000000060648201526084016106d4565b6000816040015160ff1611610dc15760405162461bcd60e51b815260206004820152602560248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f722063616e6e6f7460448201527f206265203000000000000000000000000000000000000000000000000000000060648201526084016106d4565b6068546080820151825167ffffffffffffffff90921691610de29190611676565b63ffffffff161115610e365760405162461bcd60e51b815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016106d4565b6000816020015160ff1611610eb35760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f742062652030000000000000000000000000000000000060648201526084016106d4565b8051602082015163ffffffff82169160ff90911690610ed3908290611695565b610edd91906116b8565b63ffffffff1614610f565760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d697400000000000000000060648201526084016106d4565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b600054610100900460ff1661111d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106d4565b6105ca600054610100900460ff1661119d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106d4565b6105ca33610c37565b803573ffffffffffffffffffffffffffffffffffffffff811681146111ca57600080fd5b919050565b6000602082840312156111e157600080fd5b6111ea826111a6565b9392505050565b60005b8381101561120c5781810151838201526020016111f4565b8381111561121b576000848401525b50505050565b600081518084526112398160208601602086016111f1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111ea6020830184611221565b6000806040838503121561129157600080fd5b50508035926020909101359150565b803567ffffffffffffffff811681146111ca57600080fd5b6000602082840312156112ca57600080fd5b6111ea826112a0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b803563ffffffff811681146111ca57600080fd5b803560ff811681146111ca57600080fd5b80356fffffffffffffffffffffffffffffffff811681146111ca57600080fd5b600060c0828403121561135957600080fd5b60405160c0810181811067ffffffffffffffff821117156113a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806113b283611302565b81526113c060208401611316565b60208201526113d160408401611316565b60408201526113e260608401611302565b60608201526113f360808401611302565b608082015261140460a08401611327565b60a08201525092915050565b600060c0828403121561142257600080fd5b6111ea8383611347565b60006020828403121561143e57600080fd5b5035919050565b6000806000806000806000610180888a03121561146157600080fd5b61146a886111a6565b965060208801359550604088013594506060880135935061148d608089016112a0565b925061149b60a089016111a6565b91506114aa8960c08a01611347565b905092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851680830382111561150a5761150a6114b8565b01949350505050565b600084516115258184602089016111f1565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611561816001850160208a016111f1565b6001920191820152835161157c8160028401602088016111f1565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036115ba576115ba6114b8565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826115ff576115ff6115c1565b500490565b600082821015611616576116166114b8565b500390565b60008261162a5761162a6115c1565b500690565b60008219821115611642576116426114b8565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff80831681851680830382111561150a5761150a6114b8565b600063ffffffff808416806116ac576116ac6115c1565b92169190910492915050565b600063ffffffff808316818516818304811182151516156116db576116db6114b8565b0294935050505056fea164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(SystemConfigStorageLayoutJSON), SystemConfigStorageLayout); err != nil { diff --git a/components/batcher/batcher.go b/components/batcher/batcher.go index b03684ff12..2f977eb31a 100644 --- a/components/batcher/batcher.go +++ b/components/batcher/batcher.go @@ -2,6 +2,7 @@ package batcher import ( "context" + "errors" "fmt" "io" "sync" @@ -57,10 +58,14 @@ func Main(version string, cliCtx *cli.Context) error { batcher, err := NewBatcher(ctx, *batcherCfg, l, m) if err != nil { + l.Error("Unable to create batcher", "err", err) return err } - batcher.Start() + if err := batcher.Start(); err != nil { + l.Error("Unable to start batcher", "err", err) + return err + } <-utils.WaitInterrupt() batcher.Stop(context.Background()) @@ -72,6 +77,7 @@ type Batcher struct { cancelShutdownCtx context.CancelFunc killCtx context.Context cancelKillCtx context.CancelFunc + running bool cfg Config l log.Logger @@ -105,9 +111,14 @@ func NewBatcher(parentCtx context.Context, cfg Config, l log.Logger, m metrics.M }, nil } -func (b *Batcher) Start() { +func (b *Batcher) Start() error { b.l.Info("starting Batcher") + if b.running { + return errors.New("batcher is already running") + } + b.running = true + b.shutdownCtx, b.cancelShutdownCtx = context.WithCancel(context.Background()) b.killCtx, b.cancelKillCtx = context.WithCancel(context.Background()) @@ -115,11 +126,18 @@ func (b *Batcher) Start() { go b.loop() b.l.Info("Batcher started") + + return nil } -func (b *Batcher) Stop(ctx context.Context) { +func (b *Batcher) Stop(ctx context.Context) error { b.l.Info("stopping Batcher") + if !b.running { + return errors.New("batcher is not running") + } + b.running = false + // go routine will call cancelKillCtx() if the passed in ctx is ever Done cancelKill := b.cancelKillCtx wrapped, cancel := context.WithCancel(ctx) @@ -134,6 +152,8 @@ func (b *Batcher) Stop(ctx context.Context) { b.cancelKillCtx() b.l.Info("Batcher stopped") + + return nil } // The following things occur: diff --git a/components/batcher/config.go b/components/batcher/config.go index 937f3b7014..ada5417e8f 100644 --- a/components/batcher/config.go +++ b/components/batcher/config.go @@ -64,6 +64,8 @@ type CLIConfig struct { // channel open. This allows to more eagerly send batcher transactions // during times of low L2 transaction volume. Note that the effective // L1-block distance between batcher transactions is then MaxChannelDuration + // + NumConfirmations because the batcher waits for NumConfirmations blocks + // after sending a batcher tx and only then starts a new channel. // // If 0, duration checks are disabled. MaxChannelDuration uint64 diff --git a/components/batcher/metrics/metrics.go b/components/batcher/metrics/metrics.go index 47a772481c..6f8d32f1fe 100644 --- a/components/batcher/metrics/metrics.go +++ b/components/batcher/metrics/metrics.go @@ -52,7 +52,7 @@ type Metrics struct { Info prometheus.GaugeVec Up prometheus.Gauge - // label by openend, closed, fully_submitted, timed_out + // label by opened, closed, fully_submitted, timed_out ChannelEvs kmetrics.EventVec PendingBlocksCount prometheus.GaugeVec @@ -153,16 +153,16 @@ func (m *Metrics) Serve(ctx context.Context, host string, port int) error { return kmetrics.ListenAndServe(ctx, m.registry, host, port) } +func (m *Metrics) Document() []kmetrics.DocumentedMetric { + return m.factory.Document() +} + func (m *Metrics) StartBalanceMetrics(ctx context.Context, l log.Logger, client *ethclient.Client, account common.Address, ) { kmetrics.LaunchBalanceMetrics(ctx, l, m.registry, m.ns, client, account) } -func (m *Metrics) Document() []kmetrics.DocumentedMetric { - return m.factory.Document() -} - // RecordInfo sets a pseudo-metric that contains versioning and // config info for the kroma-batcher. func (m *Metrics) RecordInfo(version string) { diff --git a/components/node/p2p/mocks/ConnectionGater.go b/components/node/p2p/mocks/ConnectionGater.go index 77c2c93eae..e5595f1b14 100644 --- a/components/node/p2p/mocks/ConnectionGater.go +++ b/components/node/p2p/mocks/ConnectionGater.go @@ -142,6 +142,20 @@ func (_m *ConnectionGater) InterceptUpgraded(_a0 network.Conn) (bool, control.Di return r0, r1 } +// IsBlocked provides a mock function with given fields: p +func (_m *ConnectionGater) IsBlocked(p peer.ID) bool { + ret := _m.Called(p) + + var r0 bool + if rf, ok := ret.Get(0).(func(peer.ID) bool); ok { + r0 = rf(p) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + // ListBlockedAddrs provides a mock function with given fields: func (_m *ConnectionGater) ListBlockedAddrs() []net.IP { ret := _m.Called() diff --git a/components/node/p2p/sync.go b/components/node/p2p/sync.go index f52a745e92..ec18c970c3 100644 --- a/components/node/p2p/sync.go +++ b/components/node/p2p/sync.go @@ -60,7 +60,7 @@ const ( ) func PayloadByNumberProtocolID(l2ChainID *big.Int) protocol.ID { - return protocol.ID(fmt.Sprintf("/opstack/req/payload_by_number/%d/0", l2ChainID)) + return protocol.ID(fmt.Sprintf("/kroma-stack/req/payload_by_number/%d/0", l2ChainID)) } type requestHandlerFn func(ctx context.Context, log log.Logger, stream network.Stream) diff --git a/components/node/rollup/driver/state.go b/components/node/rollup/driver/state.go index 887ab34793..621fe84fa2 100644 --- a/components/node/rollup/driver/state.go +++ b/components/node/rollup/driver/state.go @@ -331,7 +331,7 @@ func (d *Driver) eventLoop() { if !d.driverConfig.ProposerStopped { resp.err <- errors.New("proposer already running") } else if !bytes.Equal(unsafeHead[:], resp.hash[:]) { - resp.err <- fmt.Errorf("block hash does not match: head %d, received %d", unsafeHead.String(), resp.hash.String()) + resp.err <- fmt.Errorf("block hash does not match: head %s, received %s", unsafeHead.String(), resp.hash.String()) } else { d.log.Info("Proposer has been started") d.driverConfig.ProposerStopped = false diff --git a/e2e/actions/block_processor.go b/e2e/actions/block_processor.go new file mode 100644 index 0000000000..9589aebdbd --- /dev/null +++ b/e2e/actions/block_processor.go @@ -0,0 +1,119 @@ +package actions + +import ( + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/misc" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/params" + + "github.com/kroma-network/kroma/components/node/eth" +) + +var ( + ErrExceedsGasLimit = errors.New("tx gas exceeds block gas limit") + ErrUsesTooMuchGas = errors.New("action takes too much gas") +) + +type BlockDataProvider interface { + StateAt(root common.Hash) (*state.StateDB, error) + GetHeader(common.Hash, uint64) *types.Header + Engine() consensus.Engine + GetVMConfig() *vm.Config + Config() *params.ChainConfig + consensus.ChainHeaderReader +} + +type BlockProcessor struct { + header *types.Header + state *state.StateDB + receipts types.Receipts + transactions types.Transactions + gasPool *core.GasPool + dataProvider BlockDataProvider +} + +func NewBlockProcessorFromPayloadAttributes(provider BlockDataProvider, parent common.Hash, params *eth.PayloadAttributes) (*BlockProcessor, error) { + header := &types.Header{ + ParentHash: parent, + Coinbase: params.SuggestedFeeRecipient, + Difficulty: common.Big0, + GasLimit: uint64(*params.GasLimit), + Time: uint64(params.Timestamp), + Extra: nil, + MixDigest: common.Hash(params.PrevRandao), + Nonce: types.EncodeNonce(0), + } + return NewBlockProcessorFromHeader(provider, header) +} + +func NewBlockProcessorFromHeader(provider BlockDataProvider, h *types.Header) (*BlockProcessor, error) { + header := types.CopyHeader(h) // Copy to avoid mutating the original header + + if header.GasLimit > params.MaxGasLimit { + return nil, fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) + } + parentHeader := provider.GetHeaderByHash(header.ParentHash) + if header.Time <= parentHeader.Time { + return nil, errors.New("invalid timestamp") + } + statedb, err := provider.StateAt(parentHeader.Root) + if err != nil { + return nil, fmt.Errorf("get parent state: %w", err) + } + header.Number = new(big.Int).Add(parentHeader.Number, common.Big1) + header.BaseFee = misc.CalcBaseFee(provider.Config(), parentHeader) + header.GasUsed = 0 + gasPool := new(core.GasPool).AddGas(header.GasLimit) + return &BlockProcessor{ + header: header, + state: statedb, + gasPool: gasPool, + dataProvider: provider, + }, nil +} + +func (b *BlockProcessor) CheckTxWithinGasLimit(tx *types.Transaction) error { + if tx.Gas() > b.header.GasLimit { + return fmt.Errorf("%w tx gas: %d, block gas limit: %d", ErrExceedsGasLimit, tx.Gas(), b.header.GasLimit) + } + if tx.Gas() > b.gasPool.Gas() { + return fmt.Errorf("%w: %d, only have %d", ErrUsesTooMuchGas, tx.Gas(), b.gasPool.Gas()) + } + return nil +} + +func (b *BlockProcessor) AddTx(tx *types.Transaction) error { + txIndex := len(b.transactions) + b.state.SetTxContext(tx.Hash(), txIndex) + receipt, err := core.ApplyTransaction(b.dataProvider.Config(), b.dataProvider, &common.Address{}, + b.gasPool, b.state, b.header, tx, &b.header.GasUsed, *b.dataProvider.GetVMConfig()) + if err != nil { + return fmt.Errorf("failed to apply deposit transaction to L2 block (tx %d): %w", txIndex, err) + } + b.receipts = append(b.receipts, receipt) + b.transactions = append(b.transactions, tx) + return nil +} + +func (b *BlockProcessor) Assemble() (*types.Block, error) { + return b.dataProvider.Engine().FinalizeAndAssemble(b.dataProvider, b.header, b.state, b.transactions, nil, b.receipts, nil) +} + +func (b *BlockProcessor) Commit() error { + root, err := b.state.Commit(b.dataProvider.Config().IsEIP158(b.header.Number)) + if err != nil { + return fmt.Errorf("state write error: %w", err) + } + if err := b.state.Database().TrieDB().Commit(root, false); err != nil { + return fmt.Errorf("trie write error: %w", err) + } + return nil +} diff --git a/e2e/actions/blocktime_test.go b/e2e/actions/blocktime_test.go index e2008183fd..5918685af2 100644 --- a/e2e/actions/blocktime_test.go +++ b/e2e/actions/blocktime_test.go @@ -36,7 +36,7 @@ func TestBatchInLastPossibleBlocks(gt *testing.T) { ChainID: sd.L2Cfg.Config.ChainID, Nonce: n, GasTipCap: big.NewInt(2 * params.GWei), - GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)), + GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), Gas: params.TxGas, To: &dp.Addresses.Bob, Value: e2eutils.Ether(2), @@ -147,7 +147,7 @@ func TestLargeL1Gaps(gt *testing.T) { ChainID: sd.L2Cfg.Config.ChainID, Nonce: n, GasTipCap: big.NewInt(2 * params.GWei), - GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)), + GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), Gas: params.TxGas, To: &dp.Addresses.Bob, Value: e2eutils.Ether(2), diff --git a/e2e/actions/fork_test.go b/e2e/actions/fork_test.go index 138cb09c09..35bb88beb0 100644 --- a/e2e/actions/fork_test.go +++ b/e2e/actions/fork_test.go @@ -21,7 +21,7 @@ func TestShapellaL1Fork(gt *testing.T) { _, _, miner, proposer, _, syncer, _, batcher := setupReorgTestActors(t, dp, sd, log) - require.False(t, sd.L1Cfg.Config.IsShanghai(miner.l1Chain.CurrentBlock().Time()), "not active yet") + require.False(t, sd.L1Cfg.Config.IsShanghai(miner.l1Chain.CurrentBlock().Time), "not active yet") // start nodes proposer.ActL2PipelineFull(t) @@ -34,7 +34,7 @@ func TestShapellaL1Fork(gt *testing.T) { // verify Shanghai is active l1Block := miner.l1Chain.CurrentBlock() - require.True(t, sd.L1Cfg.Config.IsShanghai(l1Block.Time())) + require.True(t, sd.L1Cfg.Config.IsShanghai(l1Block.Time)) // build L2 chain up to and including L2 blocks referencing shanghai L1 blocks proposer.ActL1HeadSignal(t) diff --git a/e2e/actions/l1_miner_test.go b/e2e/actions/l1_miner_test.go index de91f5b1ae..cac254cb51 100644 --- a/e2e/actions/l1_miner_test.go +++ b/e2e/actions/l1_miner_test.go @@ -24,6 +24,7 @@ func TestL1Miner_BuildBlock(gt *testing.T) { }) cl := miner.EthClient() + l1Cl := miner.L1Client(t, sd.RollupCfg) signer := types.LatestSigner(sd.L1Cfg.Config) // send a tx to the miner @@ -31,7 +32,7 @@ func TestL1Miner_BuildBlock(gt *testing.T) { ChainID: sd.L1Cfg.Config.ChainID, Nonce: 0, GasTipCap: big.NewInt(2 * params.GWei), - GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)), + GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), Gas: params.TxGas, To: &dp.Addresses.Bob, Value: e2eutils.Ether(2), @@ -42,17 +43,21 @@ func TestL1Miner_BuildBlock(gt *testing.T) { miner.ActL1StartBlock(10)(t) miner.ActL1EndBlock(t) bl := miner.l1Chain.CurrentBlock() - require.Equal(t, uint64(1), bl.NumberU64()) - require.Zero(gt, bl.Transactions().Len()) + _, txs, err := l1Cl.InfoAndTxsByHash(t.Ctx(), bl.Hash()) + require.NoError(t, err) + require.Equal(t, uint64(1), bl.Number.Uint64()) + require.Zero(gt, txs.Len()) // now include the tx when we want it to miner.ActL1StartBlock(10)(t) miner.ActL1IncludeTx(dp.Addresses.Alice)(t) miner.ActL1EndBlock(t) bl = miner.l1Chain.CurrentBlock() - require.Equal(t, uint64(2), bl.NumberU64()) - require.Equal(t, 1, bl.Transactions().Len()) - require.Equal(t, tx.Hash(), bl.Transactions()[0].Hash()) + _, txs, err = l1Cl.InfoAndTxsByHash(t.Ctx(), bl.Hash()) + require.NoError(t, err) + require.Equal(t, uint64(2), bl.Number.Uint64()) + require.Equal(t, 1, txs.Len()) + require.Equal(t, tx.Hash(), txs[0].Hash()) // now make a replica that syncs these two blocks from the miner replica := NewL1Replica(t, log, sd.L1Cfg) diff --git a/e2e/actions/l1_replica.go b/e2e/actions/l1_replica.go index d806b4b98e..50d9d4be49 100644 --- a/e2e/actions/l1_replica.go +++ b/e2e/actions/l1_replica.go @@ -71,6 +71,7 @@ func NewL1Replica(t Testing, log log.Logger, genesis *core.Genesis) *L1Replica { backend, err := eth.New(n, ethCfg) require.NoError(t, err) + backend.Merger().FinalizePoS() n.RegisterAPIs(tracers.APIs(backend.APIBackend)) @@ -102,9 +103,9 @@ func (s *L1Replica) ActL1RewindDepth(depth uint64) Action { t.InvalidAction("cannot rewind L1 past genesis (current: %d, rewind depth: %d)", head, depth) return } - finalized := s.l1Chain.CurrentFinalizedBlock() - if finalized != nil && head < finalized.NumberU64()+depth { - t.InvalidAction("cannot rewind head of chain past finalized block %d with rewind depth %d", finalized.NumberU64(), depth) + finalized := s.l1Chain.CurrentFinalBlock() + if finalized != nil && head < finalized.Number.Uint64()+depth { + t.InvalidAction("cannot rewind head of chain past finalized block %d with rewind depth %d", finalized.Number.Uint64(), depth) return } if err := s.l1Chain.SetHead(head - depth); err != nil { @@ -184,10 +185,10 @@ func (s *L1Replica) L1Client(t Testing, cfg *rollup.Config) *sources.L1Client { } func (s *L1Replica) UnsafeNum() uint64 { - block := s.l1Chain.CurrentBlock() + head := s.l1Chain.CurrentBlock() headNum := uint64(0) - if block != nil { - headNum = block.NumberU64() + if head != nil { + headNum = head.Number.Uint64() } return headNum } @@ -196,16 +197,16 @@ func (s *L1Replica) SafeNum() uint64 { safe := s.l1Chain.CurrentSafeBlock() safeNum := uint64(0) if safe != nil { - safeNum = safe.NumberU64() + safeNum = safe.Number.Uint64() } return safeNum } func (s *L1Replica) FinalizedNum() uint64 { - finalized := s.l1Chain.CurrentFinalizedBlock() + finalized := s.l1Chain.CurrentFinalBlock() finalizedNum := uint64(0) if finalized != nil { - finalizedNum = finalized.NumberU64() + finalizedNum = finalized.Number.Uint64() } return finalizedNum } @@ -218,7 +219,7 @@ func (s *L1Replica) ActL1Finalize(t Testing, num uint64) { t.InvalidAction("need to move forward safe block before moving finalized block") return } - newFinalized := s.l1Chain.GetBlockByNumber(num) + newFinalized := s.l1Chain.GetHeaderByNumber(num) if newFinalized == nil { t.Fatalf("expected block at %d after finalized L1 block %d, safe head is ahead", num, finalizedNum) } @@ -233,7 +234,7 @@ func (s *L1Replica) ActL1FinalizeNext(t Testing) { // ActL1Safe marks the given unsafe block as safe. func (s *L1Replica) ActL1Safe(t Testing, num uint64) { - newSafe := s.l1Chain.GetBlockByNumber(num) + newSafe := s.l1Chain.GetHeaderByNumber(num) if newSafe == nil { t.InvalidAction("could not find L1 block %d, cannot label it as safe", num) return diff --git a/e2e/actions/l1_replica_test.go b/e2e/actions/l1_replica_test.go index 8f641127ce..053aed427b 100644 --- a/e2e/actions/l1_replica_test.go +++ b/e2e/actions/l1_replica_test.go @@ -85,7 +85,7 @@ func TestL1Replica_ActL1Sync(gt *testing.T) { }) syncFromA := replica1.ActL1Sync(canonL1(chainA)) // sync canonical chain A - for replica1.l1Chain.CurrentBlock().NumberU64()+1 < uint64(len(chainA)) { + for replica1.l1Chain.CurrentBlock().Number.Uint64()+1 < uint64(len(chainA)) { syncFromA(t) } require.Equal(t, replica1.l1Chain.CurrentBlock().Hash(), chainA[len(chainA)-1].Hash(), "sync replica1 to head of chain A") @@ -94,7 +94,7 @@ func TestL1Replica_ActL1Sync(gt *testing.T) { // sync new canonical chain B syncFromB := replica1.ActL1Sync(canonL1(chainB)) - for replica1.l1Chain.CurrentBlock().NumberU64()+1 < uint64(len(chainB)) { + for replica1.l1Chain.CurrentBlock().Number.Uint64()+1 < uint64(len(chainB)) { syncFromB(t) } require.Equal(t, replica1.l1Chain.CurrentBlock().Hash(), chainB[len(chainB)-1].Hash(), "sync replica1 to head of chain B") @@ -105,7 +105,7 @@ func TestL1Replica_ActL1Sync(gt *testing.T) { _ = replica2.Close() }) syncFromOther := replica2.ActL1Sync(replica1.CanonL1Chain()) - for replica2.l1Chain.CurrentBlock().NumberU64()+1 < uint64(len(chainB)) { + for replica2.l1Chain.CurrentBlock().Number.Uint64()+1 < uint64(len(chainB)) { syncFromOther(t) } require.Equal(t, replica2.l1Chain.CurrentBlock().Hash(), chainB[len(chainB)-1].Hash(), "sync replica2 to head of chain B") diff --git a/e2e/actions/l2_batcher_test.go b/e2e/actions/l2_batcher_test.go index c75cc123cd..cfa1e2b34f 100644 --- a/e2e/actions/l2_batcher_test.go +++ b/e2e/actions/l2_batcher_test.go @@ -48,7 +48,7 @@ func TestBatcher(gt *testing.T) { ChainID: sd.L2Cfg.Config.ChainID, Nonce: n, GasTipCap: big.NewInt(2 * params.GWei), - GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)), + GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), Gas: params.TxGas, To: &dp.Addresses.Bob, Value: e2eutils.Ether(2), @@ -73,7 +73,10 @@ func TestBatcher(gt *testing.T) { miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) miner.ActL1EndBlock(t) bl := miner.l1Chain.CurrentBlock() - log.Info("bl", "txs", len(bl.Transactions())) + l1Cl := miner.L1Client(t, sd.RollupCfg) + _, txs, err := l1Cl.InfoAndTxsByHash(t.Ctx(), bl.Hash()) + require.NoError(t, err) + log.Info("bl", "txs", len(txs)) // Now make enough L1 blocks that the syncer will have to derive a L2 block // It will also eagerly derive the block from the batcher @@ -384,7 +387,7 @@ func TestExtendedTimeWithoutL1Batches(gt *testing.T) { } // TestBigL2Txs tests a high-throughput case with constrained batcher: -// - Fill 100 L2 blocks to near max-capacity, with txs of 120 KB each +// - Fill 40 L2 blocks to near max-capacity, with txs of 120 KB each // - Buffer the L2 blocks into channels together as much as possible, submit data-txs only when necessary // (just before crossing the max RLP channel size) // - Limit the data-tx size to 40 KB, to force data to be split across multiple data-txs @@ -428,7 +431,7 @@ func TestBigL2Txs(gt *testing.T) { } // build many L2 blocks filled to the brim with large txs of random data - for i := 0; i < 100; i++ { + for i := 0; i < 40; i++ { aliceNonce, err := cl.PendingNonceAt(t.Ctx(), dp.Addresses.Alice) status := proposer.SyncStatus() // build empty L1 blocks as necessary, so the L2 proposer can continue to include txs while not drifting too far out @@ -437,7 +440,7 @@ func TestBigL2Txs(gt *testing.T) { } proposer.ActL1HeadSignal(t) proposer.ActL2StartBlock(t) - baseFee := engine.l2Chain.CurrentBlock().BaseFee() // this will go quite high, since so many consecutive blocks are filled at capacity. + baseFee := engine.l2Chain.CurrentBlock().BaseFee // this will go quite high, since so many consecutive blocks are filled at capacity. // fill the block with large L2 txs from alice for n := aliceNonce; ; n++ { require.NoError(t, err) @@ -447,7 +450,7 @@ func TestBigL2Txs(gt *testing.T) { require.NoError(t, err) gas, err := core.IntrinsicGas(data, nil, false, true, true, false) require.NoError(t, err) - if gas > engine.l2GasPool.Gas() { + if gas > engine.engineApi.RemainingBlockGas() { break } tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ diff --git a/e2e/actions/l2_challenger.go b/e2e/actions/l2_challenger.go index 5368fb555f..49aaaabc3b 100644 --- a/e2e/actions/l2_challenger.go +++ b/e2e/actions/l2_challenger.go @@ -46,21 +46,18 @@ func NewL2Challenger(t Testing, log log.Logger, cfg *ValidatorCfg, l1 *ethclient L2OutputOracleAddr: cfg.OutputOracleAddr, ColosseumAddr: cfg.ColosseumAddr, PollInterval: time.Second, - TxManagerConfig: txmgr.Config{ - ResubmissionTimeout: 5 * time.Second, - ReceiptQueryInterval: time.Second, - NumConfirmations: 1, - SafeAbortNonceTooLowCount: 4, - From: from, - Signer: signer(chainID), + NetworkTimeout: time.Second, + L1Client: l1, + RollupClient: rollupCl, + RollupConfig: rollupConfig, + AllowNonFinalized: cfg.AllowNonFinalized, + ProofFetcher: e2eutils.NewFetcher(log), + TxManager: &txmgr.SimpleTxManager{ + Config: txmgr.Config{ + From: from, + Signer: signer(chainID), + }, }, - L1Client: l1, - RollupClient: rollupCl, - RollupConfig: rollupConfig, - AllowNonFinalized: cfg.AllowNonFinalized, - From: from, - SignerFn: signer(chainID), - ProofFetcher: e2eutils.NewFetcher(log), } challenger, err := validator.NewChallenger(t.Ctx(), validatorCfg, log) @@ -70,7 +67,7 @@ func NewL2Challenger(t Testing, log log.Logger, cfg *ValidatorCfg, l1 *ethclient log: log, l1: l1, challenger: challenger, - address: crypto.PubkeyToAddress(cfg.ValidatorKey.PublicKey), + address: from, } } diff --git a/e2e/actions/l2_engine.go b/e2e/actions/l2_engine.go index f10ba0b89c..0440a4692f 100644 --- a/e2e/actions/l2_engine.go +++ b/e2e/actions/l2_engine.go @@ -3,10 +3,8 @@ package actions import ( "errors" - "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" geth "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/ethconfig" @@ -24,6 +22,7 @@ import ( "github.com/kroma-network/kroma/components/node/rollup" "github.com/kroma-network/kroma/components/node/sources" "github.com/kroma-network/kroma/components/node/testutils" + "github.com/kroma-network/kroma/e2e/e2eutils" ) // L2Engine is an in-memory implementation of the Engine API, @@ -37,22 +36,10 @@ type L2Engine struct { rollupGenesis *rollup.Genesis // L2 evm / chain - l2Chain *core.BlockChain - l2Database ethdb.Database - l2Cfg *core.Genesis - l2Signer types.Signer - - // L2 block building data - l2BuildingHeader *types.Header // block header that we add txs to for block building - l2BuildingState *state.StateDB // state used for block building - l2GasPool *core.GasPool // track gas used of ongoing building - pendingIndices map[common.Address]uint64 // per account, how many txs from the pool were already included in the block, since the pool is lagging behind block mining. - l2Transactions []*types.Transaction // collects txs that were successfully included into current block build - l2Receipts []*types.Receipt // collect receipts of ongoing building - l2ForceEmpty bool // when no additional txs may be processed (i.e. when proposer drift runs out) - l2TxFailed []*types.Transaction // log of failed transactions which could not be included - - payloadID engine.PayloadID // ID of payload that is currently being built + l2Chain *core.BlockChain + l2Signer types.Signer + + engineApi *L2EngineAPI failL2RPC error // mock error } @@ -60,6 +47,38 @@ type L2Engine struct { type EngineOption func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error func NewL2Engine(t Testing, log log.Logger, genesis *core.Genesis, rollupGenesisL1 eth.BlockID, jwtPath string, options ...EngineOption) *L2Engine { + n, ethBackend, apiBackend := newBackend(t, genesis, jwtPath, options) + engineApi := NewL2EngineAPI(log, apiBackend) + chain := ethBackend.BlockChain() + genesisBlock := chain.Genesis() + eng := &L2Engine{ + log: log, + node: n, + eth: ethBackend, + rollupGenesis: &rollup.Genesis{ + L1: rollupGenesisL1, + L2: eth.BlockID{Hash: genesisBlock.Hash(), Number: genesisBlock.NumberU64()}, + L2Time: genesis.Timestamp, + }, + l2Chain: chain, + l2Signer: types.LatestSigner(genesis.Config), + engineApi: engineApi, + } + // register the custom engine API, so we can serve engine requests while having more control + // over proposing of individual txs. + n.RegisterAPIs([]rpc.API{ + { + Namespace: "engine", + Service: eng.engineApi, + Authenticated: true, + }, + }) + require.NoError(t, n.Start(), "failed to start L2 kroma-geth node") + + return eng +} + +func newBackend(t e2eutils.TestingBase, genesis *core.Genesis, jwtPath string, options []EngineOption) (*node.Node, *geth.Ethereum, *engineApiBackend) { ethCfg := ðconfig.Config{ NetworkId: genesis.Config.ChainID.Uint64(), Genesis: genesis, @@ -88,33 +107,26 @@ func NewL2Engine(t Testing, log log.Logger, genesis *core.Genesis, rollupGenesis chain := backend.BlockChain() db := backend.ChainDb() - genesisBlock := chain.Genesis() - eng := &L2Engine{ - log: log, - node: n, - eth: backend, - rollupGenesis: &rollup.Genesis{ - L1: rollupGenesisL1, - L2: eth.BlockID{Hash: genesisBlock.Hash(), Number: genesisBlock.NumberU64()}, - L2Time: genesis.Timestamp, - }, - l2Chain: chain, - l2Database: db, - l2Cfg: genesis, - l2Signer: types.LatestSigner(genesis.Config), + apiBackend := &engineApiBackend{ + BlockChain: chain, + db: db, + genesis: genesis, } - // register the custom engine API, so we can serve engine requests while having more control - // over sequencing of individual txs. - n.RegisterAPIs([]rpc.API{ - { - Namespace: "engine", - Service: (*L2EngineAPI)(eng), - Authenticated: true, - }, - }) - require.NoError(t, n.Start(), "failed to start L2 kroma-geth node") + return n, backend, apiBackend +} - return eng +type engineApiBackend struct { + *core.BlockChain + db ethdb.Database + genesis *core.Genesis +} + +func (e *engineApiBackend) Database() ethdb.Database { + return e.db +} + +func (e *engineApiBackend) Genesis() *core.Genesis { + return e.genesis } func (s *L2Engine) EthClient() *ethclient.Client { @@ -157,39 +169,25 @@ func (e *L2Engine) ActL2RPCFail(t Testing) { // ActL2IncludeTx includes the next transaction from the given address in the block that is being built func (e *L2Engine) ActL2IncludeTx(from common.Address) Action { return func(t Testing) { - if e.l2BuildingHeader == nil { - t.InvalidAction("not currently building a block, cannot include tx from queue") - return - } - if e.l2ForceEmpty { + if e.engineApi.ForcedEmpty() { e.log.Info("Skipping including a transaction because e.L2ForceEmpty is true") - // t.InvalidAction("cannot include any proposer txs") return } - i := e.pendingIndices[from] + i := e.engineApi.PendingIndices(from) txs, q := e.eth.TxPool().ContentFrom(from) if uint64(len(txs)) <= i { t.Fatalf("no pending txs from %s, and have %d unprocessable queued txs from this account", from, len(q)) } tx := txs[i] - if tx.Gas() > e.l2BuildingHeader.GasLimit { - t.Fatalf("tx consumes %d gas, more than available in L2 block %d", tx.Gas(), e.l2BuildingHeader.GasLimit) - } - if tx.Gas() > uint64(*e.l2GasPool) { - t.InvalidAction("action takes too much gas: %d, only have %d", tx.Gas(), uint64(*e.l2GasPool)) - return - } - e.pendingIndices[from] = i + 1 // won't retry the tx - e.l2BuildingState.SetTxContext(tx.Hash(), len(e.l2Transactions)) - receipt, err := core.ApplyTransaction(e.l2Cfg.Config, e.l2Chain, &common.Address{}, - e.l2GasPool, e.l2BuildingState, e.l2BuildingHeader, tx, &e.l2BuildingHeader.GasUsed, *e.l2Chain.GetVMConfig()) - if err != nil { - e.l2TxFailed = append(e.l2TxFailed, tx) - t.Fatalf("failed to apply transaction to L2 block (tx %d): %v", len(e.l2Transactions), err) + err := e.engineApi.IncludeTx(tx, from) + if errors.Is(err, ErrNotBuildingBlock) { + t.InvalidAction(err.Error()) + } else if errors.Is(err, ErrUsesTooMuchGas) { + t.InvalidAction("included tx uses too much gas: %v", err) + } else if err != nil { + t.Fatalf("include tx: %v", err) } - e.l2Receipts = append(e.l2Receipts, receipt) - e.l2Transactions = append(e.l2Transactions, tx) } } diff --git a/e2e/actions/l2_engine_api.go b/e2e/actions/l2_engine_api.go index 5a66c21c00..cec8ec808f 100644 --- a/e2e/actions/l2_engine_api.go +++ b/e2e/actions/l2_engine_api.go @@ -6,31 +6,69 @@ import ( "encoding/binary" "errors" "fmt" - "math/big" "time" "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/misc" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/params" "github.com/kroma-network/kroma/components/node/eth" ) +type EngineBackend interface { + CurrentSafeBlock() *types.Header + CurrentFinalBlock() *types.Header + GetBlockByHash(hash common.Hash) *types.Block + GetBlock(hash common.Hash, number uint64) *types.Block + HasBlockAndState(hash common.Hash, number uint64) bool + GetCanonicalHash(n uint64) common.Hash + + GetVMConfig() *vm.Config + Config() *params.ChainConfig + // Engine retrieves the chain's consensus engine. + Engine() consensus.Engine + + StateAt(root common.Hash) (*state.StateDB, error) + + InsertBlockWithoutSetHead(block *types.Block) error + SetCanonical(head *types.Block) (common.Hash, error) + SetFinalized(header *types.Header) + SetSafe(header *types.Header) + + consensus.ChainHeaderReader +} + // L2EngineAPI wraps an engine actor, and implements the RPC backend required to serve the engine API. // This re-implements some of the Geth API work, but changes the API backend so we can deterministically // build and control the L2 block contents to reach very specific edge cases as desired for testing. -type L2EngineAPI L2Engine +type L2EngineAPI struct { + log log.Logger + backend EngineBackend + + // L2 block building data + blockProcessor *BlockProcessor + pendingIndices map[common.Address]uint64 // per account, how many txs from the pool were already included in the block, since the pool is lagging behind block mining. + l2ForceEmpty bool // when no additional txs may be processed (i.e. when proposer drift runs out) + l2TxFailed []*types.Transaction // log of failed transactions which could not be included + + payloadID engine.PayloadID // ID of payload that is currently being built +} + +func NewL2EngineAPI(log log.Logger, backend EngineBackend) *L2EngineAPI { + return &L2EngineAPI{ + log: log, + backend: backend, + } +} var ( - STATUS_INVALID = ð.ForkchoiceUpdatedResult{PayloadStatus: eth.PayloadStatusV1{Status: eth.ExecutionInvalid}, PayloadID: nil} - STATUS_SYNCING = ð.ForkchoiceUpdatedResult{PayloadStatus: eth.PayloadStatusV1{Status: eth.ExecutionSyncing}, PayloadID: nil} - INVALID_TERMINAL_BLOCK = eth.PayloadStatusV1{Status: eth.ExecutionInvalid, LatestValidHash: &common.Hash{}} + STATUS_INVALID = ð.ForkchoiceUpdatedResult{PayloadStatus: eth.PayloadStatusV1{Status: eth.ExecutionInvalid}, PayloadID: nil} + STATUS_SYNCING = ð.ForkchoiceUpdatedResult{PayloadStatus: eth.PayloadStatusV1{Status: eth.ExecutionSyncing}, PayloadID: nil} ) // computePayloadId computes a pseudo-random payloadid, based on the parameters. @@ -53,42 +91,58 @@ func computePayloadId(headBlockHash common.Hash, params *eth.PayloadAttributes) return out } -func (ea *L2EngineAPI) startBlock(parent common.Hash, params *eth.PayloadAttributes) error { - if ea.l2BuildingHeader != nil { - ea.log.Warn("started building new block without ending previous block", "previous", ea.l2BuildingHeader, "prev_payload_id", ea.payloadID) +func (ea *L2EngineAPI) RemainingBlockGas() uint64 { + if ea.blockProcessor == nil { + return 0 } + return ea.blockProcessor.gasPool.Gas() +} + +func (ea *L2EngineAPI) ForcedEmpty() bool { + return ea.l2ForceEmpty +} + +func (ea *L2EngineAPI) PendingIndices(from common.Address) uint64 { + return ea.pendingIndices[from] +} - parentHeader := ea.l2Chain.GetHeaderByHash(parent) - if parentHeader == nil { - return fmt.Errorf("uknown parent block: %s", parent) +var ErrNotBuildingBlock = errors.New("not currently building a block, cannot include tx from queue") + +func (ea *L2EngineAPI) IncludeTx(tx *types.Transaction, from common.Address) error { + if ea.blockProcessor == nil { + return ErrNotBuildingBlock + } + if ea.l2ForceEmpty { + ea.log.Info("Skipping including a transaction because ea.L2ForceEmpty is true") + return nil } - statedb, err := state.New(parentHeader.Root, state.NewDatabaseWithConfig(ea.l2Database, &trie.Config{ - Zktrie: true, - }), nil) + + err := ea.blockProcessor.CheckTxWithinGasLimit(tx) if err != nil { - return fmt.Errorf("failed to init state db around block %s (state %s): %w", parent, parentHeader.Root, err) + return err } - header := &types.Header{ - ParentHash: parent, - Coinbase: params.SuggestedFeeRecipient, - Difficulty: common.Big0, - Number: new(big.Int).Add(parentHeader.Number, common.Big1), - GasLimit: uint64(*params.GasLimit), - Time: uint64(params.Timestamp), - Extra: nil, - MixDigest: common.Hash(params.PrevRandao), + ea.pendingIndices[from] = ea.pendingIndices[from] + 1 // won't retry the tx + err = ea.blockProcessor.AddTx(tx) + if err != nil { + ea.l2TxFailed = append(ea.l2TxFailed, tx) + return fmt.Errorf("invalid L2 block (tx %d): %w", len(ea.blockProcessor.transactions), err) } + return nil +} - header.BaseFee = misc.CalcBaseFee(ea.l2Cfg.Config, parentHeader) +func (ea *L2EngineAPI) startBlock(parent common.Hash, params *eth.PayloadAttributes) error { + if ea.blockProcessor != nil { + ea.log.Warn("started building new block without ending previous block", "previous", ea.blockProcessor.header, "prev_payload_id", ea.payloadID) + } - ea.l2BuildingHeader = header - ea.l2BuildingState = statedb - ea.l2Receipts = make([]*types.Receipt, 0) - ea.l2Transactions = make([]*types.Transaction, 0) + processor, err := NewBlockProcessorFromPayloadAttributes(ea.backend, parent, params) + if err != nil { + return err + } + ea.blockProcessor = processor ea.pendingIndices = make(map[common.Address]uint64) ea.l2ForceEmpty = params.NoTxPool - ea.l2GasPool = new(core.GasPool).AddGas(header.GasLimit) ea.payloadID = computePayloadId(parent, params) // pre-process the deposits @@ -97,37 +151,25 @@ func (ea *L2EngineAPI) startBlock(parent common.Hash, params *eth.PayloadAttribu if err := tx.UnmarshalBinary(otx); err != nil { return fmt.Errorf("transaction %d is not valid: %w", i, err) } - ea.l2BuildingState.SetTxContext(tx.Hash(), i) - receipt, err := core.ApplyTransaction(ea.l2Cfg.Config, ea.l2Chain, &ea.l2BuildingHeader.Coinbase, - ea.l2GasPool, ea.l2BuildingState, ea.l2BuildingHeader, &tx, &ea.l2BuildingHeader.GasUsed, *ea.l2Chain.GetVMConfig()) + err := ea.blockProcessor.AddTx(&tx) if err != nil { ea.l2TxFailed = append(ea.l2TxFailed, &tx) return fmt.Errorf("failed to apply deposit transaction to L2 block (tx %d): %w", i, err) } - ea.l2Receipts = append(ea.l2Receipts, receipt) - ea.l2Transactions = append(ea.l2Transactions, &tx) } return nil } func (ea *L2EngineAPI) endBlock() (*types.Block, error) { - if ea.l2BuildingHeader == nil { + if ea.blockProcessor == nil { return nil, fmt.Errorf("no block is being built currently (id %s)", ea.payloadID) } - header := ea.l2BuildingHeader - ea.l2BuildingHeader = nil - - header.GasUsed = header.GasLimit - uint64(*ea.l2GasPool) - header.Root = ea.l2BuildingState.IntermediateRoot(ea.l2Cfg.Config.IsEIP158(header.Number)) - block := types.NewBlock(header, ea.l2Transactions, nil, ea.l2Receipts, trie.NewStackTrie(nil)) + processor := ea.blockProcessor + ea.blockProcessor = nil - // Write state changes to db - root, err := ea.l2BuildingState.Commit(ea.l2Cfg.Config.IsEIP158(header.Number)) + block, err := processor.Assemble() if err != nil { - return nil, fmt.Errorf("l2 state write error: %w", err) - } - if err := ea.l2BuildingState.Database().TrieDB().Commit(root, false); err != nil { - return nil, fmt.Errorf("l2 trie write error: %w", err) + return nil, fmt.Errorf("assemble block: %w", err) } return block, nil } @@ -155,31 +197,16 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc // Check whether we have the block yet in our database or not. If not, we'll // need to either trigger a sync, or to reject this forkchoice update for a // reason. - block := ea.l2Chain.GetBlockByHash(state.HeadBlockHash) + block := ea.backend.GetBlockByHash(state.HeadBlockHash) if block == nil { // TODO: syncing not supported yet return STATUS_SYNCING, nil } // Block is known locally, just sanity check that the beacon client does not // attempt to push us back to before the merge. - if block.Difficulty().BitLen() > 0 || block.NumberU64() == 0 { - var ( - td = ea.l2Chain.GetTd(state.HeadBlockHash, block.NumberU64()) - ptd = ea.l2Chain.GetTd(block.ParentHash(), block.NumberU64()-1) - ttd = ea.l2Chain.Config().TerminalTotalDifficulty - ) - if td == nil || (block.NumberU64() > 0 && ptd == nil) { - ea.log.Error("TDs unavailable for TTD check", "number", block.NumberU64(), "hash", state.HeadBlockHash, "td", td, "parent", block.ParentHash(), "ptd", ptd) - return STATUS_INVALID, errors.New("TDs unavailable for TDD check") - } - if td.Cmp(ttd) < 0 { - ea.log.Error("Refusing beacon update to pre-merge", "number", block.NumberU64(), "hash", state.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) - return ð.ForkchoiceUpdatedResult{PayloadStatus: INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil - } - if block.NumberU64() > 0 && ptd.Cmp(ttd) >= 0 { - ea.log.Error("Parent block is already post-ttd", "number", block.NumberU64(), "hash", state.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) - return ð.ForkchoiceUpdatedResult{PayloadStatus: INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil - } + // Note: Differs from kroma-geth implementation as pre-merge blocks are never supported here + if block.Difficulty().BitLen() > 0 { + return STATUS_INVALID, errors.New("pre-merge blocks not supported") } valid := func(id *engine.PayloadID) *eth.ForkchoiceUpdatedResult { return ð.ForkchoiceUpdatedResult{ @@ -187,16 +214,16 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc PayloadID: id, } } - if rawdb.ReadCanonicalHash(ea.l2Database, block.NumberU64()) != state.HeadBlockHash { + if ea.backend.GetCanonicalHash(block.NumberU64()) != state.HeadBlockHash { // Block is not canonical, set head. - if latestValid, err := ea.l2Chain.SetCanonical(block); err != nil { + if latestValid, err := ea.backend.SetCanonical(block); err != nil { return ð.ForkchoiceUpdatedResult{PayloadStatus: eth.PayloadStatusV1{Status: eth.ExecutionInvalid, LatestValidHash: &latestValid}}, err } - } else if ea.l2Chain.CurrentBlock().Hash() == state.HeadBlockHash { + } else if ea.backend.CurrentHeader().Hash() == state.HeadBlockHash { // If the specified head matches with our local head, do nothing and keep // generating the payload. It's a special corner case that a few slots are // missing and we are requested to generate the payload in slot. - } else if ea.l2Chain.Config().Kroma == nil { // minor L2Engine API divergence: allow validators to reorg their own chain + } else if ea.backend.Config().Kroma == nil { // minor L2Engine API divergence: allow validators to reorg their own chain panic("engine not configured as kroma engine") } @@ -204,30 +231,30 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc // chain final and completely in PoS mode. if state.FinalizedBlockHash != (common.Hash{}) { // If the finalized block is not in our canonical tree, somethings wrong - finalBlock := ea.l2Chain.GetBlockByHash(state.FinalizedBlockHash) - if finalBlock == nil { + finalHeader := ea.backend.GetHeaderByHash(state.FinalizedBlockHash) + if finalHeader == nil { ea.log.Warn("Final block not available in database", "hash", state.FinalizedBlockHash) return STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("final block not available in database")) - } else if rawdb.ReadCanonicalHash(ea.l2Database, finalBlock.NumberU64()) != state.FinalizedBlockHash { + } else if ea.backend.GetCanonicalHash(finalHeader.Number.Uint64()) != state.FinalizedBlockHash { ea.log.Warn("Final block not in canonical chain", "number", block.NumberU64(), "hash", state.HeadBlockHash) return STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("final block not in canonical chain")) } // Set the finalized block - ea.l2Chain.SetFinalized(finalBlock) + ea.backend.SetFinalized(finalHeader) } // Check if the safe block hash is in our canonical tree, if not somethings wrong if state.SafeBlockHash != (common.Hash{}) { - safeBlock := ea.l2Chain.GetBlockByHash(state.SafeBlockHash) - if safeBlock == nil { + safeHeader := ea.backend.GetHeaderByHash(state.SafeBlockHash) + if safeHeader == nil { ea.log.Warn("Safe block not available in database") return STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("safe block not available in database")) } - if rawdb.ReadCanonicalHash(ea.l2Database, safeBlock.NumberU64()) != state.SafeBlockHash { + if ea.backend.GetCanonicalHash(safeHeader.Number.Uint64()) != state.SafeBlockHash { ea.log.Warn("Safe block not in canonical chain") return STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("safe block not in canonical chain")) } // Set the safe block - ea.l2Chain.SetSafe(safeBlock) + ea.backend.SetSafe(safeHeader) } // If payload generation was requested, create a new block to be potentially // sealed by the beacon client. The payload will be requested later, and we @@ -272,7 +299,7 @@ func (ea *L2EngineAPI) NewPayloadV1(ctx context.Context, payload *eth.ExecutionP } // If we already have the block locally, ignore the entire execution and just // return a fake success. - if block := ea.l2Chain.GetBlockByHash(payload.BlockHash); block != nil { + if block := ea.backend.GetBlockByHash(payload.BlockHash); block != nil { ea.log.Warn("Ignoring already known beacon payload", "number", payload.BlockNumber, "hash", payload.BlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) hash := block.Hash() return ð.PayloadStatusV1{Status: eth.ExecutionValid, LatestValidHash: &hash}, nil @@ -280,16 +307,23 @@ func (ea *L2EngineAPI) NewPayloadV1(ctx context.Context, payload *eth.ExecutionP // TODO: skipping invalid ancestor check (i.e. not remembering previously failed blocks) - parent := ea.l2Chain.GetBlock(block.ParentHash(), block.NumberU64()-1) + parent := ea.backend.GetBlock(block.ParentHash(), block.NumberU64()-1) if parent == nil { // TODO: hack, saying we accepted if we don't know the parent block. Might want to return critical error if we can't actually sync. return ð.PayloadStatusV1{Status: eth.ExecutionAccepted, LatestValidHash: nil}, nil } - if !ea.l2Chain.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { + + if block.Time() <= parent.Time() { + log.Warn("Invalid timestamp", "parent", block.Time(), "block", block.Time()) + return ea.invalid(errors.New("invalid timestamp"), parent.Header()), nil + } + + if !ea.backend.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { ea.log.Warn("State not available, ignoring new payload") return ð.PayloadStatusV1{Status: eth.ExecutionAccepted}, nil } - if err := ea.l2Chain.InsertBlockWithoutSetHead(block); err != nil { + log.Trace("Inserting block without sethead", "hash", block.Hash(), "number", block.Number) + if err := ea.backend.InsertBlockWithoutSetHead(block); err != nil { ea.log.Warn("NewPayloadV1: inserting block failed", "error", err) // TODO not remembering the payload as invalid return ea.invalid(err, parent.Header()), nil @@ -299,7 +333,7 @@ func (ea *L2EngineAPI) NewPayloadV1(ctx context.Context, payload *eth.ExecutionP } func (ea *L2EngineAPI) invalid(err error, latestValid *types.Header) *eth.PayloadStatusV1 { - currentHash := ea.l2Chain.CurrentBlock().Hash() + currentHash := ea.backend.CurrentHeader().Hash() if latestValid != nil { // Set latest valid hash to 0x0 if parent is PoW block currentHash = common.Hash{} diff --git a/e2e/actions/l2_engine_api_test.go b/e2e/actions/l2_engine_api_test.go new file mode 100644 index 0000000000..499c41c583 --- /dev/null +++ b/e2e/actions/l2_engine_api_test.go @@ -0,0 +1,406 @@ +package actions + +import ( + "context" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" + + "github.com/kroma-network/kroma/components/node/eth" + "github.com/kroma-network/kroma/components/node/rollup/derive" + "github.com/kroma-network/kroma/components/node/testlog" +) + +var ( + gasLimit = eth.Uint64Quantity(30_000_000) + feeRecipient = common.Address{} +) + +func RunEngineAPITests(t *testing.T, createBackend func() EngineBackend) { + t.Run("CreateBlock", func(t *testing.T) { + api := newTestHelper(t, createBackend) + + block := api.addBlock() + api.assert.Equal(block.BlockHash, api.headHash(), "should create and import new block") + }) + + t.Run("IncludeRequiredTransactions", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesis := api.backend.CurrentHeader() + + txData, err := derive.L1InfoDeposit(1, eth.HeaderBlockInfo(genesis), eth.SystemConfig{}) + api.assert.NoError(err) + tx := types.NewTx(txData) + block := api.addBlock(tx) + api.assert.Equal(block.BlockHash, api.headHash(), "should create and import new block") + imported := api.backend.GetBlockByHash(block.BlockHash) + api.assert.Len(imported.Transactions(), 1, "should include transaction") + + api.assert.NotEqual(genesis.Root, block.StateRoot) + newState, err := api.backend.StateAt(common.Hash(block.StateRoot)) + require.NoError(t, err, "imported block state should be available") + require.NotNil(t, newState) + }) + + t.Run("RejectCreatingBlockWithInvalidRequiredTransaction", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesis := api.backend.CurrentHeader() + + txData, err := derive.L1InfoDeposit(1, eth.HeaderBlockInfo(genesis), eth.SystemConfig{}) + api.assert.NoError(err) + txData.Gas = uint64(gasLimit + 1) + tx := types.NewTx(txData) + txRlp, err := tx.MarshalBinary() + api.assert.NoError(err) + + result, err := api.engine.ForkchoiceUpdatedV1(api.ctx, ð.ForkchoiceState{ + HeadBlockHash: genesis.Hash(), + SafeBlockHash: genesis.Hash(), + FinalizedBlockHash: genesis.Hash(), + }, ð.PayloadAttributes{ + Timestamp: eth.Uint64Quantity(genesis.Time + 1), + PrevRandao: eth.Bytes32(genesis.MixDigest), + SuggestedFeeRecipient: feeRecipient, + Transactions: []eth.Data{txRlp}, + NoTxPool: true, + GasLimit: &gasLimit, + }) + api.assert.Error(err) + api.assert.Equal(eth.ExecutionInvalid, result.PayloadStatus.Status) + }) + + t.Run("IgnoreUpdateHeadToOlderBlock", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesisHash := api.headHash() + api.addBlock() + block := api.addBlock() + api.assert.Equal(block.BlockHash, api.headHash(), "should have extended chain") + + api.forkChoiceUpdated(genesisHash, genesisHash, genesisHash) + api.assert.Equal(block.BlockHash, api.headHash(), "should not have reset chain head") + }) + + t.Run("AllowBuildingOnOlderBlock", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesis := api.backend.CurrentHeader() + api.addBlock() + block := api.addBlock() + api.assert.Equal(block.BlockHash, api.headHash(), "should have extended chain") + + payloadID := api.startBlockBuilding(genesis, eth.Uint64Quantity(genesis.Time+3)) + api.assert.Equal(block.BlockHash, api.headHash(), "should not reset chain head when building starts") + + payload := api.getPayload(payloadID) + api.assert.Equal(genesis.Hash(), payload.ParentHash, "should have old block as parent") + + api.newPayload(payload) + api.forkChoiceUpdated(payload.BlockHash, genesis.Hash(), genesis.Hash()) + api.assert.Equal(payload.BlockHash, api.headHash(), "should reorg to block built on old parent") + }) + + t.Run("RejectInvalidBlockHash", func(t *testing.T) { + api := newTestHelper(t, createBackend) + + // Invalid because BlockHash won't be correct (among many other reasons) + block := ð.ExecutionPayload{} + r, err := api.engine.NewPayloadV1(api.ctx, block) + api.assert.NoError(err) + api.assert.Equal(eth.ExecutionInvalidBlockHash, r.Status) + }) + + t.Run("RejectBlockWithInvalidStateTransition", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesis := api.backend.CurrentHeader() + + // Build a valid block + payloadID := api.startBlockBuilding(genesis, eth.Uint64Quantity(genesis.Time+2)) + newBlock := api.getPayload(payloadID) + + // But then make it invalid by changing the state root + newBlock.StateRoot = eth.Bytes32(genesis.TxHash) + updateBlockHash(newBlock) + + r, err := api.engine.NewPayloadV1(api.ctx, newBlock) + api.assert.NoError(err) + api.assert.Equal(eth.ExecutionInvalid, r.Status) + }) + + t.Run("RejectBlockWithSameTimeAsParent", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesis := api.backend.CurrentHeader() + + // Start with a valid time + payloadID := api.startBlockBuilding(genesis, eth.Uint64Quantity(genesis.Time+1)) + newBlock := api.getPayload(payloadID) + + // Then make it invalid to check NewPayload rejects it + newBlock.Timestamp = eth.Uint64Quantity(genesis.Time) + updateBlockHash(newBlock) + + r, err := api.engine.NewPayloadV1(api.ctx, newBlock) + api.assert.NoError(err) + api.assert.Equal(eth.ExecutionInvalid, r.Status) + }) + + t.Run("RejectBlockWithTimeBeforeParent", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesis := api.backend.CurrentHeader() + + // Start with a valid time + payloadID := api.startBlockBuilding(genesis, eth.Uint64Quantity(genesis.Time+1)) + newBlock := api.getPayload(payloadID) + + // Then make it invalid to check NewPayload rejects it + newBlock.Timestamp = eth.Uint64Quantity(genesis.Time - 1) + updateBlockHash(newBlock) + + r, err := api.engine.NewPayloadV1(api.ctx, newBlock) + api.assert.NoError(err) + api.assert.Equal(eth.ExecutionInvalid, r.Status) + }) + + t.Run("RejectCreateBlockWithSameTimeAsParent", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesis := api.backend.CurrentHeader() + + result, err := api.engine.ForkchoiceUpdatedV1(api.ctx, ð.ForkchoiceState{ + HeadBlockHash: genesis.Hash(), + SafeBlockHash: genesis.Hash(), + FinalizedBlockHash: genesis.Hash(), + }, ð.PayloadAttributes{ + Timestamp: eth.Uint64Quantity(genesis.Time), + PrevRandao: eth.Bytes32(genesis.MixDigest), + SuggestedFeeRecipient: feeRecipient, + Transactions: nil, + NoTxPool: true, + GasLimit: &gasLimit, + }) + api.assert.Error(err) + api.assert.Equal(eth.ExecutionInvalid, result.PayloadStatus.Status) + }) + + t.Run("RejectCreateBlockWithTimeBeforeParent", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesis := api.backend.CurrentHeader() + + result, err := api.engine.ForkchoiceUpdatedV1(api.ctx, ð.ForkchoiceState{ + HeadBlockHash: genesis.Hash(), + SafeBlockHash: genesis.Hash(), + FinalizedBlockHash: genesis.Hash(), + }, ð.PayloadAttributes{ + Timestamp: eth.Uint64Quantity(genesis.Time - 1), + PrevRandao: eth.Bytes32(genesis.MixDigest), + SuggestedFeeRecipient: feeRecipient, + Transactions: nil, + NoTxPool: true, + GasLimit: &gasLimit, + }) + api.assert.Error(err) + api.assert.Equal(eth.ExecutionInvalid, result.PayloadStatus.Status) + }) + + t.Run("RejectCreateBlockWithGasLimitAboveMax", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesis := api.backend.CurrentHeader() + + gasLimit := eth.Uint64Quantity(params.MaxGasLimit + 1) + + result, err := api.engine.ForkchoiceUpdatedV1(api.ctx, ð.ForkchoiceState{ + HeadBlockHash: genesis.Hash(), + SafeBlockHash: genesis.Hash(), + FinalizedBlockHash: genesis.Hash(), + }, ð.PayloadAttributes{ + Timestamp: eth.Uint64Quantity(genesis.Time + 1), + PrevRandao: eth.Bytes32(genesis.MixDigest), + SuggestedFeeRecipient: feeRecipient, + Transactions: nil, + NoTxPool: true, + GasLimit: &gasLimit, + }) + api.assert.Error(err) + api.assert.Equal(eth.ExecutionInvalid, result.PayloadStatus.Status) + }) + + t.Run("UpdateSafeAndFinalizedHead", func(t *testing.T) { + api := newTestHelper(t, createBackend) + + finalized := api.addBlock() + safe := api.addBlock() + head := api.addBlock() + + api.forkChoiceUpdated(head.BlockHash, safe.BlockHash, finalized.BlockHash) + api.assert.Equal(head.BlockHash, api.headHash(), "should update head block") + api.assert.Equal(safe.BlockHash, api.safeHash(), "should update safe block") + api.assert.Equal(finalized.BlockHash, api.finalHash(), "should update finalized block") + }) + + t.Run("RejectSafeHeadWhenNotAncestor", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesis := api.backend.CurrentHeader() + + api.addBlock() + chainA2 := api.addBlock() + chainA3 := api.addBlock() + + chainB1 := api.addBlockWithParent(genesis, eth.Uint64Quantity(genesis.Time+3)) + + result, err := api.engine.ForkchoiceUpdatedV1(api.ctx, ð.ForkchoiceState{ + HeadBlockHash: chainA3.BlockHash, + SafeBlockHash: chainB1.BlockHash, + FinalizedBlockHash: chainA2.BlockHash, + }, nil) + api.assert.ErrorContains(err, "Invalid forkchoice state", "should return error from forkChoiceUpdated") + api.assert.Equal(eth.ExecutionInvalid, result.PayloadStatus.Status, "forkChoiceUpdated should return invalid") + api.assert.Nil(result.PayloadID, "should not provide payload ID when invalid") + }) + + t.Run("RejectFinalizedHeadWhenNotAncestor", func(t *testing.T) { + api := newTestHelper(t, createBackend) + genesis := api.backend.CurrentHeader() + + api.addBlock() + chainA2 := api.addBlock() + chainA3 := api.addBlock() + + chainB1 := api.addBlockWithParent(genesis, eth.Uint64Quantity(genesis.Time+3)) + + result, err := api.engine.ForkchoiceUpdatedV1(api.ctx, ð.ForkchoiceState{ + HeadBlockHash: chainA3.BlockHash, + SafeBlockHash: chainA2.BlockHash, + FinalizedBlockHash: chainB1.BlockHash, + }, nil) + api.assert.ErrorContains(err, "Invalid forkchoice state", "should return error from forkChoiceUpdated") + api.assert.Equal(eth.ExecutionInvalid, result.PayloadStatus.Status, "forkChoiceUpdated should return invalid") + api.assert.Nil(result.PayloadID, "should not provide payload ID when invalid") + }) +} + +// Updates the block hash to the expected value based on the other fields in the payload +func updateBlockHash(newBlock *eth.ExecutionPayload) { + // And fix up the block hash + newHash, _ := newBlock.CheckBlockHash() + newBlock.BlockHash = newHash +} + +type testHelper struct { + t *testing.T + ctx context.Context + engine *L2EngineAPI + backend EngineBackend + assert *require.Assertions +} + +func newTestHelper(t *testing.T, createBackend func() EngineBackend) *testHelper { + logger := testlog.Logger(t, log.LvlDebug) + ctx := context.Background() + backend := createBackend() + api := NewL2EngineAPI(logger, backend) + test := &testHelper{ + t: t, + ctx: ctx, + engine: api, + backend: backend, + assert: require.New(t), + } + return test +} + +func (h *testHelper) headHash() common.Hash { + return h.backend.CurrentHeader().Hash() +} + +func (h *testHelper) safeHash() common.Hash { + return h.backend.CurrentSafeBlock().Hash() +} + +func (h *testHelper) finalHash() common.Hash { + return h.backend.CurrentFinalBlock().Hash() +} + +func (h *testHelper) Log(args ...any) { + h.t.Log(args...) +} + +func (h *testHelper) addBlock(txs ...*types.Transaction) *eth.ExecutionPayload { + head := h.backend.CurrentHeader() + return h.addBlockWithParent(head, eth.Uint64Quantity(head.Time+2), txs...) +} + +func (h *testHelper) addBlockWithParent(head *types.Header, timestamp eth.Uint64Quantity, txs ...*types.Transaction) *eth.ExecutionPayload { + prevHead := h.backend.CurrentHeader() + id := h.startBlockBuilding(head, timestamp, txs...) + + block := h.getPayload(id) + h.assert.Equal(timestamp, block.Timestamp, "should create block with correct timestamp") + h.assert.Equal(head.Hash(), block.ParentHash, "should have correct parent") + h.assert.Len(block.Transactions, len(txs)) + + h.newPayload(block) + + // Should not have changed the chain head yet + h.assert.Equal(prevHead, h.backend.CurrentHeader()) + + h.forkChoiceUpdated(block.BlockHash, head.Hash(), head.Hash()) + h.assert.Equal(block.BlockHash, h.backend.CurrentHeader().Hash()) + return block +} + +func (h *testHelper) forkChoiceUpdated(head common.Hash, safe common.Hash, finalized common.Hash) { + h.Log("forkChoiceUpdated", "head", head, "safe", safe, "finalized", finalized) + result, err := h.engine.ForkchoiceUpdatedV1(h.ctx, ð.ForkchoiceState{ + HeadBlockHash: head, + SafeBlockHash: safe, + FinalizedBlockHash: finalized, + }, nil) + h.assert.NoError(err) + h.assert.Equal(eth.ExecutionValid, result.PayloadStatus.Status, "forkChoiceUpdated should return valid") + h.assert.Nil(result.PayloadStatus.ValidationError, "should not have validation error when valid") + h.assert.Nil(result.PayloadID, "should not provide payload ID when block building not requested") +} + +func (h *testHelper) startBlockBuilding(head *types.Header, newBlockTimestamp eth.Uint64Quantity, txs ...*types.Transaction) *eth.PayloadID { + h.Log("Start block building", "head", head.Hash(), "timestamp", newBlockTimestamp) + var txData []eth.Data + for _, tx := range txs { + rlp, err := tx.MarshalBinary() + h.assert.NoError(err, "Failed to marshall tx %v", tx) + txData = append(txData, rlp) + } + result, err := h.engine.ForkchoiceUpdatedV1(h.ctx, ð.ForkchoiceState{ + HeadBlockHash: head.Hash(), + SafeBlockHash: head.Hash(), + FinalizedBlockHash: head.Hash(), + }, ð.PayloadAttributes{ + Timestamp: newBlockTimestamp, + PrevRandao: eth.Bytes32(head.MixDigest), + SuggestedFeeRecipient: feeRecipient, + Transactions: txData, + NoTxPool: true, + GasLimit: &gasLimit, + }) + h.assert.NoError(err) + h.assert.Equal(eth.ExecutionValid, result.PayloadStatus.Status) + id := result.PayloadID + h.assert.NotNil(id) + return id +} + +func (h *testHelper) getPayload(id *eth.PayloadID) *eth.ExecutionPayload { + h.Log("getPayload", "id", id) + block, err := h.engine.GetPayloadV1(h.ctx, *id) + h.assert.NoError(err) + h.assert.NotNil(block) + return block +} + +func (h *testHelper) newPayload(block *eth.ExecutionPayload) { + h.Log("newPayload", "hash", block.BlockHash) + r, err := h.engine.NewPayloadV1(h.ctx, block) + h.assert.NoError(err) + h.assert.Equal(eth.ExecutionValid, r.Status) + h.assert.Nil(r.ValidationError) +} diff --git a/e2e/actions/l2_engine_test.go b/e2e/actions/l2_engine_test.go index e5f1a9d1e6..4123f26483 100644 --- a/e2e/actions/l2_engine_test.go +++ b/e2e/actions/l2_engine_test.go @@ -106,17 +106,17 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) { ChainID: sd.L2Cfg.Config.ChainID, Nonce: 0, GasTipCap: big.NewInt(2 * params.GWei), - GasFeeCap: new(big.Int).Add(engine.l2Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)), + GasFeeCap: new(big.Int).Add(engine.l2Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), Gas: params.TxGas, To: &dp.Addresses.Bob, Value: e2eutils.Ether(2), }) require.NoError(gt, cl.SendTransaction(t.Ctx(), tx)) - buildBlock := func(includeAlice bool) { + l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + buildBlock := func(includeAlice bool, l2Cl *sources.EngineClient) { parent := engine.l2Chain.CurrentBlock() - l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) - require.NoError(t, err) // Now let's ask the engine to build a block fcRes, err := l2Cl.ForkchoiceUpdate(t.Ctx(), ð.ForkchoiceState{ @@ -124,9 +124,9 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) { SafeBlockHash: genesisBlock.Hash(), FinalizedBlockHash: genesisBlock.Hash(), }, ð.PayloadAttributes{ - Timestamp: eth.Uint64Quantity(parent.Time()) + 2, + Timestamp: eth.Uint64Quantity(parent.Time) + 2, PrevRandao: eth.Bytes32{}, - SuggestedFeeRecipient: common.Address{'C'}, + SuggestedFeeRecipient: common.Address{}, Transactions: nil, NoTxPool: false, GasLimit: (*eth.Uint64Quantity)(&sd.RollupCfg.Genesis.SystemConfig.GasLimit), @@ -159,13 +159,19 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) { require.Equal(t, fcRes.PayloadStatus.Status, eth.ExecutionValid) require.Equal(t, payload.BlockHash, engine.l2Chain.CurrentBlock().Hash(), "now payload is canonical") } - buildBlock(false) - require.Zero(t, engine.l2Chain.CurrentBlock().Transactions().Len(), "no tx included") - buildBlock(true) - require.Equal(gt, 1, engine.l2Chain.CurrentBlock().Transactions().Len(), "tx from alice is included") - buildBlock(false) - require.Zero(t, engine.l2Chain.CurrentBlock().Transactions().Len(), "no tx included") - require.Equal(t, uint64(3), engine.l2Chain.CurrentBlock().NumberU64(), "built 3 blocks") + buildBlock(false, l2Cl) + _, txs, err := l2Cl.InfoAndTxsByHash(t.Ctx(), engine.l2Chain.CurrentBlock().Hash()) + require.NoError(t, err) + require.Zero(t, txs.Len(), "no tx included") + buildBlock(true, l2Cl) + _, txs, err = l2Cl.InfoAndTxsByHash(t.Ctx(), engine.l2Chain.CurrentBlock().Hash()) + require.NoError(t, err) + require.Equal(gt, 1, txs.Len(), "tx from alice is included") + buildBlock(false, l2Cl) + _, txs, err = l2Cl.InfoAndTxsByHash(t.Ctx(), engine.l2Chain.CurrentBlock().Hash()) + require.NoError(t, err) + require.Zero(t, txs.Len(), "no tx included") + require.Equal(t, uint64(3), engine.l2Chain.CurrentBlock().Number.Uint64(), "built 3 blocks") } func TestL2EngineAPIFail(gt *testing.T) { @@ -186,3 +192,15 @@ func TestL2EngineAPIFail(gt *testing.T) { require.NoError(t, err) require.Equal(gt, sd.L2Cfg.ToBlock().Hash(), head.Hash(), "expecting engine to start at genesis") } + +func TestEngineAPITests(t *testing.T) { + RunEngineAPITests(t, func() EngineBackend { + jwtPath := e2eutils.WriteDefaultJWT(t) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + sd := e2eutils.Setup(t, dp, defaultAlloc) + n, _, apiBackend := newBackend(t, sd.L2Cfg, jwtPath, nil) + err := n.Start() + require.NoError(t, err) + return apiBackend + }) +} diff --git a/e2e/actions/l2_proposer_test.go b/e2e/actions/l2_proposer_test.go index 0efd7d967d..41043e776a 100644 --- a/e2e/actions/l2_proposer_test.go +++ b/e2e/actions/l2_proposer_test.go @@ -54,7 +54,7 @@ func TestL2Proposer_ProposerDrift(gt *testing.T) { ChainID: sd.L2Cfg.Config.ChainID, Nonce: n, GasTipCap: big.NewInt(2 * params.GWei), - GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee(), big.NewInt(2*params.GWei)), + GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), Gas: params.TxGas, To: &dp.Addresses.Bob, Value: e2eutils.Ether(2), @@ -75,7 +75,7 @@ func TestL2Proposer_ProposerDrift(gt *testing.T) { origin := miner.l1Chain.CurrentBlock() // L2 makes blocks to catch up - for proposer.SyncStatus().UnsafeL2.Time+sd.RollupCfg.BlockTime < origin.Time() { + for proposer.SyncStatus().UnsafeL2.Time+sd.RollupCfg.BlockTime < origin.Time { makeL2BlockWithAliceTx() require.Equal(t, uint64(0), proposer.SyncStatus().UnsafeL2.L1Origin.Number, "no L1 origin change before time matches") } @@ -88,7 +88,7 @@ func TestL2Proposer_ProposerDrift(gt *testing.T) { proposer.ActL1HeadSignal(t) // Make blocks up till the proposer drift is about to surpass, but keep the old L1 origin - for proposer.SyncStatus().UnsafeL2.Time+sd.RollupCfg.BlockTime <= origin.Time()+sd.RollupCfg.MaxProposerDrift { + for proposer.SyncStatus().UnsafeL2.Time+sd.RollupCfg.BlockTime <= origin.Time+sd.RollupCfg.MaxProposerDrift { proposer.ActL2KeepL1Origin(t) makeL2BlockWithAliceTx() require.Equal(t, uint64(1), proposer.SyncStatus().UnsafeL2.L1Origin.Number, "expected to keep old L1 origin") @@ -97,7 +97,7 @@ func TestL2Proposer_ProposerDrift(gt *testing.T) { // We passed the proposer drift: we can still keep the old origin, but can't include any txs proposer.ActL2KeepL1Origin(t) proposer.ActL2StartBlock(t) - require.True(t, engine.l2ForceEmpty, "engine should not be allowed to include anything after proposer drift is surpassed") + require.True(t, engine.engineApi.ForcedEmpty(), "engine should not be allowed to include anything after proposer drift is surpassed") } // This tests a chain halt where the proposer would build an unsafe L2 block with a L1 origin diff --git a/e2e/actions/l2_syncer.go b/e2e/actions/l2_syncer.go index 4577052ec6..f9a71731e8 100644 --- a/e2e/actions/l2_syncer.go +++ b/e2e/actions/l2_syncer.go @@ -149,6 +149,7 @@ func (s *L2Syncer) SyncStatus() *eth.SyncStatus { UnsafeL2: s.L2Unsafe(), SafeL2: s.L2Safe(), FinalizedL2: s.L2Finalized(), + UnsafeL2SyncTarget: s.derivation.UnsafeL2SyncTarget(), } } diff --git a/e2e/actions/l2_syncer_test.go b/e2e/actions/l2_syncer_test.go index 798cf7254e..8e5e1dd20e 100644 --- a/e2e/actions/l2_syncer_test.go +++ b/e2e/actions/l2_syncer_test.go @@ -41,20 +41,20 @@ func TestL2Syncer_ProposerWindow(gt *testing.T) { miner.ActL1SetFeeRecipient(common.Address{'A'}) // Make two proposer windows worth of empty L1 blocks. After we pass the first proposer window, the L2 chain should get blocks - for miner.l1Chain.CurrentBlock().NumberU64() < sd.RollupCfg.ProposerWindowSize*2 { + for miner.l1Chain.CurrentBlock().Number.Uint64() < sd.RollupCfg.ProposerWindowSize*2 { miner.ActL1StartBlock(10)(t) miner.ActL1EndBlock(t) syncer.ActL2PipelineFull(t) - l1Head := miner.l1Chain.CurrentBlock().NumberU64() + l1Head := miner.l1Chain.CurrentBlock().Number.Uint64() expectedL1Origin := uint64(0) // as soon as we complete the proposer window, we force-adopt the L1 origin if l1Head >= sd.RollupCfg.ProposerWindowSize { expectedL1Origin = l1Head - sd.RollupCfg.ProposerWindowSize } require.Equal(t, expectedL1Origin, syncer.SyncStatus().SafeL2.L1Origin.Number, "L1 origin is forced in, given enough L1 blocks pass by") - require.LessOrEqual(t, miner.l1Chain.GetBlockByNumber(expectedL1Origin).Time(), engine.l2Chain.CurrentBlock().Time(), "L2 time higher than L1 origin time") + require.LessOrEqual(t, miner.l1Chain.GetBlockByNumber(expectedL1Origin).Time(), engine.l2Chain.CurrentBlock().Time, "L2 time higher than L1 origin time") } tip2N := syncer.SyncStatus() @@ -75,7 +75,7 @@ func TestL2Syncer_ProposerWindow(gt *testing.T) { syncer.ActL2PipelineFull(t) require.Equal(t, tip2N.SafeL2, syncer.SyncStatus().SafeL2) - for miner.l1Chain.CurrentBlock().NumberU64() < sd.RollupCfg.ProposerWindowSize*2 { + for miner.l1Chain.CurrentBlock().Number.Uint64() < sd.RollupCfg.ProposerWindowSize*2 { miner.ActL1StartBlock(10)(t) miner.ActL1EndBlock(t) } diff --git a/e2e/actions/l2_validator.go b/e2e/actions/l2_validator.go index 30c8dd4227..5d6141a6fd 100644 --- a/e2e/actions/l2_validator.go +++ b/e2e/actions/l2_validator.go @@ -1,21 +1,21 @@ package actions import ( - "context" "crypto/ecdsa" "math/big" "time" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/require" "github.com/kroma-network/kroma/components/node/sources" validator "github.com/kroma-network/kroma/components/validator" - kcrypto "github.com/kroma-network/kroma/utils/service/crypto" "github.com/kroma-network/kroma/utils/service/txmgr" ) @@ -27,56 +27,86 @@ type ValidatorCfg struct { } type L2Validator struct { - log log.Logger - l1 *ethclient.Client - l2os *validator.L2OutputSubmitter - address common.Address - lastTx common.Hash + log log.Logger + l1 *ethclient.Client + l2os *validator.L2OutputSubmitter + address common.Address + privKey *ecdsa.PrivateKey + contractAddr common.Address + lastTx common.Hash } func NewL2Validator(t Testing, log log.Logger, cfg *ValidatorCfg, l1 *ethclient.Client, rollupCl *sources.RollupClient) *L2Validator { - signer := func(chainID *big.Int) kcrypto.SignerFn { - s := kcrypto.PrivateKeySignerFn(cfg.ValidatorKey, chainID) - return func(_ context.Context, addr common.Address, tx *types.Transaction) (*types.Transaction, error) { - return s(addr, tx) - } - } from := crypto.PubkeyToAddress(cfg.ValidatorKey.PublicKey) - chainID, err := l1.ChainID(t.Ctx()) - require.NoError(t, err) - rollupConfig, err := rollupCl.RollupConfig(t.Ctx()) require.NoError(t, err) validatorCfg := validator.Config{ L2OutputOracleAddr: cfg.OutputOracleAddr, PollInterval: time.Second, - TxManagerConfig: txmgr.Config{ - ResubmissionTimeout: 5 * time.Second, - ReceiptQueryInterval: time.Second, - NumConfirmations: 1, - SafeAbortNonceTooLowCount: 4, - From: from, - Signer: signer(chainID), + NetworkTimeout: time.Second, + L1Client: l1, + RollupClient: rollupCl, + RollupConfig: rollupConfig, + AllowNonFinalized: cfg.AllowNonFinalized, + // We use custom signing here instead of using the transaction manager. + TxManager: &txmgr.SimpleTxManager{ + Config: txmgr.Config{From: from}, }, - L1Client: l1, - RollupClient: rollupCl, - RollupConfig: rollupConfig, - AllowNonFinalized: cfg.AllowNonFinalized, - From: from, - SignerFn: signer(chainID), } - l2os, err := validator.NewL2OutputSubmitter(t.Ctx(), validatorCfg, log) + l2os, err := validator.NewL2OutputSubmitter(validatorCfg, log) require.NoError(t, err) return &L2Validator{ - log: log, - l1: l1, - l2os: l2os, - address: crypto.PubkeyToAddress(cfg.ValidatorKey.PublicKey), + log: log, + l1: l1, + l2os: l2os, + address: from, + privKey: cfg.ValidatorKey, + contractAddr: cfg.OutputOracleAddr, + } +} + +// sendTx reimplements creating & sending transactions because we need to do the final send as async in +// the action tests while we do it synchronously in the real system. +func (v *L2Validator) sendTx(t Testing, data []byte) { + gasTipCap := big.NewInt(2 * params.GWei) + pendingHeader, err := v.l1.HeaderByNumber(t.Ctx(), big.NewInt(-1)) + require.NoError(t, err, "need l1 pending header for gas price estimation") + gasFeeCap := new(big.Int).Add(gasTipCap, new(big.Int).Mul(pendingHeader.BaseFee, big.NewInt(2))) + chainID, err := v.l1.ChainID(t.Ctx()) + require.NoError(t, err) + nonce, err := v.l1.NonceAt(t.Ctx(), v.address, nil) + require.NoError(t, err) + + gasLimit, err := v.l1.EstimateGas(t.Ctx(), ethereum.CallMsg{ + From: v.address, + To: &v.contractAddr, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + Data: data, + }) + require.NoError(t, err) + + rawTx := &types.DynamicFeeTx{ + Nonce: nonce, + To: &v.contractAddr, + Data: data, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + Gas: gasLimit, + ChainID: chainID, } + + tx, err := types.SignNewTx(v.privKey, types.LatestSignerForChainID(chainID), rawTx) + require.NoError(t, err, "need to sign tx") + + err = v.l1.SendTransaction(t.Ctx(), tx) + require.NoError(t, err, "need to send tx") + + v.lastTx = tx.Hash() } func (v *L2Validator) CanSubmit(t Testing) bool { @@ -92,13 +122,12 @@ func (v *L2Validator) ActSubmitL2Output(t Testing) { } require.NoError(t, err) - tx, err := v.l2os.CreateSubmitL2OutputTx(t.Ctx(), output) + txData, err := v.l2os.SubmitL2OutputTxData(output) require.NoError(t, err) - err = v.l1.SendTransaction(t.Ctx(), tx) - require.NoError(t, err) - - v.lastTx = tx.Hash() + // Note: Use L1 instead of the output submitter's transaction manager because + // this is non-blocking while the txmgr is blocking & deadlocks the tests + v.sendTx(t, txData) } func (v *L2Validator) LastSubmitL2OutputTx() common.Hash { diff --git a/e2e/actions/system_config_test.go b/e2e/actions/system_config_test.go index 2d7a94d273..4bf3379ff8 100644 --- a/e2e/actions/system_config_test.go +++ b/e2e/actions/system_config_test.go @@ -80,7 +80,7 @@ func TestBatcherKeyRotation(gt *testing.T) { miner.ActL1StartBlock(12)(t) miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t) miner.ActL1EndBlock(t) - cfgChangeL1BlockNum := miner.l1Chain.CurrentBlock().NumberU64() + cfgChangeL1BlockNum := miner.l1Chain.CurrentBlock().Number.Uint64() // sequence L2 blocks, and submit with new batcher proposer.ActL1HeadSignal(t) @@ -200,7 +200,7 @@ func TestGPOParamsChange(gt *testing.T) { miner.ActEmptyBlock(t) proposer.ActL1HeadSignal(t) proposer.ActBuildToL1Head(t) - basefee := miner.l1Chain.CurrentBlock().BaseFee() + basefee := miner.l1Chain.CurrentBlock().BaseFee // alice makes a L2 tx, proposer includes it alice.ActResetTxOpts(t) @@ -238,7 +238,7 @@ func TestGPOParamsChange(gt *testing.T) { miner.ActL1StartBlock(12)(t) miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t) miner.ActL1EndBlock(t) - basefeeGPOUpdate := miner.l1Chain.CurrentBlock().BaseFee() + basefeeGPOUpdate := miner.l1Chain.CurrentBlock().BaseFee // build empty L2 chain, up to but excluding the L2 block with the L1 origin that processes the GPO change proposer.ActL1HeadSignal(t) @@ -274,7 +274,7 @@ func TestGPOParamsChange(gt *testing.T) { // build more L2 blocks, with new L1 origin miner.ActEmptyBlock(t) - basefee = miner.l1Chain.CurrentBlock().BaseFee() + basefee = miner.l1Chain.CurrentBlock().BaseFee proposer.ActL1HeadSignal(t) proposer.ActBuildToL1Head(t) // and Alice makes a tx again @@ -313,7 +313,7 @@ func TestGasLimitChange(gt *testing.T) { proposer.ActL1HeadSignal(t) proposer.ActBuildToL1Head(t) - oldGasLimit := propEngine.l2Chain.CurrentBlock().GasLimit() + oldGasLimit := propEngine.l2Chain.CurrentBlock().GasLimit require.Equal(t, oldGasLimit, uint64(dp.DeployConfig.L2GenesisBlockGasLimit)) // change gas limit on L1 to triple what it was @@ -335,12 +335,12 @@ func TestGasLimitChange(gt *testing.T) { proposer.ActL1HeadSignal(t) proposer.ActBuildToL1HeadExcl(t) - require.Equal(t, oldGasLimit, propEngine.l2Chain.CurrentBlock().GasLimit()) + require.Equal(t, oldGasLimit, propEngine.l2Chain.CurrentBlock().GasLimit) require.Equal(t, uint64(1), proposer.SyncStatus().UnsafeL2.L1Origin.Number) // now include the L1 block with the gaslimit change, and see if it changes as expected proposer.ActBuildToL1Head(t) - require.Equal(t, oldGasLimit*3, propEngine.l2Chain.CurrentBlock().GasLimit()) + require.Equal(t, oldGasLimit*3, propEngine.l2Chain.CurrentBlock().GasLimit) require.Equal(t, uint64(2), proposer.SyncStatus().UnsafeL2.L1Origin.Number) // now submit all this to L1, and see if a syncer can sync and reproduce it diff --git a/e2e/actions/user_test.go b/e2e/actions/user_test.go index f92c856c12..32d9ccb68f 100644 --- a/e2e/actions/user_test.go +++ b/e2e/actions/user_test.go @@ -125,7 +125,7 @@ func runCrossLayerUserTest(gt *testing.T, test blueScheduledTest) { proposer.ActL1HeadSignal(t) // sync proposer build enough blocks to adopt latest L1 origin - for proposer.SyncStatus().UnsafeL2.L1Origin.Number < miner.l1Chain.CurrentBlock().NumberU64() { + for proposer.SyncStatus().UnsafeL2.L1Origin.Number < miner.l1Chain.CurrentBlock().Number.Uint64() { proposer.ActL2StartBlock(t) proposer.ActL2EndBlock(t) } diff --git a/e2e/e2eutils/setup.go b/e2e/e2eutils/setup.go index fad8826944..b72e83e615 100644 --- a/e2e/e2eutils/setup.go +++ b/e2e/e2eutils/setup.go @@ -23,7 +23,7 @@ var testingJWTSecret = [32]byte{123} func WriteDefaultJWT(t TestingBase) string { // Sadly the geth node config cannot load JWT secret from memory, it has to be a file jwtPath := path.Join(t.TempDir(), "jwt_secret") - if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0600); err != nil { + if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0o600); err != nil { t.Fatalf("failed to prepare jwt file for geth: %v", err) } return jwtPath @@ -79,7 +79,7 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams { L1GenesisBlockNonce: 0, CliqueSignerAddress: common.Address{}, // proof of stake, no clique L1GenesisBlockTimestamp: hexutil.Uint64(time.Now().Unix()), - L1GenesisBlockGasLimit: 15_000_000, + L1GenesisBlockGasLimit: 30_000_000, L1GenesisBlockDifficulty: uint64ToBig(1), L1GenesisBlockMixHash: common.Hash{}, L1GenesisBlockCoinbase: common.Address{}, @@ -90,7 +90,7 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams { FinalizationPeriodSeconds: 12, L2GenesisBlockNonce: 0, - L2GenesisBlockGasLimit: 15_000_000, + L2GenesisBlockGasLimit: 30_000_000, L2GenesisBlockDifficulty: uint64ToBig(0), L2GenesisBlockMixHash: common.Hash{}, L2GenesisBlockNumber: 0, diff --git a/e2e/geth.go b/e2e/geth.go index e860c54a35..77c46b158b 100644 --- a/e2e/geth.go +++ b/e2e/geth.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -20,6 +21,7 @@ import ( "github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/node" @@ -124,7 +126,6 @@ func initL1Geth(cfg *SystemConfig, genesis *core.Genesis, opts ...GethOption) (* ethConfig := ðconfig.Config{ NetworkId: cfg.DeployConfig.L1ChainID, Genesis: genesis, - Miner: miner.Config{Etherbase: cfg.DeployConfig.CliqueSignerAddress}, } nodeConfig := &node.Config{ Name: "l1-geth", @@ -140,44 +141,107 @@ func initL1Geth(cfg *SystemConfig, genesis *core.Genesis, opts ...GethOption) (* if err != nil { return nil, nil, err } - - // Clique does not have safe/finalized block info. But we do want to test the usage of that, - // since post-merge L1 has it (incl. Goerli testnet which is already upgraded). So we mock it on top of clique. - l1Node.RegisterLifecycle(&fakeSafeFinalizedL1{ - eth: l1Eth, + // Activate merge + l1Eth.Merger().FinalizePoS() + + // Instead of running a whole beacon node, we run this fake-proof-of-stake sidecar that sequences L1 blocks using the Engine API. + l1Node.RegisterLifecycle(&fakePoS{ + eth: l1Eth, + log: log.Root(), // geth logger is global anyway. Would be nice to replace with a local logger though. + blockTime: cfg.DeployConfig.L1BlockTime, // for testing purposes we make it really fast, otherwise we don't see it finalize in short tests finalizedDistance: 8, safeDistance: 4, + engineAPI: catalyst.NewConsensusAPI(l1Eth), }) return l1Node, l1Eth, nil } -type fakeSafeFinalizedL1 struct { - eth *eth.Ethereum +// fakePoS is a testing-only utility to attach to Geth, +// to build a fake proof-of-stake L1 chain with fixed block time and basic lagging safe/finalized blocks. +type fakePoS struct { + eth *eth.Ethereum + log log.Logger + blockTime uint64 + finalizedDistance uint64 safeDistance uint64 - sub ethereum.Subscription -} -var _ node.Lifecycle = (*fakeSafeFinalizedL1)(nil) + engineAPI *catalyst.ConsensusAPI + sub ethereum.Subscription +} -func (f *fakeSafeFinalizedL1) Start() error { - headChanges := make(chan core.ChainHeadEvent, 10) - headsSub := f.eth.BlockChain().SubscribeChainHeadEvent(headChanges) +func (f *fakePoS) Start() error { f.sub = event.NewSubscription(func(quit <-chan struct{}) error { - defer headsSub.Unsubscribe() + // poll every half a second: enough to catch up with any block time when ticks are missed + t := time.NewTicker(time.Second / 2) for { select { - case head := <-headChanges: - num := head.Block.NumberU64() - if num > f.finalizedDistance { - toFinalize := f.eth.BlockChain().GetBlockByNumber(num - f.finalizedDistance) - f.eth.BlockChain().SetFinalized(toFinalize) + case now := <-t.C: + chain := f.eth.BlockChain() + head := chain.CurrentBlock() + finalized := chain.CurrentFinalBlock() + if finalized == nil { // fallback to genesis if nothing is finalized + finalized = chain.Genesis().Header() + } + safe := chain.CurrentSafeBlock() + if safe == nil { // fallback to finalized if nothing is safe + safe = finalized + } + if head.Number.Uint64() > f.finalizedDistance { // progress finalized block, if we can + finalized = chain.GetHeaderByNumber(head.Number.Uint64() - f.finalizedDistance) + } + if head.Number.Uint64() > f.safeDistance { // progress safe block, if we can + safe = chain.GetHeaderByNumber(head.Number.Uint64() - f.safeDistance) } - if num > f.safeDistance { - toSafe := f.eth.BlockChain().GetBlockByNumber(num - f.safeDistance) - f.eth.BlockChain().SetSafe(toSafe) + // start building the block as soon as we are past the current head time + if head.Time >= uint64(now.Unix()) { + continue + } + res, err := f.engineAPI.ForkchoiceUpdatedV1(engine.ForkchoiceStateV1{ + HeadBlockHash: head.Hash(), + SafeBlockHash: safe.Hash(), + FinalizedBlockHash: finalized.Hash(), + }, &engine.PayloadAttributes{ + Timestamp: head.Time + f.blockTime, + Random: common.Hash{}, + SuggestedFeeRecipient: common.Address{}, + }) + if err != nil { + f.log.Error("failed to start building L1 block", "err", err) + continue + } + if res.PayloadID == nil { + f.log.Error("failed to start block building", "res", res) + continue + } + // wait with sealing, if we are not behind already + delay := time.Until(time.Unix(int64(head.Time+f.blockTime), 0)) + tim := time.NewTimer(delay) + select { + case <-tim.C: + // no-op + case <-quit: + tim.Stop() + return nil + } + payload, err := f.engineAPI.GetPayloadV1(*res.PayloadID) + if err != nil { + f.log.Error("failed to finish building L1 block", "err", err) + continue + } + if _, err := f.engineAPI.NewPayloadV1(*payload); err != nil { + f.log.Error("failed to insert built L1 block", "err", err) + continue + } + if _, err := f.engineAPI.ForkchoiceUpdatedV1(engine.ForkchoiceStateV1{ + HeadBlockHash: payload.BlockHash, + SafeBlockHash: safe.Hash(), + FinalizedBlockHash: finalized.Hash(), + }, nil); err != nil { + f.log.Error("failed to make built L1 block canonical", "err", err) + continue } case <-quit: return nil @@ -187,7 +251,7 @@ func (f *fakeSafeFinalizedL1) Start() error { return nil } -func (f *fakeSafeFinalizedL1) Stop() error { +func (f *fakePoS) Stop() error { f.sub.Unsubscribe() return nil } @@ -300,5 +364,4 @@ func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, pri } } return n, backend, nil - } diff --git a/e2e/kroma_geth.go b/e2e/kroma_geth.go index 9bea8984f7..ea56c53f4e 100644 --- a/e2e/kroma_geth.go +++ b/e2e/kroma_geth.go @@ -76,7 +76,7 @@ func NewKromaGeth(t *testing.T, ctx context.Context, cfg *SystemConfig) (*KromaG require.Nil(t, node.Start()) auth := rpc.WithHTTPAuth(gn.NewJWTAuth(cfg.JWTSecret)) - l2Node, err := client.NewRPC(ctx, logger, node.WSAuthEndpoint(), auth) + l2Node, err := client.NewRPC(ctx, logger, node.WSAuthEndpoint(), client.WithGethRPCOptions(auth)) require.Nil(t, err) // Finally create the engine client diff --git a/e2e/kroma_geth_test.go b/e2e/kroma_geth_test.go index cf98c2082f..6eba82458e 100644 --- a/e2e/kroma_geth_test.go +++ b/e2e/kroma_geth_test.go @@ -16,6 +16,7 @@ import ( // TestMissingGasLimit tests that kroma-geth cannot build a block without gas limit while kroma is active in the chain config. func TestMissingGasLimit(t *testing.T) { + parallel(t) cfg := DefaultSystemConfig(t) cfg.DeployConfig.FundDevAccounts = false ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) @@ -38,6 +39,7 @@ func TestMissingGasLimit(t *testing.T) { // TestInvalidDepositInFCU runs an invalid deposit through a FCU/GetPayload/NewPayload/FCU set of calls. // This tests that deposits must always allow the block to be built even if they are invalid. func TestInvalidDepositInFCU(t *testing.T) { + parallel(t) cfg := DefaultSystemConfig(t) cfg.DeployConfig.FundDevAccounts = false ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) diff --git a/e2e/setup.go b/e2e/setup.go index 66b4786bef..9e1bdef016 100644 --- a/e2e/setup.go +++ b/e2e/setup.go @@ -36,14 +36,28 @@ import ( "github.com/kroma-network/kroma/components/node/sources" "github.com/kroma-network/kroma/components/node/testlog" validator "github.com/kroma-network/kroma/components/validator" + validatormetrics "github.com/kroma-network/kroma/components/validator/metrics" "github.com/kroma-network/kroma/e2e/e2eutils" "github.com/kroma-network/kroma/utils/chain-ops/genesis" klog "github.com/kroma-network/kroma/utils/service/log" + "github.com/kroma-network/kroma/utils/service/txmgr" ) -var ( - testingJWTSecret = [32]byte{123} -) +var testingJWTSecret = [32]byte{123} + +func newTxMgrConfig(l1Addr string, privKey *ecdsa.PrivateKey) txmgr.CLIConfig { + return txmgr.CLIConfig{ + L1RPCURL: l1Addr, + PrivateKey: hexPriv(privKey), + NumConfirmations: 1, + SafeAbortNonceTooLowCount: 3, + ResubmissionTimeout: 3 * time.Second, + ReceiptQueryInterval: 50 * time.Millisecond, + NetworkTimeout: 2 * time.Second, + TxSendTimeout: 10 * time.Minute, + TxNotInMempoolTimeout: 2 * time.Minute, + } +} func DefaultSystemConfig(t *testing.T) SystemConfig { secrets, err := e2eutils.DefaultMnemonicConfig.Secrets() @@ -53,7 +67,7 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { deployConfig := &genesis.DeployConfig{ L1ChainID: 900, L2ChainID: 901, - L2BlockTime: 2, + L2BlockTime: 1, FinalizationPeriodSeconds: 60 * 60 * 24, MaxProposerDrift: 10, @@ -74,9 +88,9 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { L1BlockTime: 2, L1GenesisBlockNonce: 4660, - CliqueSignerAddress: addresses.CliqueSigner, + CliqueSignerAddress: common.Address{}, // e2e used to run Clique, but now uses fake Proof of Stake. L1GenesisBlockTimestamp: hexutil.Uint64(time.Now().Unix()), - L1GenesisBlockGasLimit: 8_000_000, + L1GenesisBlockGasLimit: 30_000_000, L1GenesisBlockDifficulty: uint642big(1), L1GenesisBlockMixHash: common.Hash{}, L1GenesisBlockCoinbase: common.Address{}, @@ -86,7 +100,7 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { L1GenesisBlockBaseFeePerGas: uint642big(7), L2GenesisBlockNonce: 0, - L2GenesisBlockGasLimit: 8_000_000, + L2GenesisBlockGasLimit: 30_000_000, L2GenesisBlockDifficulty: uint642big(1), L2GenesisBlockMixHash: common.Hash{}, L2GenesisBlockNumber: 0, @@ -166,7 +180,7 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { func writeDefaultJWT(t *testing.T) string { // Sadly the geth node config cannot load JWT secret from memory, it has to be a file jwtPath := path.Join(t.TempDir(), "jwt_secret") - if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0600); err != nil { + if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0o600); err != nil { t.Fatalf("failed to prepare jwt file for geth: %v", err) } return jwtPath @@ -198,8 +212,14 @@ type SystemConfig struct { // Any node name not in the topology will not have p2p enabled. P2PTopology map[string][]string + // Enables req-resp sync in the P2P nodes + P2PReqRespSync bool + // If the validator can make outputs for L2 blocks derived from L1 blocks which are not finalized on L1 yet. NonFinalizedOutputs bool + + // Explicitly disable batcher, for tests that rely on unsafe L2 payloads + DisableBatcher bool } type System struct { @@ -207,6 +227,8 @@ type System struct { RollupConfig *rollup.Config + L2GenesisCfg *core.Genesis + // Connections to running nodes Nodes map[string]*node.Node Backends map[string]*geth_eth.Ethereum @@ -222,7 +244,9 @@ func (sys *System) Close() { sys.Validator.Stop() } if sys.Batcher != nil { - sys.Batcher.Stop() + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + sys.Batcher.Stop(ctx) } for _, node := range sys.RollupNodes { @@ -316,6 +340,7 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { if err != nil { return nil, err } + sys.L2GenesisCfg = l2Genesis for addr, amount := range cfg.Premine { if existing, ok := l2Genesis.Alloc[addr]; ok { l2Genesis.Alloc[addr] = core.GenesisAccount{ @@ -384,11 +409,6 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { didErrAfterStart = true return nil, err } - err = l1Backend.StartMining(1) - if err != nil { - didErrAfterStart = true - return nil, err - } for name, node := range sys.Nodes { if name == "l1" { continue @@ -403,26 +423,13 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { // Configure connections to L1 and L2 for rollup nodes. // TODO: refactor testing to use in-process rpc connections instead of websockets. - l1EndpointConfig := l1Node.WSEndpoint() - useHTTP := os.Getenv("E2E_USE_HTTP") == "true" - if useHTTP { - log.Info("using HTTP client") - l1EndpointConfig = l1Node.HTTPEndpoint() - } - for name, rollupCfg := range cfg.Nodes { - l2EndpointConfig := sys.Nodes[name].WSAuthEndpoint() - if useHTTP { - l2EndpointConfig = sys.Nodes[name].HTTPAuthEndpoint() - } - rollupCfg.L1 = &rollupNode.L1EndpointConfig{ - L1NodeAddr: l1EndpointConfig, - L1TrustRPC: false, - L1RPCKind: sources.RPCKindBasic, - } - rollupCfg.L2 = &rollupNode.L2EndpointConfig{ - L2EngineAddr: l2EndpointConfig, - L2EngineJWTSecret: cfg.JWTSecret, + configureL1(rollupCfg, l1Node) + configureL2(rollupCfg, sys.Nodes[name], cfg.JWTSecret) + + rollupCfg.L2Sync = &rollupNode.PreparedL2SyncEndpoint{ + Client: nil, + TrustRPC: false, } } @@ -471,9 +478,10 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { // TODO we can enable discv5 in the testnodes to test discovery of new peers. // Would need to mock though, and the discv5 implementation does not provide nice mocks here. p := &p2p.Prepared{ - HostP2P: h, - LocalNode: nil, - UDPv5: nil, + HostP2P: h, + LocalNode: nil, + UDPv5: nil, + EnableReqRespSync: cfg.P2PReqRespSync, } p2pNodes[name] = p return p, nil @@ -566,30 +574,27 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { // Validator (L2 Output Submitter + Challenger) validatorCliCfg := validator.CLIConfig{ - L1EthRpc: sys.Nodes["l1"].WSEndpoint(), - RollupRpc: sys.RollupNodes["proposer"].HTTPEndpoint(), - L2OOAddress: predeploys.DevL2OutputOracleAddr.String(), - ColosseumAddress: predeploys.DevColosseumAddr.String(), - PollInterval: 50 * time.Millisecond, - NumConfirmations: 1, - ResubmissionTimeout: 3 * time.Second, - SafeAbortNonceTooLowCount: 3, - AllowNonFinalized: cfg.NonFinalizedOutputs, + L1EthRpc: sys.Nodes["l1"].WSEndpoint(), + RollupRpc: sys.RollupNodes["proposer"].HTTPEndpoint(), + L2OOAddress: predeploys.DevL2OutputOracleAddr.String(), + ColosseumAddress: predeploys.DevColosseumAddr.String(), + PollInterval: 50 * time.Millisecond, + AllowNonFinalized: cfg.NonFinalizedOutputs, + TxMgrConfig: newTxMgrConfig(sys.Nodes["l1"].WSEndpoint(), cfg.Secrets.Validator), LogConfig: klog.CLIConfig{ Level: "info", Format: "text", }, - PrivateKey: hexPriv(cfg.Secrets.Validator), ProverGrpc: "http://0.0.0.0:0", } - validatorCfg, err := validator.NewValidatorConfig(validatorCliCfg, sys.cfg.Loggers["validator"]) + validatorCfg, err := validator.NewValidatorConfig(validatorCliCfg, sys.cfg.Loggers["validator"], validatormetrics.NoopMetrics) if err != nil { return nil, fmt.Errorf("unable to init validator config: %w", err) } // replace to mock fetcher validatorCfg.ProofFetcher = e2eutils.NewFetcher(sys.cfg.Loggers["validator"]) - sys.Validator, err = validator.NewValidator(context.Background(), *validatorCfg, sys.cfg.Loggers["validator"]) + sys.Validator, err = validator.NewValidator(context.Background(), *validatorCfg, sys.cfg.Loggers["validator"], validatormetrics.NoopMetrics) if err != nil { return nil, fmt.Errorf("unable to setup validator: %w", err) } @@ -598,24 +603,21 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { // Batcher (Batch Submitter) batcherCliCfg := batcher.CLIConfig{ - L1EthRpc: sys.Nodes["l1"].WSEndpoint(), - L2EthRpc: sys.Nodes["proposer"].WSEndpoint(), - RollupRpc: sys.RollupNodes["proposer"].HTTPEndpoint(), - MaxChannelDuration: 1, - MaxL1TxSize: 120_000, - TargetL1TxSize: 100_000, - TargetNumFrames: 1, - ApproxComprRatio: 0.4, - SubSafetyMargin: 4, - PollInterval: 50 * time.Millisecond, - NumConfirmations: 1, - ResubmissionTimeout: 5 * time.Second, - SafeAbortNonceTooLowCount: 3, + L1EthRpc: sys.Nodes["l1"].WSEndpoint(), + L2EthRpc: sys.Nodes["proposer"].WSEndpoint(), + RollupRpc: sys.RollupNodes["proposer"].HTTPEndpoint(), + MaxChannelDuration: 1, + MaxL1TxSize: 120_000, + TargetL1TxSize: 100_000, + TargetNumFrames: 1, + ApproxComprRatio: 0.4, + SubSafetyMargin: 4, + PollInterval: 50 * time.Millisecond, + TxMgrConfig: newTxMgrConfig(sys.Nodes["l1"].WSEndpoint(), cfg.Secrets.Batcher), LogConfig: klog.CLIConfig{ Level: "info", Format: "text", }, - PrivateKey: hexPriv(cfg.Secrets.Batcher), } batcherCfg, err := batcher.NewBatcherConfig(batcherCliCfg, sys.cfg.Loggers["batcher"], batchermetrics.NoopMetrics) @@ -627,11 +629,46 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { return nil, fmt.Errorf("failed to setup batcher: %w", err) } - sys.Batcher.Start() + // Batcher may be enabled later + if !sys.cfg.DisableBatcher { + if err := sys.Batcher.Start(); err != nil { + return nil, fmt.Errorf("unable to start batcher: %w", err) + } + } return sys, nil } +func configureL1(rollupNodeCfg *rollupNode.Config, l1Node *node.Node) { + l1EndpointConfig := l1Node.WSEndpoint() + useHTTP := os.Getenv("E2E_USE_HTTP") == "true" + if useHTTP { + log.Info("using HTTP client") + l1EndpointConfig = l1Node.HTTPEndpoint() + } + rollupNodeCfg.L1 = &rollupNode.L1EndpointConfig{ + L1NodeAddr: l1EndpointConfig, + L1TrustRPC: false, + L1RPCKind: sources.RPCKindBasic, + RateLimit: 0, + BatchSize: 20, + HttpPollInterval: time.Millisecond * 100, + } +} + +func configureL2(rollupNodeCfg *rollupNode.Config, l2Node *node.Node, jwtSecret [32]byte) { + useHTTP := os.Getenv("E2E_USE_HTTP") == "true" + l2EndpointConfig := l2Node.WSAuthEndpoint() + if useHTTP { + l2EndpointConfig = l2Node.HTTPAuthEndpoint() + } + + rollupNodeCfg.L2 = &rollupNode.L2EndpointConfig{ + L2EngineAddr: l2EndpointConfig, + L2EngineJWTSecret: jwtSecret, + } +} + func (cfg SystemConfig) L1ChainIDBig() *big.Int { return new(big.Int).SetUint64(cfg.DeployConfig.L1ChainID) } diff --git a/e2e/system_test.go b/e2e/system_test.go index a995c70473..279c3d1e23 100644 --- a/e2e/system_test.go +++ b/e2e/system_test.go @@ -28,6 +28,7 @@ import ( "github.com/kroma-network/kroma/bindings/predeploys" "github.com/kroma-network/kroma/components/node/client" "github.com/kroma-network/kroma/components/node/eth" + "github.com/kroma-network/kroma/components/node/metrics" rollupNode "github.com/kroma-network/kroma/components/node/node" "github.com/kroma-network/kroma/components/node/p2p" "github.com/kroma-network/kroma/components/node/rollup" @@ -36,6 +37,7 @@ import ( "github.com/kroma-network/kroma/components/node/sources" "github.com/kroma-network/kroma/components/node/testlog" "github.com/kroma-network/kroma/components/node/withdrawals" + kpprof "github.com/kroma-network/kroma/utils/service/pprof" ) var enableParallelTesting bool = true @@ -94,8 +96,8 @@ func TestL2OutputSubmitter(t *testing.T) { // when it creates it's first block and uses and old L1 Origin. It then does not submit a batch // for that block and subsequently reorgs to match what the syncer derives when running the // reconciliation process. - l2Syncer := sys.Clients["syncer"] - _, err = waitForL2Block(big.NewInt(6), l2Syncer, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + l2Sync := sys.Clients["syncer"] + _, err = waitForL2Block(big.NewInt(6), l2Sync, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) require.Nil(t, err) // Wait for batch submitter to update L2 output oracle. @@ -307,7 +309,7 @@ func TestPendingGasLimit(t *testing.T) { cfg := DefaultSystemConfig(t) // configure the L2 gas limit to be high, and the pending gas limits to be lower for resource saving. - cfg.DeployConfig.L2GenesisBlockGasLimit = 20_000_000 + cfg.DeployConfig.L2GenesisBlockGasLimit = 30_000_000 cfg.GethOptions["proposer"] = []GethOption{ func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { ethCfg.Miner.GasCeil = 10_000_000 @@ -345,8 +347,8 @@ func TestPendingGasLimit(t *testing.T) { for { checkGasLimit(l2Prop, big.NewInt(-1), 10_000_000) checkGasLimit(l2Sync, big.NewInt(-1), 9_000_000) - checkGasLimit(l2Prop, nil, 20_000_000) - latestSyncHeader := checkGasLimit(l2Sync, nil, 20_000_000) + checkGasLimit(l2Prop, nil, 30_000_000) + latestSyncHeader := checkGasLimit(l2Sync, nil, 30_000_000) // Stop once the syncer passes genesis: // this implies we checked a new block from the proposer, on both proposer and syncer nodes. @@ -410,7 +412,7 @@ func TestMintOnRevertedDeposit(t *testing.T) { defer sys.Close() l1Client := sys.Clients["l1"] - l2Syncer := sys.Clients["syncer"] + l2Sync := sys.Clients["syncer"] // Find deposit contract depositContract, err := bindings.NewKromaPortal(predeploys.DevKromaPortalAddr, l1Client) @@ -424,12 +426,12 @@ func TestMintOnRevertedDeposit(t *testing.T) { fromAddr := opts.From ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) - startBalance, err := l2Syncer.BalanceAt(ctx, fromAddr, nil) + startBalance, err := l2Sync.BalanceAt(ctx, fromAddr, nil) cancel() require.Nil(t, err) ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) - startNonce, err := l2Syncer.NonceAt(ctx, fromAddr, nil) + startNonce, err := l2Sync.NonceAt(ctx, fromAddr, nil) require.NoError(t, err) cancel() @@ -446,17 +448,17 @@ func TestMintOnRevertedDeposit(t *testing.T) { reconstructedDep, err := derive.UnmarshalDepositLogEvent(receipt.Logs[0]) require.NoError(t, err, "Could not reconstruct L2 Deposit") tx = types.NewTx(reconstructedDep) - receipt, err = waitForL2Transaction(tx.Hash(), l2Syncer, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + receipt, err = waitForL2Transaction(tx.Hash(), l2Sync, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.NoError(t, err) require.Equal(t, receipt.Status, types.ReceiptStatusFailed) // Confirm balance ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) - endBalance, err := l2Syncer.BalanceAt(ctx, fromAddr, nil) + endBalance, err := l2Sync.BalanceAt(ctx, fromAddr, nil) cancel() require.Nil(t, err) ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) - toAddrBalance, err := l2Syncer.BalanceAt(ctx, toAddr, nil) + toAddrBalance, err := l2Sync.BalanceAt(ctx, toAddr, nil) require.NoError(t, err) cancel() @@ -466,7 +468,7 @@ func TestMintOnRevertedDeposit(t *testing.T) { require.Equal(t, common.Big0.Int64(), toAddrBalance.Int64(), "The recipient account balance should be zero") ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) - endNonce, err := l2Syncer.NonceAt(ctx, fromAddr, nil) + endNonce, err := l2Sync.NonceAt(ctx, fromAddr, nil) require.NoError(t, err) cancel() require.Equal(t, startNonce+1, endNonce, "Nonce of deposit sender should increment on L2, even if the deposit fails") @@ -479,7 +481,7 @@ func TestMissingBatchE2E(t *testing.T) { } // Note this test zeroes the balance of the batch-submitter to make the batches unable to go into L1. // The test logs may look scary, but this is expected: - // 'batcher unable to publish transaction role=batcher err="insufficient funds for gas * price + value"' + // 'unable to publish transaction role=batcher err="insufficient funds for gas * price + value"' cfg := DefaultSystemConfig(t) // small proposer window size so the test does not take as long @@ -608,9 +610,10 @@ func TestSystemMockP2P(t *testing.T) { } cfg := DefaultSystemConfig(t) - // slow down L1 blocks so we can see the L2 blocks arrive well before the L1 blocks do. - // Keep the proposer window small so the L2 chain is started quick - cfg.DeployConfig.L1BlockTime = 10 + // Disable batcher, so we don't sync from L1 + cfg.DisableBatcher = true + // disable at the start, so we don't miss any gossiped blocks. + cfg.Nodes["proposer"].Driver.ProposerStopped = true // connect the nodes cfg.P2PTopology = map[string][]string{ @@ -632,6 +635,11 @@ func TestSystemMockP2P(t *testing.T) { require.Nil(t, err, "Error starting up system") defer sys.Close() + // Enable the proposer now that everyone is ready to receive payloads. + rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["proposer"].HTTPEndpoint()) + require.NoError(t, err) + require.NoError(t, rollupRPCClient.Call(nil, "admin_startProposer", sys.L2GenesisCfg.ToBlock().Hash())) + l2Prop := sys.Clients["proposer"] l2Sync := sys.Clients["syncer"] @@ -653,11 +661,11 @@ func TestSystemMockP2P(t *testing.T) { require.Nil(t, err, "Sending L2 tx to proposer") // Wait for tx to be mined on the L2 proposer chain - receiptProp, err := waitForL2Transaction(tx.Hash(), l2Prop, 6*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + receiptProp, err := waitForL2Transaction(tx.Hash(), l2Prop, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on proposer") // Wait until the block it was first included in shows up in the safe chain on the syncer - receiptSync, err := waitForL2Transaction(tx.Hash(), l2Sync, 6*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + receiptSync, err := waitForL2Transaction(tx.Hash(), l2Sync, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on syncer") require.Equal(t, receiptProp, receiptSync) @@ -670,7 +678,7 @@ func TestSystemMockP2P(t *testing.T) { require.Contains(t, received, receiptSync.BlockHash) } -// TestSystemMockP2P sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that +// TestSystemRPCAltSync sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that // the nodes can sync L2 blocks before they are confirmed on L1. // // Test steps: @@ -681,24 +689,28 @@ func TestSystemMockP2P(t *testing.T) { // 6. Wait for the RPC sync method to grab the block from the proposer over RPC and insert it into the syncer's unsafe chain. // 7. Wait for the syncer to sync the unsafe chain into the safe chain. // 8. Verify that the TX is included in the syncer's safe chain. -func TestSystemMockAltSync(t *testing.T) { +func TestSystemRPCAltSync(t *testing.T) { parallel(t) if !verboseGethNodes { log.Root().SetHandler(log.DiscardHandler()) } cfg := DefaultSystemConfig(t) - // slow down L1 blocks so we can see the L2 blocks arrive well before the L1 blocks do. - // Keep the proposer window small so the L2 chain is started quick - cfg.DeployConfig.L1BlockTime = 10 + // the default is nil, but this may change in the future. + // This test must ensure the blocks are not synced via Gossip, but instead via the alt RPC based sync. + cfg.P2PTopology = nil + // Disable batcher, so there will not be any L1 data to sync from + cfg.DisableBatcher = true - var published, received []common.Hash + var published, received []string propTracer, syncTracer := new(FnTracer), new(FnTracer) + // The proposer still publishes the blocks to the tracer, even if they do not reach the network due to disabled P2P propTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayload) { - published = append(published, payload.BlockHash) + published = append(published, payload.ID().String()) } + // Blocks are now received via the RPC based alt-sync method syncTracer.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayload) { - received = append(received, payload.BlockHash) + received = append(received, payload.ID().String()) } cfg.Nodes["proposer"].Tracer = propTracer cfg.Nodes["syncer"].Tracer = syncTracer @@ -709,7 +721,7 @@ func TestSystemMockAltSync(t *testing.T) { action: func(sCfg *SystemConfig, system *System) { rpc, _ := system.Nodes["proposer"].Attach() // never errors cfg.Nodes["syncer"].L2Sync = &rollupNode.PreparedL2SyncEndpoint{ - Rpc: client.NewBaseRPCClient(rpc), + Client: client.NewBaseRPCClient(rpc), } }, }) @@ -737,26 +749,179 @@ func TestSystemMockAltSync(t *testing.T) { require.Nil(t, err, "Sending L2 tx to proposer") // Wait for tx to be mined on the L2 proposer chain - receiptSeq, err := waitForTransaction(tx.Hash(), l2Prop, 6*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + receiptProp, err := waitForTransaction(tx.Hash(), l2Prop, 6*time.Duration(sys.RollupConfig.BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on proposer") // Wait for alt RPC sync to pick up the blocks on the proposer chain - receiptVerif, err := waitForTransaction(tx.Hash(), l2Sync, 12*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + receiptSync, err := waitForTransaction(tx.Hash(), l2Sync, 12*time.Duration(sys.RollupConfig.BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on syncer") - require.Equal(t, receiptSeq, receiptVerif) + require.Equal(t, receiptProp, receiptSync) // Verify that the tx was received via RPC sync (P2P is disabled) - require.Contains(t, received, receiptVerif.BlockHash) + require.Contains(t, received, eth.BlockID{Hash: receiptSync.BlockHash, Number: receiptSync.BlockNumber.Uint64()}.String()) // Verify that everything that was received was published require.GreaterOrEqual(t, len(published), len(received)) require.ElementsMatch(t, received, published[:len(received)]) } +func TestSystemP2PAltSync(t *testing.T) { + parallel(t) + if !verboseGethNodes { + log.Root().SetHandler(log.DiscardHandler()) + } + + cfg := DefaultSystemConfig(t) + + // remove default syncer node + delete(cfg.Nodes, "syncer") + // Add more syncer nodes + cfg.Nodes["alice"] = &rollupNode.Config{ + Driver: driver.Config{ + SyncerConfDepth: 0, + ProposerConfDepth: 0, + ProposerEnabled: false, + }, + L1EpochPollInterval: time.Second * 4, + } + cfg.Nodes["bob"] = &rollupNode.Config{ + Driver: driver.Config{ + SyncerConfDepth: 0, + ProposerConfDepth: 0, + ProposerEnabled: false, + }, + L1EpochPollInterval: time.Second * 4, + } + cfg.Loggers["alice"] = testlog.Logger(t, log.LvlInfo).New("role", "alice") + cfg.Loggers["bob"] = testlog.Logger(t, log.LvlInfo).New("role", "bob") + + // connect the nodes + cfg.P2PTopology = map[string][]string{ + "proposer": {"alice", "bob"}, + "alice": {"proposer", "bob"}, + "bob": {"alice", "proposer"}, + } + // Enable the P2P req-resp based sync + cfg.P2PReqRespSync = true + + // Disable batcher, so there will not be any L1 data to sync from + cfg.DisableBatcher = true + + var published []string + propTracer := new(FnTracer) + // The proposer still publishes the blocks to the tracer, even if they do not reach the network due to disabled P2P + propTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayload) { + published = append(published, payload.ID().String()) + } + // Blocks are now received via the RPC based alt-sync method + cfg.Nodes["proposer"].Tracer = propTracer + + sys, err := cfg.Start() + require.NoError(t, err, "Error starting up system") + defer sys.Close() + + l2Prop := sys.Clients["proposer"] + + // Transactor Account + ethPrivKey := cfg.Secrets.Alice + + // Submit a TX to L2 proposer node + toAddr := common.Address{0xff, 0xff} + tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ + ChainID: cfg.L2ChainIDBig(), + Nonce: 0, + To: &toAddr, + Value: big.NewInt(1_000_000_000), + GasTipCap: big.NewInt(10), + GasFeeCap: big.NewInt(200), + Gas: 21000, + }) + err = l2Prop.SendTransaction(context.Background(), tx) + require.NoError(t, err, "Sending L2 tx to proposer") + + // Wait for tx to be mined on the L2 proposer chain + receiptProp, err := waitForTransaction(tx.Hash(), l2Prop, 6*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + require.NoError(t, err, "Waiting for L2 tx on proposer") + + // Gossip is able to respond to IWANT messages for the duration of heartbeat_time * message_window = 0.5 * 12 = 6 + // Wait till we pass that, and then we'll have missed some blocks that cannot be retrieved in any way from gossip + time.Sleep(time.Second * 10) + + // set up our syncer node, connect it to alice/bob + cfg.Loggers["syncer"] = testlog.Logger(t, log.LvlInfo).New("role", "syncer") + snapLog := log.New() + snapLog.SetHandler(log.DiscardHandler()) + + // Create a peer, and hook up alice and bob + h, err := sys.Mocknet.GenPeer() + require.NoError(t, err) + _, err = sys.Mocknet.LinkPeers(sys.RollupNodes["alice"].P2P().Host().ID(), h.ID()) + require.NoError(t, err) + _, err = sys.Mocknet.LinkPeers(sys.RollupNodes["bob"].P2P().Host().ID(), h.ID()) + require.NoError(t, err) + + // Configure the new rollup node that'll be syncing + var syncedPayloads []string + syncNodeCfg := &rollupNode.Config{ + L2Sync: &rollupNode.PreparedL2SyncEndpoint{Client: nil}, + Driver: driver.Config{SyncerConfDepth: 0}, + Rollup: *sys.RollupConfig, + P2PSigner: nil, + RPC: rollupNode.RPCConfig{ + ListenAddr: "127.0.0.1", + ListenPort: 0, + EnableAdmin: true, + }, + P2P: &p2p.Prepared{HostP2P: h, EnableReqRespSync: true}, + Metrics: rollupNode.MetricsConfig{Enabled: false}, // no metrics server + Pprof: kpprof.CLIConfig{}, + L1EpochPollInterval: time.Second * 10, + Tracer: &FnTracer{ + OnUnsafeL2PayloadFn: func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayload) { + syncedPayloads = append(syncedPayloads, payload.ID().String()) + }, + }, + } + configureL1(syncNodeCfg, sys.Nodes["l1"]) + syncerL2Engine, _, err := initL2Geth("syncer", big.NewInt(int64(cfg.DeployConfig.L2ChainID)), sys.L2GenesisCfg, cfg.JWTFilePath) + require.NoError(t, err) + require.NoError(t, syncerL2Engine.Start()) + + configureL2(syncNodeCfg, syncerL2Engine, cfg.JWTSecret) + + syncerNode, err := rollupNode.New(context.Background(), syncNodeCfg, cfg.Loggers["syncer"], snapLog, "", metrics.NewMetrics("")) + require.NoError(t, err) + err = syncerNode.Start(context.Background()) + require.NoError(t, err) + + // connect alice and bob to our new syncer node + _, err = sys.Mocknet.ConnectPeers(sys.RollupNodes["alice"].P2P().Host().ID(), syncerNode.P2P().Host().ID()) + require.NoError(t, err) + _, err = sys.Mocknet.ConnectPeers(sys.RollupNodes["bob"].P2P().Host().ID(), syncerNode.P2P().Host().ID()) + require.NoError(t, err) + + rpc, err := syncerL2Engine.Attach() + require.NoError(t, err) + l2Sync := ethclient.NewClient(rpc) + + // It may take a while to sync, but eventually we should see the proposed data show up + receiptSync, err := waitForTransaction(tx.Hash(), l2Sync, 100*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + require.NoError(t, err, "Waiting for L2 tx on syncer") + + require.Equal(t, receiptProp, receiptSync) + + // Verify that the tx was received via P2P sync + require.Contains(t, syncedPayloads, eth.BlockID{Hash: receiptSync.BlockHash, Number: receiptSync.BlockNumber.Uint64()}.String()) + + // Verify that everything that was received was published + require.GreaterOrEqual(t, len(published), len(syncedPayloads)) + require.ElementsMatch(t, syncedPayloads, published[:len(syncedPayloads)]) +} + // TestSystemDenseTopology sets up a dense p2p topology with 3 syncer nodes and 1 proposer node. func TestSystemDenseTopology(t *testing.T) { - t.Skip("Skipping dense topology test to avoid flakiness. @refcell address in p2p scoring pr.") + t.Skip("Skipping dense topology test to avoid flakiness.") parallel(t) if !verboseGethNodes { @@ -851,21 +1016,21 @@ func TestSystemDenseTopology(t *testing.T) { require.NoError(t, err, "Sending L2 tx to proposer") // Wait for tx to be mined on the L2 proposer chain - receiptSeq, err := waitForTransaction(tx.Hash(), l2Prop, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + receiptProp, err := waitForTransaction(tx.Hash(), l2Prop, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second) require.NoError(t, err, "Waiting for L2 tx on proposer") // Wait until the block it was first included in shows up in the safe chain on the syncer - receiptVerif, err := waitForTransaction(tx.Hash(), l2Sync, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + receiptSync, err := waitForTransaction(tx.Hash(), l2Sync, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second) require.NoError(t, err, "Waiting for L2 tx on syncer") - require.Equal(t, receiptSeq, receiptVerif) + require.Equal(t, receiptProp, receiptSync) - receiptVerif, err = waitForTransaction(tx.Hash(), l2Sync2, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + receiptSync, err = waitForTransaction(tx.Hash(), l2Sync2, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second) require.NoError(t, err, "Waiting for L2 tx on syncer2") - require.Equal(t, receiptSeq, receiptVerif) + require.Equal(t, receiptProp, receiptSync) - receiptVerif, err = waitForTransaction(tx.Hash(), l2Sync3, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + receiptSync, err = waitForTransaction(tx.Hash(), l2Sync3, 10*time.Duration(sys.RollupConfig.BlockTime)*time.Second) require.NoError(t, err, "Waiting for L2 tx on syncer3") - require.Equal(t, receiptSeq, receiptVerif) + require.Equal(t, receiptProp, receiptSync) // Verify that everything that was received was published require.GreaterOrEqual(t, len(published), len(received1)) @@ -876,9 +1041,9 @@ func TestSystemDenseTopology(t *testing.T) { require.ElementsMatch(t, published, received3[:len(published)]) // Verify that the tx was received via p2p - require.Contains(t, received1, receiptVerif.BlockHash) - require.Contains(t, received2, receiptVerif.BlockHash) - require.Contains(t, received3, receiptVerif.BlockHash) + require.Contains(t, received1, receiptSync.BlockHash) + require.Contains(t, received2, receiptSync.BlockHash) + require.Contains(t, received3, receiptSync.BlockHash) } func TestL1InfoContract(t *testing.T) { @@ -975,7 +1140,6 @@ func TestL1InfoContract(t *testing.T) { checkInfoList("On proposer with state", l1InfosFromProposerState) checkInfoList("On syncer with tx", l1InfosFromSyncerTransactions) checkInfoList("On syncer with state", l1InfosFromSyncerState) - } // calcGasFees determines the actual cost of the transaction given a specific basefee @@ -1491,7 +1655,8 @@ func TestStopStartBatcher(t *testing.T) { require.Greater(t, newSeqStatus.SafeL2.Number, propStatus.SafeL2.Number, "Safe chain did not advance") // stop the batch submission - sys.Batcher.Stop() + err = sys.Batcher.Stop(context.Background()) + require.NoError(t, err) // wait for any old safe blocks being submitted / derived time.Sleep(safeBlockInclusionDuration) @@ -1510,7 +1675,8 @@ func TestStopStartBatcher(t *testing.T) { require.Equal(t, newSeqStatus.SafeL2.Number, propStatus.SafeL2.Number, "Safe chain advanced while batcher was stopped") // start the batch submission - sys.Batcher.Start() + err = sys.Batcher.Start() + require.NoError(t, err) time.Sleep(safeBlockInclusionDuration) // send a third tx diff --git a/e2e/system_tob_test.go b/e2e/system_tob_test.go index 7965567952..ad40cf18ee 100644 --- a/e2e/system_tob_test.go +++ b/e2e/system_tob_test.go @@ -427,6 +427,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { i := i // avoid loop var capture t.Run(fmt.Sprintf("withdrawal test#%d", i+1), func(t *testing.T) { parallel(t) + // Create our system configuration, funding all accounts we created for L1/L2, and start it cfg := DefaultSystemConfig(t) cfg.DeployConfig.FinalizationPeriodSeconds = 6 @@ -722,7 +723,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { // TODO: Check L1 balance as well here. We avoided this due to time constraints as it seems L1 fees // were off slightly. _ = endL1Balance - //require.Equal(t, transactor.ExpectedL1Balance, endL1Balance, "Unexpected L1 balance for transactor") + // require.Equal(t, transactor.ExpectedL1Balance, endL1Balance, "Unexpected L1 balance for transactor") require.Equal(t, transactor.ExpectedL1Nonce, endL1Nonce, "Unexpected L1 nonce for transactor") require.Equal(t, transactor.ExpectedL2Nonce, endL2PropNonce, "Unexpected L2 proposer nonce for transactor") require.Equal(t, transactor.ExpectedL2Balance, endL2PropBalance, "Unexpected L2 proposer balance for transactor") diff --git a/go.mod b/go.mod index 03f03071d9..32c9295b2b 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 - github.com/ethereum/go-ethereum v1.11.2 + github.com/ethereum/go-ethereum v1.11.5 github.com/fsnotify/fsnotify v1.6.0 github.com/golang/snappy v0.0.4 github.com/google/go-cmp v0.5.9 @@ -72,6 +72,7 @@ require ( github.com/go-stack/stack v1.8.1 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/golang/mock v1.6.0 // indirect @@ -83,7 +84,6 @@ require ( github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-bexpr v0.1.11 // indirect - github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/huin/goupnp v1.0.3 // indirect github.com/iden3/go-iden3-crypto v0.0.13 // indirect @@ -141,7 +141,6 @@ require ( github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect - github.com/prometheus/tsdb v0.10.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-18 v0.2.0 // indirect github.com/quic-go/qtls-go1-19 v0.2.0 // indirect @@ -183,4 +182,4 @@ require ( nhooyr.io/websocket v1.8.7 // indirect ) -replace github.com/ethereum/go-ethereum v1.11.2 => github.com/kroma-network/go-ethereum v0.0.0-20230502143901-e237931a63ce +replace github.com/ethereum/go-ethereum v1.11.5 => github.com/kroma-network/go-ethereum v0.0.0-20230510092457-20e23d92c5e4 diff --git a/go.sum b/go.sum index 541e177fdc..1028a049a6 100644 --- a/go.sum +++ b/go.sum @@ -154,7 +154,6 @@ github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/docker/docker v23.0.0+incompatible h1:L6c28tNyqZ4/ub9AZC9d5QUuunoHHfEH4/Ue+h/E5nE= github.com/docker/docker v23.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= @@ -219,11 +218,9 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= @@ -255,6 +252,8 @@ github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= @@ -294,7 +293,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= @@ -359,8 +357,6 @@ github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:i github.com/hashicorp/golang-lru/v2 v2.0.1 h1:5pv5N1lT1fjLg2VQ5KWc7kmucp2x/kvFOnxuVTqZ6x4= github.com/hashicorp/golang-lru/v2 v2.0.1/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= @@ -474,10 +470,11 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kroma-network/go-ethereum v0.0.0-20230502143901-e237931a63ce h1:up2D1uq6iL1ql1PTaddw4qD/FDH2rGj4fLAOYJvT1pE= -github.com/kroma-network/go-ethereum v0.0.0-20230502143901-e237931a63ce/go.mod h1:ZUqN6UL9AcLf9iBWDq61+IU0+ra8Kd5vSB6eYZYsrf0= +github.com/kroma-network/go-ethereum v0.0.0-20230510092457-20e23d92c5e4 h1:x8MavAirhVwIffXNQxIQYHNR6bXKGnHO38IKg1fBNMs= +github.com/kroma-network/go-ethereum v0.0.0-20230510092457-20e23d92c5e4/go.mod h1:bsCi94qJ3k9vrG+fIbaofgsrYwtyRad+ethUxyAzs5o= github.com/kroma-network/zktrie v0.5.1-0.20230420142222-950ce7a8ce84 h1:VpLCQx+tFV6Nk0hbs3Noyxma/q9wIDdyacKpGQWUMI8= github.com/kroma-network/zktrie v0.5.1-0.20230420142222-950ce7a8ce84/go.mod h1:w54LrYo5rJEV503BgMPRNONsLTOEQv5V87q+uYaw9sM= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= @@ -615,7 +612,6 @@ github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -685,8 +681,6 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= -github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U= diff --git a/packages/common-ts/.depcheckrc b/packages/common-ts/.depcheckrc new file mode 100644 index 0000000000..1b21e0f630 --- /dev/null +++ b/packages/common-ts/.depcheckrc @@ -0,0 +1,13 @@ +ignores: [ + "@babel/eslint-parser", + "@typescript-eslint/eslint-plugin", + "@typescript-eslint/parser", + "eslint-config-prettier", + "eslint-import-resolver-typescript" + "eslint-plugin-import", + "eslint-plugin-jsdoc", + "eslint-plugin-prefer-arrow", + "eslint-plugin-prettier", + "eslint-plugin-react", + "eslint-plugin-unicorn", +] diff --git a/packages/common-ts/.eslintrc.js b/packages/common-ts/.eslintrc.js index bfd2057be8..fe91b823c7 100644 --- a/packages/common-ts/.eslintrc.js +++ b/packages/common-ts/.eslintrc.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-undef module.exports = { extends: '../../.eslintrc.js', } diff --git a/packages/common-ts/.gitignore b/packages/common-ts/.gitignore index b51ea715cf..122586a131 100644 --- a/packages/common-ts/.gitignore +++ b/packages/common-ts/.gitignore @@ -1,2 +1,3 @@ node_modules/ -build/ \ No newline at end of file +build/ +coverage.json diff --git a/packages/common-ts/package.json b/packages/common-ts/package.json index f0a8e62642..924daf4b90 100644 --- a/packages/common-ts/package.json +++ b/packages/common-ts/package.json @@ -17,7 +17,7 @@ "lint": "yarn lint:fix && yarn lint:check", "pre-commit": "lint-staged", "test": "ts-mocha test/*.spec.ts", - "test:coverage": "echo 'no coverage'" + "test:coverage": "nyc ts-mocha test/*.spec.ts && nyc merge .nyc_output coverage.json" }, "keywords": [ "ethereum", @@ -48,8 +48,7 @@ "pino": "^6.11.3", "pino-multi-stream": "^5.3.0", "pino-sentry": "^0.7.0", - "prom-client": "^13.1.0", - "qs": "^6.10.5" + "prom-client": "^13.1.0" }, "devDependencies": { "@ethersproject/abstract-provider": "^5.7.0", diff --git a/packages/common-ts/src/base-service/base-service-v2.ts b/packages/common-ts/src/base-service/base-service-v2.ts index 514f8d607d..1038ba0a22 100644 --- a/packages/common-ts/src/base-service/base-service-v2.ts +++ b/packages/common-ts/src/base-service/base-service-v2.ts @@ -211,8 +211,15 @@ export abstract class BaseServiceV2< // Since BCFG turns everything into lower case, we're required to turn all of the input option // names into lower case for the validation step. We'll turn the names back into their original // names when we're done. + const lowerCaseOptions = Object.entries(params.options).reduce( + (acc, [key, val]) => { + acc[key.toLowerCase()] = val + return acc + }, + {} + ) const cleaned = cleanEnv( - { ...config.env, ...config.args, ...(params.options || {}) }, + { ...config.env, ...config.args, ...(lowerCaseOptions || {}) }, Object.entries(params.optionsSpec || {}).reduce((acc, [key, val]) => { acc[key.toLowerCase()] = val.validator({ desc: val.desc, diff --git a/packages/common-ts/test/service.spec.ts b/packages/common-ts/test/service.spec.ts new file mode 100644 index 0000000000..43aac70b3e --- /dev/null +++ b/packages/common-ts/test/service.spec.ts @@ -0,0 +1,28 @@ +import { validators } from '../dist' +import { BaseServiceV2 } from '../src' + +type ServiceOptions = { + camelCase: string +} + +class Service extends BaseServiceV2 { + constructor(options?: Partial) { + super({ + name: 'test-service', + version: '0.0', + options, + optionsSpec: { + camelCase: { validator: validators.str, desc: 'test' }, + }, + metricsSpec: {}, + }) + } + protected async main() { + } +} + +describe('BaseServiceV2', () => { + it('base service ctor does not throw on camel case options', async () => { + new Service({ camelCase: 'test' }) + }) +}) diff --git a/packages/contracts/.env.example b/packages/contracts/.env.example index 289f5847eb..8e8d733f4e 100644 --- a/packages/contracts/.env.example +++ b/packages/contracts/.env.example @@ -6,6 +6,8 @@ L1_RPC_MAINNET= L1_RPC_SEPOLIA= # RPC for Lightscale easel testnet L1_RPC_EASEL= +# RPC for Kroma sepolia testnet +L2_RPC_KROMA_SEPOLIA= # RPC for Sail L2_RPC_SAIL= diff --git a/packages/contracts/.eslintrc.js b/packages/contracts/.eslintrc.js index 048ff5ebd5..c71bbe2960 100644 --- a/packages/contracts/.eslintrc.js +++ b/packages/contracts/.eslintrc.js @@ -1,4 +1,13 @@ +// eslint-disable-next-line no-undef module.exports = { extends: '../../.eslintrc.js', ignorePatterns: ['src/contract-artifacts.ts'], + overrides: [ + { + files: ['**/*.ts'], + rules: { + 'no-constant-condition': ['error', { checkLoops: false }], + }, + }, + ], } diff --git a/packages/contracts/.gas-snapshot b/packages/contracts/.gas-snapshot index 631647631a..4eb486a9b0 100644 --- a/packages/contracts/.gas-snapshot +++ b/packages/contracts/.gas-snapshot @@ -1,15 +1,3 @@ -Colosseum_Test:testCannot_createChallengeWhenPrevInProgress() (gas: 525004) -Colosseum_Test:testCannot_createChallengeWithBadSegments() (gas: 99159) -Colosseum_Test:test_asserterBisectAfterTimedOut() (gas: 526189) -Colosseum_Test:test_bisect() (gas: 510568) -Colosseum_Test:test_bisectIfNotYourTurn() (gas: 519766) -Colosseum_Test:test_challengerBisectAfterTimedOut() (gas: 528387) -Colosseum_Test:test_challengerNotCloseWhenAsserterTimeout() (gas: 526966) -Colosseum_Test:test_constructor() (gas: 19587) -Colosseum_Test:test_createChallenge() (gas: 504034) -Colosseum_Test:test_proveFault() (gas: 1472985) -Colosseum_Test:test_timeoutWhenTimedOutAsserterTurn() (gas: 423504) -Colosseum_Test:test_timeoutWhenTimedOutChallengerTurn() (gas: 467264) CrossDomainMessenger_BaseGas_Test:test_baseGas_succeeds() (gas: 11448) CrossDomainOwnable2_Test:test_onlyOwner_notMessenger_reverts() (gas: 8451) CrossDomainOwnable2_Test:test_onlyOwner_notOwner2_reverts() (gas: 61940) @@ -27,28 +15,28 @@ CrossDomainOwnable3_Test:test_transferOwnershipNoLocal_succeeds() (gas: 48766) CrossDomainOwnable3_Test:test_transferOwnership_noLocalZeroAddress_reverts() (gas: 12063) CrossDomainOwnable3_Test:test_transferOwnership_notOwner_reverts() (gas: 13461) CrossDomainOwnable3_Test:test_transferOwnership_zeroAddress_reverts() (gas: 12129) -CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 72656) +CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 72651) CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597) CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34883) FeeVault_Test:test_constructor_succeeds() (gas: 10766) FeeVault_Test:test_minWithdrawalAmount_succeeds() (gas: 10737) -GasBenchMark_KromaPortal:test_depositTransaction_benchmark() (gas: 75084) -GasBenchMark_KromaPortal:test_depositTransaction_benchmark_1() (gas: 77832) -GasBenchMark_KromaPortal:test_proveWithdrawalTransaction_benchmark() (gas: 262088) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 257204) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2090399) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 433662) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 3180799) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 336256) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 2617099) +GasBenchMark_KromaPortal:test_depositTransaction_benchmark() (gas: 75079) +GasBenchMark_KromaPortal:test_depositTransaction_benchmark_1() (gas: 75712) +GasBenchMark_KromaPortal:test_proveWithdrawalTransaction_benchmark() (gas: 262065) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 257162) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2090357) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 433620) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 3180757) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 336214) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 2617057) GasBenchMark_L1StandardBridge_Finalize:test_finalizeBridgeETH_benchmark() (gas: 32270) GasBenchMark_L2OutputOracle:test_submitL2Output_benchmark() (gas: 88493) GasPriceOracle_Test:test_baseFee_succeeds() (gas: 8325) GasPriceOracle_Test:test_decimals_succeeds() (gas: 5419) GasPriceOracle_Test:test_gasPrice_succeeds() (gas: 8294) -GasPriceOracle_Test:test_l1BaseFee_succeeds() (gas: 10656) -GasPriceOracle_Test:test_overhead_succeeds() (gas: 10613) -GasPriceOracle_Test:test_scalar_succeeds() (gas: 10677) +GasPriceOracle_Test:test_l1BaseFee_succeeds() (gas: 10679) +GasPriceOracle_Test:test_overhead_succeeds() (gas: 10635) +GasPriceOracle_Test:test_scalar_succeeds() (gas: 10633) Hashing_hashDepositSource_Test:test_hashDepositSource_succeeds() (gas: 639) KromaMintableERC20_Test:test_bridge_succeeds() (gas: 7707) KromaMintableERC20_Test:test_burn_notBridge_reverts() (gas: 11172) @@ -71,53 +59,53 @@ KromaMintableTokenFactory_Test:test_bridge_succeeds() (gas: 7607) KromaMintableTokenFactory_Test:test_createKromaMintableERC20_remoteIsZero_succeeds() (gas: 9387) KromaMintableTokenFactory_Test:test_createKromaMintableERC20_sameTwice_succeeds() (gas: 2289963) KromaMintableTokenFactory_Test:test_createKromaMintableERC20_succeeds() (gas: 1151012) -KromaPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 10983) -KromaPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 15907) -KromaPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 16103) +KromaPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 11006) +KromaPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 15930) +KromaPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 21822) KromaPortalUpgradeable_Test:test_upgradeToAndCall_upgrading_succeeds() (gas: 180688) -KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 296980) -KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 300367) +KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 296934) +KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 300321) KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() (gas: 41750) -KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 292299) -KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 289030) -KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 273045) -KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 326997) -KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 338319) -KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_paused_reverts() (gas: 53567) -KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() (gas: 327740) +KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 292253) +KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 288984) +KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 272999) +KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 326951) +KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 338296) +KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_paused_reverts() (gas: 53565) +KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() (gas: 327717) KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails_fails() (gas: 8797746687696168158) -KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 289868) -KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 81730) -KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 66266) -KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_paused_reverts() (gas: 87043) -KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() (gas: 515616) -KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() (gas: 448209) -KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 286823) -KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() (gas: 273283) -KromaPortal_Test:test_constructor_succeeds() (gas: 19604) -KromaPortal_Test:test_depositTransaction_contractCreation_reverts() (gas: 14239) -KromaPortal_Test:test_depositTransaction_createWithZeroValueForContract_succeeds() (gas: 76809) -KromaPortal_Test:test_depositTransaction_createWithZeroValueForEOA_succeeds() (gas: 77175) -KromaPortal_Test:test_depositTransaction_noValueContract_succeeds() (gas: 76805) -KromaPortal_Test:test_depositTransaction_noValueEOA_succeeds() (gas: 77084) -KromaPortal_Test:test_depositTransaction_smallGasLimit_reverts() (gas: 14268) -KromaPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation_succeeds() (gas: 83845) -KromaPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() (gas: 75986) -KromaPortal_Test:test_depositTransaction_withEthValueFromContract_succeeds() (gas: 83513) -KromaPortal_Test:test_depositTransaction_withEthValueFromEOA_succeeds() (gas: 84119) -KromaPortal_Test:test_isOutputFinalized_succeeds() (gas: 122029) -KromaPortal_Test:test_pause_onlyGuardian_reverts() (gas: 22342) -KromaPortal_Test:test_pause_succeeds() (gas: 42361) -KromaPortal_Test:test_receive_succeeds() (gas: 127645) -KromaPortal_Test:test_simple_isOutputFinalized_succeeds() (gas: 33068) -KromaPortal_Test:test_unpause_onlyGuardian_reverts() (gas: 46339) -KromaPortal_Test:test_unpause_succeeds() (gas: 31933) -L1BlockTest:test_basefee_succeeds() (gas: 7554) -L1BlockTest:test_hash_succeeds() (gas: 7576) +KromaPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 289822) +KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 81707) +KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 66243) +KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_paused_reverts() (gas: 87018) +KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() (gas: 515456) +KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() (gas: 448141) +KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 286777) +KromaPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() (gas: 273260) +KromaPortal_Test:test_constructor_succeeds() (gas: 19536) +KromaPortal_Test:test_depositTransaction_contractCreation_reverts() (gas: 14229) +KromaPortal_Test:test_depositTransaction_createWithZeroValueForContract_succeeds() (gas: 76804) +KromaPortal_Test:test_depositTransaction_createWithZeroValueForEOA_succeeds() (gas: 77170) +KromaPortal_Test:test_depositTransaction_noValueContract_succeeds() (gas: 76800) +KromaPortal_Test:test_depositTransaction_noValueEOA_succeeds() (gas: 77079) +KromaPortal_Test:test_depositTransaction_smallGasLimit_reverts() (gas: 14258) +KromaPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation_succeeds() (gas: 83840) +KromaPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() (gas: 75984) +KromaPortal_Test:test_depositTransaction_withEthValueFromContract_succeeds() (gas: 83508) +KromaPortal_Test:test_depositTransaction_withEthValueFromEOA_succeeds() (gas: 84114) +KromaPortal_Test:test_isOutputFinalized_succeeds() (gas: 121941) +KromaPortal_Test:test_pause_onlyGuardian_reverts() (gas: 22250) +KromaPortal_Test:test_pause_succeeds() (gas: 42269) +KromaPortal_Test:test_receive_succeeds() (gas: 127653) +KromaPortal_Test:test_simple_isOutputFinalized_succeeds() (gas: 33001) +KromaPortal_Test:test_unpause_onlyGuardian_reverts() (gas: 46290) +KromaPortal_Test:test_unpause_succeeds() (gas: 31860) +L1BlockTest:test_basefee_succeeds() (gas: 7577) +L1BlockTest:test_hash_succeeds() (gas: 7554) L1BlockTest:test_number_succeeds() (gas: 7629) -L1BlockTest:test_sequenceNumber_succeeds() (gas: 7630) -L1BlockTest:test_timestamp_succeeds() (gas: 7640) -L1BlockTest:test_updateValues_succeeds() (gas: 60482) +L1BlockTest:test_sequenceNumber_succeeds() (gas: 7586) +L1BlockTest:test_timestamp_succeeds() (gas: 7685) +L1BlockTest:test_updateValues_succeeds() (gas: 65609) L1CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 13949) L1CrossDomainMessenger_Test:test_relayMessage_reentrancyDiffMessage_succeeds() (gas: 697775) L1CrossDomainMessenger_Test:test_relayMessage_reentrancySameMessage_reverts() (gas: 640888) @@ -126,42 +114,42 @@ L1CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 64997) L1CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 84006) L1CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 12404) L1CrossDomainMessenger_Test:test_replayMessage_withValue_reverts() (gas: 44778) -L1CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 282833) -L1CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 1478965) +L1CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 282807) +L1CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 1478885) L1CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 68131) L1CrossDomainMessenger_Test:test_xDomainSender_notSet_reverts() (gas: 15601) L1ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 52833) L1ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 27424) -L1ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 350350) +L1ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 350480) L1ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 61054) L1ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 25770) L1ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 50668) L1ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 25216) -L1ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 347908) +L1ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 348038) L1ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 60928) L1ERC721Bridge_Test:test_constructor_succeeds() (gas: 8595) L1ERC721Bridge_Test:test_finalizeBridgeERC721_notEscrowed_reverts() (gas: 22168) L1ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 19846) L1ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 16068) L1ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 17664) -L1ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 319409) -L1StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 601076) -L1StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 598857) +L1ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 319539) +L1StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 601206) +L1StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 598987) L1StandardBridge_BridgeERC20_TestFail:test_bridgeERC20_notEoa_reverts() (gas: 17149) -L1StandardBridge_BridgeETHTo_Test:test_bridgeETHTo_succeeds() (gas: 397610) -L1StandardBridge_BridgeETH_Test:test_bridgeETH_succeeds() (gas: 384947) +L1StandardBridge_BridgeETHTo_Test:test_bridgeETHTo_succeeds() (gas: 397568) +L1StandardBridge_BridgeETH_Test:test_bridgeETH_succeeds() (gas: 384905) L1StandardBridge_BridgeETH_TestFail:test_BridgeETH_notEoa_reverts() (gas: 35576) L1StandardBridge_FinalizeBridgeERC20Withdrawal_Test:test_finalizeBridgeERC20Withdrawal_succeeds() (gas: 467887) L1StandardBridge_FinalizeBridgeERC20Withdrawal_TestFail:test_finalizeBridgeERC20Withdrawal_notMessenger_reverts() (gas: 24540) L1StandardBridge_FinalizeBridgeERC20Withdrawal_TestFail:test_finalizeBridgeERC20Withdrawal_notOtherBridge_reverts() (gas: 25038) L1StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 42203) -L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 27604) +L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 27601) L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 27707) L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 27676) L1StandardBridge_FinalizeETHWithdrawal_Test:test_finalizeETHWithdrawal_succeeds() (gas: 47293) L1StandardBridge_Getter_Test:test_getters_succeeds() (gas: 20659) L1StandardBridge_Initialize_Test:test_initialize_succeeds() (gas: 16254) -L1StandardBridge_Receive_Test:test_receive_succeeds() (gas: 504758) +L1StandardBridge_Receive_Test:test_receive_succeeds() (gas: 504888) L2CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 8481) L2CrossDomainMessenger_Test:test_relayMessage_reentrancyDiffMessage_succeeds() (gas: 680634) L2CrossDomainMessenger_Test:test_relayMessage_reentrancySameMessage_reverts() (gas: 626663) @@ -221,7 +209,7 @@ L2OutputOracleUpgradeable_Test:test_upgrading_succeeds() (gas: 180490) L2StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 380193) L2StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 376265) L2StandardBridge_Bridge_Test:test_finalizeBridgeERC20_succeeds() (gas: 83339) -L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 23873) +L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 23876) L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 24037) L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 23903) L2StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 36115) @@ -245,11 +233,6 @@ NodeReader_Test:test_readUint8_bytestring00() (gas: 677) NodeReader_Test:test_readUint8_bytestring01() (gas: 651) NodeReader_Test:test_readUint8_bytestring7f() (gas: 672) NodeReader_Test:test_readUint8_too_short_bytestring() (gas: 3510) -ValidatorRewardVault_Test:test_constructor_succeeds() (gas: 5534) -ValidatorRewardVault_Test:test_minWithdrawalAmount_succeeds() (gas: 5476) -ValidatorRewardVault_Test:test_receive_succeeds() (gas: 17409) -ValidatorRewardVault_Test:test_withdraw_notEnough_reverts() (gas: 9413) -ValidatorRewardVault_Test:test_withdraw_succeeds() (gas: 158985) ProxyAdmin_Test:test_changeProxyAdmin_succeeds() (gas: 30242) ProxyAdmin_Test:test_getProxyAdmin_succeeds() (gas: 13337) ProxyAdmin_Test:test_getProxyImplementation_succeeds() (gas: 49338) @@ -268,27 +251,34 @@ Proxy_Test:test_upgradeToAndCall_functionDoesNotExist_reverts() (gas: 104826) Proxy_Test:test_upgradeToAndCall_isPayable_succeeds() (gas: 53907) Proxy_Test:test_upgradeToAndCall_succeeds() (gas: 125289) Proxy_Test:test_upgradeTo_clashingFunctionSignatures_succeeds() (gas: 101590) -ResourceMetering_Test:test_meter_initialBaseFee_succeeds() (gas: 7063) -ResourceMetering_Test:test_meter_initialResourceParams_succeeds() (gas: 9076) -ResourceMetering_Test:test_meter_maxValue_succeeds() (gas: 7075) -ResourceMetering_Test:test_meter_minBaseFeeLessThanMaxBaseFee_succeeds() (gas: 6230) -ResourceMetering_Test:test_meter_updateNoGasDelta_succeeds() (gas: 2008252) -ResourceMetering_Test:test_meter_updateOneEmptyBlock_succeeds() (gas: 18477) -ResourceMetering_Test:test_meter_updateParamsNoChange_succeeds() (gas: 14077) -ResourceMetering_Test:test_meter_updateTenEmptyBlocks_succeeds() (gas: 21279) -ResourceMetering_Test:test_meter_updateTwoEmptyBlocks_succeeds() (gas: 21235) -ResourceMetering_Test:test_meter_useMax_succeeds() (gas: 20017572) -ResourceMetering_Test:test_meter_useMoreThanMax_reverts() (gas: 16168) +ResourceMetering_Test:test_meter_initialResourceParams_succeeds() (gas: 10368) +ResourceMetering_Test:test_meter_updateNoGasDelta_succeeds() (gas: 2009696) +ResourceMetering_Test:test_meter_updateOneEmptyBlock_succeeds() (gas: 18860) +ResourceMetering_Test:test_meter_updateParamsNoChange_succeeds() (gas: 15149) +ResourceMetering_Test:test_meter_updateTenEmptyBlocks_succeeds() (gas: 21713) +ResourceMetering_Test:test_meter_updateTwoEmptyBlocks_succeeds() (gas: 21669) +ResourceMetering_Test:test_meter_useMax_succeeds() (gas: 20018715) +ResourceMetering_Test:test_meter_useMoreThanMax_reverts() (gas: 17505) Semver_Test:test_behindProxy_succeeds() (gas: 506754) Semver_Test:test_version_succeeds() (gas: 9424) -SetPrevBaseFee_Test:test_setPrevBaseFee_succeeds() (gas: 11559) +SetPrevBaseFee_Test:test_setPrevBaseFee_succeeds() (gas: 11515) StandardBridge_Stateless_Test:test_isCorrectTokenPair_succeeds() (gas: 14442) StandardBridge_Stateless_Test:test_isKromaMintableERC20_succeeds() (gas: 23496) -SystemConfig_Initialize_TestFail:test_initialize_lowGasLimit_reverts() (gas: 62012) -SystemConfig_Setters_TestFail:test_setBatcherHash_notOwner_reverts() (gas: 10612) -SystemConfig_Setters_TestFail:test_setGasConfig_notOwner_reverts() (gas: 10555) -SystemConfig_Setters_TestFail:test_setGasLimit_notOwner_reverts() (gas: 10658) -SystemConfig_Setters_TestFail:test_setUnsafeBlockSigner_notOwner_reverts() (gas: 10660) +SystemConfig_Initialize_TestFail:test_initialize_lowGasLimit_reverts() (gas: 148786) +SystemConfig_Setters_TestFail:test_setBatcherHash_notOwner_reverts() (gas: 10552) +SystemConfig_Setters_TestFail:test_setGasConfig_notOwner_reverts() (gas: 10628) +SystemConfig_Setters_TestFail:test_setGasLimit_notOwner_reverts() (gas: 10621) +SystemConfig_Setters_TestFail:test_setResourceConfig_badMinMax_reverts() (gas: 13008) +SystemConfig_Setters_TestFail:test_setResourceConfig_badPrecision_reverts() (gas: 15609) +SystemConfig_Setters_TestFail:test_setResourceConfig_lowGasLimit_reverts() (gas: 16088) +SystemConfig_Setters_TestFail:test_setResourceConfig_notOwner_reverts() (gas: 11796) +SystemConfig_Setters_TestFail:test_setResourceConfig_zeroDenominator_reverts() (gas: 13045) +SystemConfig_Setters_TestFail:test_setUnsafeBlockSigner_notOwner_reverts() (gas: 10645) +ValidatorRewardVault_Test:test_constructor_succeeds() (gas: 5534) +ValidatorRewardVault_Test:test_minWithdrawalAmount_succeeds() (gas: 5476) +ValidatorRewardVault_Test:test_receive_succeeds() (gas: 17409) +ValidatorRewardVault_Test:test_withdraw_notEnough_reverts() (gas: 9413) +ValidatorRewardVault_Test:test_withdraw_succeeds() (gas: 158985) ZKMerkleTrie_Test:test_verifyInclustionProof_valid_0() (gas: 141786) ZKMerkleTrie_Test:test_verifyInclustionProof_valid_1() (gas: 350493) ZKMerkleTrie_Test:test_verifyInclustionProof_valid_2() (gas: 350409) diff --git a/packages/contracts/.gitignore b/packages/contracts/.gitignore index 683f2f4b5a..8ad70c6cb0 100644 --- a/packages/contracts/.gitignore +++ b/packages/contracts/.gitignore @@ -2,7 +2,7 @@ artifacts forge-artifacts cache typechain -coverage.out +coverage.json .deps broadcast genesis.json diff --git a/packages/contracts/.prettierignore b/packages/contracts/.prettierignore index a9eeca2bb1..3bd5669fbb 100644 --- a/packages/contracts/.prettierignore +++ b/packages/contracts/.prettierignore @@ -1,9 +1,11 @@ # Deps and test files + node_modules lib contracts/vendor/*.sol # build output + artifacts forge-artifacts cache @@ -12,5 +14,6 @@ coverage* deployments # Other autogenerated files + gasReporterOutput.json slither.db.json diff --git a/packages/contracts/.storage-layout b/packages/contracts/.storage-layout index 914db49101..234273b7d5 100644 --- a/packages/contracts/.storage-layout +++ b/packages/contracts/.storage-layout @@ -60,32 +60,34 @@ ➡ contracts/L1/SystemConfig.sol:SystemConfig ======================= -| Name | Type | Slot | Offset | Bytes | Contract | -|---------------|-------------|------|--------|-------|--------------------------------------------| -| _initialized | uint8 | 0 | 0 | 1 | contracts/L1/SystemConfig.sol:SystemConfig | -| _initializing | bool | 0 | 1 | 1 | contracts/L1/SystemConfig.sol:SystemConfig | -| __gap | uint256[50] | 1 | 0 | 1600 | contracts/L1/SystemConfig.sol:SystemConfig | -| _owner | address | 51 | 0 | 20 | contracts/L1/SystemConfig.sol:SystemConfig | -| __gap | uint256[49] | 52 | 0 | 1568 | contracts/L1/SystemConfig.sol:SystemConfig | -| overhead | uint256 | 101 | 0 | 32 | contracts/L1/SystemConfig.sol:SystemConfig | -| scalar | uint256 | 102 | 0 | 32 | contracts/L1/SystemConfig.sol:SystemConfig | -| batcherHash | bytes32 | 103 | 0 | 32 | contracts/L1/SystemConfig.sol:SystemConfig | -| gasLimit | uint64 | 104 | 0 | 8 | contracts/L1/SystemConfig.sol:SystemConfig | +| Name | Type | Slot | Offset | Bytes | Contract | +|-----------------|----------------------------------------|------|--------|-------|--------------------------------------------| +| _initialized | uint8 | 0 | 0 | 1 | contracts/L1/SystemConfig.sol:SystemConfig | +| _initializing | bool | 0 | 1 | 1 | contracts/L1/SystemConfig.sol:SystemConfig | +| __gap | uint256[50] | 1 | 0 | 1600 | contracts/L1/SystemConfig.sol:SystemConfig | +| _owner | address | 51 | 0 | 20 | contracts/L1/SystemConfig.sol:SystemConfig | +| __gap | uint256[49] | 52 | 0 | 1568 | contracts/L1/SystemConfig.sol:SystemConfig | +| overhead | uint256 | 101 | 0 | 32 | contracts/L1/SystemConfig.sol:SystemConfig | +| scalar | uint256 | 102 | 0 | 32 | contracts/L1/SystemConfig.sol:SystemConfig | +| batcherHash | bytes32 | 103 | 0 | 32 | contracts/L1/SystemConfig.sol:SystemConfig | +| gasLimit | uint64 | 104 | 0 | 8 | contracts/L1/SystemConfig.sol:SystemConfig | +| _resourceConfig | struct ResourceMetering.ResourceConfig | 105 | 0 | 32 | contracts/L1/SystemConfig.sol:SystemConfig | ======================= ➡ contracts/L2/L1Block.sol:L1Block ======================= -| Name | Type | Slot | Offset | Bytes | Contract | -|----------------|---------|------|--------|-------|----------------------------------| -| number | uint64 | 0 | 0 | 8 | contracts/L2/L1Block.sol:L1Block | -| timestamp | uint64 | 0 | 8 | 8 | contracts/L2/L1Block.sol:L1Block | -| basefee | uint256 | 1 | 0 | 32 | contracts/L2/L1Block.sol:L1Block | -| hash | bytes32 | 2 | 0 | 32 | contracts/L2/L1Block.sol:L1Block | -| sequenceNumber | uint64 | 3 | 0 | 8 | contracts/L2/L1Block.sol:L1Block | -| batcherHash | bytes32 | 4 | 0 | 32 | contracts/L2/L1Block.sol:L1Block | -| l1FeeOverhead | uint256 | 5 | 0 | 32 | contracts/L2/L1Block.sol:L1Block | -| l1FeeScalar | uint256 | 6 | 0 | 32 | contracts/L2/L1Block.sol:L1Block | +| Name | Type | Slot | Offset | Bytes | Contract | +|----------------------|---------|------|--------|-------|----------------------------------| +| number | uint64 | 0 | 0 | 8 | contracts/L2/L1Block.sol:L1Block | +| timestamp | uint64 | 0 | 8 | 8 | contracts/L2/L1Block.sol:L1Block | +| basefee | uint256 | 1 | 0 | 32 | contracts/L2/L1Block.sol:L1Block | +| hash | bytes32 | 2 | 0 | 32 | contracts/L2/L1Block.sol:L1Block | +| sequenceNumber | uint64 | 3 | 0 | 8 | contracts/L2/L1Block.sol:L1Block | +| batcherHash | bytes32 | 4 | 0 | 32 | contracts/L2/L1Block.sol:L1Block | +| l1FeeOverhead | uint256 | 5 | 0 | 32 | contracts/L2/L1Block.sol:L1Block | +| l1FeeScalar | uint256 | 6 | 0 | 32 | contracts/L2/L1Block.sol:L1Block | +| validatorRewardRatio | uint256 | 7 | 0 | 32 | contracts/L2/L1Block.sol:L1Block | ======================= ➡ contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger @@ -127,24 +129,24 @@ ➡ contracts/L2/ValidatorRewardVault.sol:ValidatorRewardVault ======================= -| Name | Type | Slot | Offset | Bytes | Contract | -|----------------|---------|------|--------|-------|----------------------------------------------------| +| Name | Type | Slot | Offset | Bytes | Contract | +|----------------|---------|------|--------|-------|------------------------------------------------------------| | totalProcessed | uint256 | 0 | 0 | 32 | contracts/L2/ValidatorRewardVault.sol:ValidatorRewardVault | ======================= ➡ contracts/L2/ProtocolVault.sol:ProtocolVault ======================= -| Name | Type | Slot | Offset | Bytes | Contract | -|----------------|---------|------|--------|-------|--------------------------------------------| +| Name | Type | Slot | Offset | Bytes | Contract | +|----------------|---------|------|--------|-------|----------------------------------------------| | totalProcessed | uint256 | 0 | 0 | 32 | contracts/L2/ProtocolVault.sol:ProtocolVault | ======================= ➡ contracts/L2/ProposerRewardVault.sol:ProposerRewardVault ======================= -| Name | Type | Slot | Offset | Bytes | Contract | -|----------------|---------|------|--------|-------|----------------------------------------| +| Name | Type | Slot | Offset | Bytes | Contract | +|----------------|---------|------|--------|-------|----------------------------------------------------------| | totalProcessed | uint256 | 0 | 0 | 32 | contracts/L2/ProposerRewardVault.sol:ProposerRewardVault | ======================= diff --git a/packages/contracts/README.md b/packages/contracts/README.md index 9b63b9a325..e4a618d480 100644 --- a/packages/contracts/README.md +++ b/packages/contracts/README.md @@ -53,7 +53,7 @@ We work on this repository with a combination of [Hardhat](https://hardhat.org) A specific version must be used. ```shell - > foundryup -C 2ff99025abade470a795724c10648c800a41025e + > foundryup -C da2392e58bb8a7fefeba46b40c4df1afad8ccd22 ``` 2. Install node modules with yarn (v1) and Node.js (16+): @@ -89,9 +89,11 @@ Each target contract is tested with a separate yarn command, for example: #### Configuration -1. Create or modify a file `.json` inside of the [`deploy-config`](./deploy-config/) folder. +1. Create or modify a file `.ts` inside of the [`deploy-config`](./deploy-config/) folder. 2. Fill out this file according to the `deployConfigSpec` located inside of the - [`hardhat.config.ts](./hardhat.config.ts). + [`hardhat.config.ts`](./hardhat.config.ts). +3. Optionally: Run `npx hardhat generate-deploy-config --network ` to generate the associated JSON + file. This is required if using `utils/chain-ops`. #### Execution @@ -250,3 +252,8 @@ Test contracts should be named one of the following according to their use: - `TargetContract_Init` for contracts that perform basic setup to be reused in other test contracts. - `TargetContract_Function_Test` for contracts containing happy path tests for a given function. - `TargetContract_Function_TestFail` for contracts containing sad path tests for a given function. + +## Withdrawing From Fee Vaults + +See the file `scripts/FeeVaultWithdrawal.s.sol` to withdraw from the L2 fee vaults. It includes +instructions on how to run it. `foundry` is required. diff --git a/packages/contracts/contracts/L1/KromaPortal.sol b/packages/contracts/contracts/L1/KromaPortal.sol index b126f15a47..7fc817212d 100644 --- a/packages/contracts/contracts/L1/KromaPortal.sol +++ b/packages/contracts/contracts/L1/KromaPortal.sol @@ -9,8 +9,9 @@ import { SafeCall } from "../libraries/SafeCall.sol"; import { Types } from "../libraries/Types.sol"; import { Semver } from "../universal/Semver.sol"; import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; -import { ResourceMetering } from "./ResourceMetering.sol"; import { L2OutputOracle } from "./L2OutputOracle.sol"; +import { ResourceMetering } from "./ResourceMetering.sol"; +import { SystemConfig } from "./SystemConfig.sol"; import { ZKMerkleTrie } from "./ZKMerkleTrie.sol"; /** @@ -45,10 +46,15 @@ contract KromaPortal is Initializable, ResourceMetering, Semver { uint64 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000; /** - * @notice Address of the L2OutputOracle. + * @notice Address of the L2OutputOracle contract. */ L2OutputOracle public immutable L2_ORACLE; + /** + * @notice Address of the SystemConfig contract. + */ + SystemConfig public immutable SYSTEM_CONFIG; + /** * @notice Address that has the ability to pause and unpause withdrawals. */ @@ -78,8 +84,7 @@ contract KromaPortal is Initializable, ResourceMetering, Semver { /** * @notice Determines if cross domain messaging is paused. When set to true, - * deposits and withdrawals are paused. This may be removed in the - * future. + * withdrawals are paused. This may be removed in the future. */ bool public paused; @@ -146,16 +151,19 @@ contract KromaPortal is Initializable, ResourceMetering, Semver { * @param _l2Oracle Address of the L2OutputOracle contract. * @param _guardian Address that can pause deposits and withdrawals. * @param _paused Sets the contract's pausability state. + * @param _config Address of the SystemConfig contract. * @param _zkMerkleTrie Address of the ZKMerkleTrie contract. */ constructor( L2OutputOracle _l2Oracle, address _guardian, bool _paused, + SystemConfig _config, ZKMerkleTrie _zkMerkleTrie ) Semver(0, 1, 0) { L2_ORACLE = _l2Oracle; GUARDIAN = _guardian; + SYSTEM_CONFIG = _config; ZK_MERKLE_TRIE = _zkMerkleTrie; initialize(_paused); } @@ -169,7 +177,7 @@ contract KromaPortal is Initializable, ResourceMetering, Semver { __ResourceMetering_init(); } - /** + /** * @notice Pause deposits and withdrawals. */ function pause() external { @@ -198,6 +206,21 @@ contract KromaPortal is Initializable, ResourceMetering, Semver { depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes("")); } + /** + * @notice Getter for the resource config. Used internally by the ResourceMetering + * contract. The SystemConfig is the source of truth for the resource config. + * + * @return ResourceMetering.ResourceConfig + */ + function _resourceConfig() + internal + view + override + returns (ResourceMetering.ResourceConfig memory) + { + return SYSTEM_CONFIG.resourceConfig(); + } + /** * @notice Proves a withdrawal transaction. * @@ -289,10 +312,9 @@ contract KromaPortal is Initializable, ResourceMetering, Semver { * * @param _tx Withdrawal transaction to finalize. */ - function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) - external - whenNotPaused - { + function finalizeWithdrawalTransaction( + Types.WithdrawalTransaction memory _tx + ) external whenNotPaused { // Make sure that the l2Sender has not yet been set. The l2Sender is set to a value other // than the default value when a withdrawal transaction is being finalized. This check is // a defacto reentrancy guard. @@ -308,10 +330,7 @@ contract KromaPortal is Initializable, ResourceMetering, Semver { // A withdrawal can only be finalized if it has been proven. We know that a withdrawal has // been proven at least once when its timestamp is non-zero. Unproven withdrawals will have // a timestamp of zero. - require( - provenWithdrawal.timestamp != 0, - "KromaPortal: withdrawal has not been proven yet" - ); + require(provenWithdrawal.timestamp != 0, "KromaPortal: withdrawal has not been proven yet"); // As a sanity check, we make sure that the proven withdrawal's timestamp is greater than // starting timestamp inside the L2OutputOracle. Not strictly necessary but extra layer of diff --git a/packages/contracts/contracts/L1/ResourceMetering.sol b/packages/contracts/contracts/L1/ResourceMetering.sol index bf05b6e031..7413d9317b 100644 --- a/packages/contracts/contracts/L1/ResourceMetering.sol +++ b/packages/contracts/contracts/L1/ResourceMetering.sol @@ -29,44 +29,34 @@ abstract contract ResourceMetering is Initializable { } /** - * @notice Maximum amount of the resource that can be used within this block. - * This value cannot be larger than the L2 block gas limit. - */ - int256 public constant MAX_RESOURCE_LIMIT = 20_000_000; - - /** - * @notice Along with the resource limit, determines the target resource limit. - */ - int256 public constant ELASTICITY_MULTIPLIER = 10; - - /** - * @notice Target amount of the resource that should be used within this block. - */ - int256 public constant TARGET_RESOURCE_LIMIT = MAX_RESOURCE_LIMIT / ELASTICITY_MULTIPLIER; - - /** - * @notice Denominator that determines max change on fee per block. - */ - int256 public constant BASE_FEE_MAX_CHANGE_DENOMINATOR = 8; - - /** - * @notice Minimum base fee value, cannot go lower than this. - */ - int256 public constant MINIMUM_BASE_FEE = 1 gwei; - - /** - * @notice Maximum base fee value, cannot go higher than this. - * It is possible for the MAXIMUM_BASE_FEE to raise to a value - * that is so large it will consume the entire gas limit of - * an L1 block. - */ - int256 public constant MAXIMUM_BASE_FEE = int256(uint256(type(uint128).max)); - - /** - * @notice Initial base fee value. This value must be smaller than the - * MAXIMUM_BASE_FEE. + * @notice Represents the configuration for the EIP-1559 based curve for the deposit gas + * market. These values should be set with care as it is possible to set them in + * a way that breaks the deposit gas market. The target resource limit is defined as + * maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a + * single word. There is additional space for additions in the future. + * + * @custom:field maxResourceLimit Represents the maximum amount of deposit gas that + * can be purchased per block. + * @custom:field elasticityMultiplier Determines the target resource limit along with + * the resource limit. + * @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block. + * @custom:field minimumBaseFee The min deposit base fee, it is clamped to this + * value. + * @custom:field systemTxMaxGas The amount of gas supplied to the system + * transaction. This should be set to the same number + * that the kroma-node sets as the gas limit for the + * system transaction. + * @custom:field maximumBaseFee The max deposit base fee, it is clamped to this + * value. */ - uint128 public constant INITIAL_BASE_FEE = 1 gwei; + struct ResourceConfig { + uint32 maxResourceLimit; + uint8 elasticityMultiplier; + uint8 baseFeeMaxChangeDenominator; + uint32 minimumBaseFee; + uint32 systemTxMaxGas; + uint128 maximumBaseFee; + } /** * @notice EIP-1559 style gas parameters. @@ -103,20 +93,25 @@ abstract contract ResourceMetering is Initializable { function _metered(uint64 _amount, uint256 _initialGas) internal { // Update block number and base fee if necessary. uint256 blockDiff = block.number - params.prevBlockNum; + + ResourceConfig memory config = _resourceConfig(); + int256 targetResourceLimit = int256(uint256(config.maxResourceLimit)) / + int256(uint256(config.elasticityMultiplier)); + if (blockDiff > 0) { // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate // at which deposits can be created and therefore limit the potential for deposits to // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes. - int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - TARGET_RESOURCE_LIMIT; + int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - targetResourceLimit; int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) / - (TARGET_RESOURCE_LIMIT * BASE_FEE_MAX_CHANGE_DENOMINATOR); + (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator))); // Update base fee by adding the base fee delta and clamp the resulting value between // min and max. int256 newBaseFee = Arithmetic.clamp({ _value: int256(uint256(params.prevBaseFee)) + baseFeeDelta, - _min: MINIMUM_BASE_FEE, - _max: MAXIMUM_BASE_FEE + _min: int256(uint256(config.minimumBaseFee)), + _max: int256(uint256(config.maximumBaseFee)) }); // If we skipped more than one block, we also need to account for every empty block. @@ -129,11 +124,11 @@ abstract contract ResourceMetering is Initializable { newBaseFee = Arithmetic.clamp({ _value: Arithmetic.cdexp({ _coefficient: newBaseFee, - _denominator: BASE_FEE_MAX_CHANGE_DENOMINATOR, + _denominator: int256(uint256(config.baseFeeMaxChangeDenominator)), _exponent: int256(blockDiff - 1) }), - _min: MINIMUM_BASE_FEE, - _max: MAXIMUM_BASE_FEE + _min: int256(uint256(config.minimumBaseFee)), + _max: int256(uint256(config.maximumBaseFee)) }); } @@ -146,7 +141,7 @@ abstract contract ResourceMetering is Initializable { // Make sure we can actually buy the resource amount requested by the user. params.prevBoughtGas += _amount; require( - int256(uint256(params.prevBoughtGas)) <= MAX_RESOURCE_LIMIT, + int256(uint256(params.prevBoughtGas)) <= int256(uint256(config.maxResourceLimit)), "ResourceMetering: cannot buy more gas than available gas limit" ); @@ -169,6 +164,14 @@ abstract contract ResourceMetering is Initializable { } } + /** + * @notice Virtual function that returns the resource config. Contracts that inherit this + * contract must implement this function. + * + * @return ResourceConfig + */ + function _resourceConfig() internal virtual returns (ResourceConfig memory); + /** * @notice Sets initial resource parameter values. This function must either be called by the * initializer function of an upgradeable child contract. @@ -176,7 +179,7 @@ abstract contract ResourceMetering is Initializable { // solhint-disable-next-line func-name-mixedcase function __ResourceMetering_init() internal onlyInitializing { params = ResourceParams({ - prevBaseFee: INITIAL_BASE_FEE, + prevBaseFee: 1 gwei, prevBoughtGas: 0, prevBlockNum: uint64(block.number) }); diff --git a/packages/contracts/contracts/L1/SystemConfig.sol b/packages/contracts/contracts/L1/SystemConfig.sol index c4e384caa7..13749606d0 100644 --- a/packages/contracts/contracts/L1/SystemConfig.sol +++ b/packages/contracts/contracts/L1/SystemConfig.sol @@ -6,6 +6,7 @@ import { } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { Semver } from "../universal/Semver.sol"; +import { ResourceMetering } from "./ResourceMetering.sol"; /** * @title SystemConfig @@ -43,19 +44,12 @@ contract SystemConfig is OwnableUpgradeable, Semver { bytes32 public constant UNSAFE_BLOCK_SIGNER_SLOT = keccak256("systemconfig.unsafeblocksigner"); /** - * @notice Minimum gas limit. This should not be lower than the maximum deposit gas resource - * limit in the ResourceMetering contract used by KromaPortal, to ensure the L2 - * block always has sufficient gas to process deposits. - */ - uint64 public constant MINIMUM_GAS_LIMIT = 8_000_000; - - /** - * @notice Fixed L2 gas overhead. + * @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation. */ uint256 public overhead; /** - * @notice Dynamic L2 gas overhead. + * @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation. */ uint256 public scalar; @@ -66,10 +60,17 @@ contract SystemConfig is OwnableUpgradeable, Semver { bytes32 public batcherHash; /** - * @notice L2 gas limit. + * @notice L2 block gas limit. */ uint64 public gasLimit; + /** + * @notice The configuration for the deposit fee market. Used by the KromaPortal + * to meter the cost of buying L2 gas on L1. Set as internal and wrapped with a getter + * so that the struct is returned instead of a tuple. + */ + ResourceMetering.ResourceConfig internal _resourceConfig; + /** * @notice Emitted when configuration is updated * @@ -88,6 +89,7 @@ contract SystemConfig is OwnableUpgradeable, Semver { * @param _batcherHash Initial batcher hash. * @param _gasLimit Initial gas limit. * @param _unsafeBlockSigner Initial unsafe block signer address. + * @param _config Initial resource config. */ constructor( address _owner, @@ -95,13 +97,23 @@ contract SystemConfig is OwnableUpgradeable, Semver { uint256 _scalar, bytes32 _batcherHash, uint64 _gasLimit, - address _unsafeBlockSigner + address _unsafeBlockSigner, + ResourceMetering.ResourceConfig memory _config ) Semver(0, 1, 0) { - initialize(_owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner); + initialize( + _owner, + _overhead, + _scalar, + _batcherHash, + _gasLimit, + _unsafeBlockSigner, + _config + ); } /** - * @notice Initializer. + * @notice Initializer. The resource config must be set before the + * require check. * * @param _owner Initial owner of the contract. * @param _overhead Initial overhead value. @@ -109,6 +121,7 @@ contract SystemConfig is OwnableUpgradeable, Semver { * @param _batcherHash Initial batcher hash. * @param _gasLimit Initial gas limit. * @param _unsafeBlockSigner Initial unsafe block signer address. + * @param _config Initial ResourceConfig. */ function initialize( address _owner, @@ -116,9 +129,9 @@ contract SystemConfig is OwnableUpgradeable, Semver { uint256 _scalar, bytes32 _batcherHash, uint64 _gasLimit, - address _unsafeBlockSigner + address _unsafeBlockSigner, + ResourceMetering.ResourceConfig memory _config ) public initializer { - require(_gasLimit >= MINIMUM_GAS_LIMIT, "SystemConfig: gas limit too low"); __Ownable_init(); transferOwnership(_owner); overhead = _overhead; @@ -126,6 +139,21 @@ contract SystemConfig is OwnableUpgradeable, Semver { batcherHash = _batcherHash; gasLimit = _gasLimit; _setUnsafeBlockSigner(_unsafeBlockSigner); + _setResourceConfig(_config); + require(_gasLimit >= minimumGasLimit(), "SystemConfig: gas limit too low"); + } + + /** + * @notice Returns the minimum L2 gas limit that can be safely set for the system to + * operate. The L2 gas limit must be larger than or equal to the amount of + * gas that is allocated for deposits per block plus the amount of gas that + * is allocated for the system transaction. + * This function is used to determine if changes to parameters are safe. + * + * @return uint64 + */ + function minimumGasLimit() public view returns (uint64) { + return uint64(_resourceConfig.maxResourceLimit) + uint64(_resourceConfig.systemTxMaxGas); } /** @@ -189,7 +217,7 @@ contract SystemConfig is OwnableUpgradeable, Semver { * @param _gasLimit New gas limit. */ function setGasLimit(uint64 _gasLimit) external onlyOwner { - require(_gasLimit >= MINIMUM_GAS_LIMIT, "SystemConfig: gas limit too low"); + require(_gasLimit >= minimumGasLimit(), "SystemConfig: gas limit too low"); gasLimit = _gasLimit; bytes memory data = abi.encode(_gasLimit); @@ -208,4 +236,60 @@ contract SystemConfig is OwnableUpgradeable, Semver { sstore(slot, _unsafeBlockSigner) } } + + /** + * @notice A getter for the resource config. Ensures that the struct is + * returned instead of a tuple. + * + * @return ResourceConfig + */ + function resourceConfig() external view returns (ResourceMetering.ResourceConfig memory) { + return _resourceConfig; + } + + /** + * @notice An external setter for the resource config. In the future, this + * method may emit an event that the `kroma-node` picks up for when the + * resource config is changed. + * + * @param _config The new resource config values. + */ + function setResourceConfig(ResourceMetering.ResourceConfig memory _config) external onlyOwner { + _setResourceConfig(_config); + } + + /** + * @notice An internal setter for the resource config. Ensures that the + * config is sane before storing it by checking for invariants. + * + * @param _config The new resource config. + */ + function _setResourceConfig(ResourceMetering.ResourceConfig memory _config) internal { + // Min base fee must be less than or equal to max base fee. + require( + _config.minimumBaseFee <= _config.maximumBaseFee, + "SystemConfig: min base fee must be less than max base" + ); + // Base fee change denominator must be greater than 0. + require(_config.baseFeeMaxChangeDenominator > 0, "SystemConfig: denominator cannot be 0"); + // Max resource limit plus system tx gas must be less than or equal to the L2 gas limit. + // The gas limit must be increased before these values can be increased. + require( + _config.maxResourceLimit + _config.systemTxMaxGas <= gasLimit, + "SystemConfig: gas limit too low" + ); + // Elasticity multiplier must be greater than 0. + require( + _config.elasticityMultiplier > 0, + "SystemConfig: elasticity multiplier cannot be 0" + ); + // No precision loss when computing target resource limit. + require( + ((_config.maxResourceLimit / _config.elasticityMultiplier) * + _config.elasticityMultiplier) == _config.maxResourceLimit, + "SystemConfig: precision loss with target resource limit" + ); + + _resourceConfig = _config; + } } diff --git a/packages/contracts/contracts/echidna/FuzzKromaPortal.sol b/packages/contracts/contracts/echidna/FuzzKromaPortal.sol index f7ad790147..e525313d82 100644 --- a/packages/contracts/contracts/echidna/FuzzKromaPortal.sol +++ b/packages/contracts/contracts/echidna/FuzzKromaPortal.sol @@ -2,7 +2,10 @@ pragma solidity 0.8.15; import { KromaPortal } from "../L1/KromaPortal.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; +import { ResourceMetering } from "../L1/ResourceMetering.sol"; +import { SystemConfig } from "../L1/SystemConfig.sol"; import { ZKMerkleTrie } from "../L1/ZKMerkleTrie.sol"; +import { Constants } from "../libraries/Constants.sol"; import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; contract EchidnaFuzzKromaPortal { @@ -10,10 +13,22 @@ contract EchidnaFuzzKromaPortal { bool internal failedToComplete; constructor() { + ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); + + SystemConfig systemConfig = new SystemConfig({ + _owner: address(1), + _overhead: 0, + _scalar: 10000, + _batcherHash: bytes32(0), + _gasLimit: 30_000_000, + _unsafeBlockSigner: address(0), + _config: rcfg + }); portal = new KromaPortal({ _l2Oracle: L2OutputOracle(address(0)), _guardian: address(0), _paused: false, + _config: systemConfig, _zkMerkleTrie: ZKMerkleTrie(address(0)) }); } diff --git a/packages/contracts/contracts/echidna/FuzzResourceMetering.sol b/packages/contracts/contracts/echidna/FuzzResourceMetering.sol index 658199f964..81e389a9a6 100644 --- a/packages/contracts/contracts/echidna/FuzzResourceMetering.sol +++ b/packages/contracts/contracts/echidna/FuzzResourceMetering.sol @@ -4,6 +4,7 @@ import { StdUtils } from "forge-std/Test.sol"; import { ResourceMetering } from "../L1/ResourceMetering.sol"; import { Arithmetic } from "../libraries/Arithmetic.sol"; +import { Constants } from "../libraries/Constants.sol"; contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { bool internal failedMaxGasPerBlock; @@ -25,6 +26,20 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { __ResourceMetering_init(); } + function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) { + return _resourceConfig(); + } + + function _resourceConfig() + internal + pure + override + returns (ResourceMetering.ResourceConfig memory) + { + ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); + return rcfg; + } + /** * @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test * the underlying resource metering/gas market logic @@ -35,12 +50,16 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { uint256 cachedPrevBoughtGas = uint256(params.prevBoughtGas); uint256 cachedPrevBlockNum = uint256(params.prevBlockNum); + ResourceMetering.ResourceConfig memory rcfg = resourceConfig(); + uint256 targetResourceLimit = uint256(rcfg.maxResourceLimit) / + uint256(rcfg.elasticityMultiplier); + // check that the last block's base fee hasn't dropped below the minimum - if (cachedPrevBaseFee < uint256(MINIMUM_BASE_FEE)) { + if (cachedPrevBaseFee < uint256(rcfg.minimumBaseFee)) { failedNeverBelowMinBaseFee = true; } // check that the last block didn't consume more than the max amount of gas - if (cachedPrevBoughtGas > uint256(MAX_RESOURCE_LIMIT)) { + if (cachedPrevBoughtGas > uint256(rcfg.maxResourceLimit)) { failedMaxGasPerBlock = true; } @@ -52,11 +71,11 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { if (_raiseBaseFee) { gasToBurn = bound( _gasToBurn, - uint256(TARGET_RESOURCE_LIMIT), - uint256(MAX_RESOURCE_LIMIT) + uint256(targetResourceLimit), + uint256(rcfg.maxResourceLimit) ); } else { - gasToBurn = bound(_gasToBurn, 0, uint256(TARGET_RESOURCE_LIMIT)); + gasToBurn = bound(_gasToBurn, 0, targetResourceLimit); } _burnInternal(uint64(gasToBurn)); @@ -64,13 +83,13 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { // Part 3: we run checks and modify our invariant flags based on the updated params values // Calculate the maximum allowed baseFee change (per block) - uint256 maxBaseFeeChange = cachedPrevBaseFee / uint256(BASE_FEE_MAX_CHANGE_DENOMINATOR); + uint256 maxBaseFeeChange = cachedPrevBaseFee / uint256(rcfg.baseFeeMaxChangeDenominator); // If the last block used more than the target amount of gas (and there were no // empty blocks in between), ensure this block's baseFee increased, but not by // more than the max amount per block if ( - (cachedPrevBoughtGas > uint256(TARGET_RESOURCE_LIMIT)) && + (cachedPrevBoughtGas > uint256(targetResourceLimit)) && (uint256(params.prevBlockNum) - cachedPrevBlockNum == 1) ) { failedRaiseBaseFee = failedRaiseBaseFee || (params.prevBaseFee <= cachedPrevBaseFee); @@ -82,7 +101,7 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { // If the last block used less than the target amount of gas, (or was empty), // ensure that: this block's baseFee was decreased, but not by more than the max amount if ( - (cachedPrevBoughtGas < uint256(TARGET_RESOURCE_LIMIT)) || + (cachedPrevBoughtGas < uint256(targetResourceLimit)) || (uint256(params.prevBlockNum) - cachedPrevBlockNum > 1) ) { // Invariant: baseFee should decrease @@ -105,11 +124,11 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { Arithmetic.clamp( Arithmetic.cdexp( int256(cachedPrevBaseFee), - BASE_FEE_MAX_CHANGE_DENOMINATOR, + int256(uint256(rcfg.baseFeeMaxChangeDenominator)), int256(uint256(params.prevBlockNum) - cachedPrevBlockNum) ), - MINIMUM_BASE_FEE, - MAXIMUM_BASE_FEE + int256(uint256(rcfg.minimumBaseFee)), + int256(uint256(rcfg.maximumBaseFee)) ) ); } diff --git a/packages/contracts/contracts/libraries/Constants.sol b/packages/contracts/contracts/libraries/Constants.sol index 9d63dbc13b..c92dac1e9d 100644 --- a/packages/contracts/contracts/libraries/Constants.sol +++ b/packages/contracts/contracts/libraries/Constants.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import { ResourceMetering } from "../L1/ResourceMetering.sol"; + /** * @title Constants * @notice Constants is a library for storing constants. Simple! Don't put everything in here, just @@ -24,4 +26,24 @@ library Constants { * non-zero to reduce the gas cost of message passing transactions. */ address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; + + /** + * @notice Returns the default values for the ResourceConfig. These are the recommended values + * for a production network. + */ + function DEFAULT_RESOURCE_CONFIG() + internal + pure + returns (ResourceMetering.ResourceConfig memory) + { + ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ + maxResourceLimit: 20_000_000, + elasticityMultiplier: 10, + baseFeeMaxChangeDenominator: 8, + minimumBaseFee: 1 gwei, + systemTxMaxGas: 1_000_000, + maximumBaseFee: type(uint128).max + }); + return config; + } } diff --git a/packages/contracts/contracts/test/BenchmarkTest.t.sol b/packages/contracts/contracts/test/BenchmarkTest.t.sol index f14baa9632..be3b6594f6 100644 --- a/packages/contracts/contracts/test/BenchmarkTest.t.sol +++ b/packages/contracts/contracts/test/BenchmarkTest.t.sol @@ -33,8 +33,6 @@ contract SetPrevBaseFee_Test is Portal_Initializer { // In order to achieve this we make no assertions, and handle everything else in the setUp() // function. contract GasBenchMark_KromaPortal is Portal_Initializer { - uint128 internal INITIAL_BASE_FEE; - // Reusable default values for a test withdrawal Types.WithdrawalTransaction _defaultTx; @@ -88,8 +86,6 @@ contract GasBenchMark_KromaPortal is Portal_Initializer { 1 ); - INITIAL_BASE_FEE = portal.INITIAL_BASE_FEE(); - // Fund the portal so that we can withdraw ETH. vm.deal(address(portal), 0xFFFFFFFF); } @@ -105,7 +101,7 @@ contract GasBenchMark_KromaPortal is Portal_Initializer { } function test_depositTransaction_benchmark_1() external { - setPrevBaseFee(vm, address(portal), INITIAL_BASE_FEE); + setPrevBaseFee(vm, address(portal), 1 gwei); portal.depositTransaction{ value: NON_ZERO_VALUE }( NON_ZERO_ADDRESS, ZERO_VALUE, @@ -126,16 +122,9 @@ contract GasBenchMark_KromaPortal is Portal_Initializer { } contract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer { - uint128 internal INITIAL_BASE_FEE; - - function setUp() public virtual override { - super.setUp(); - INITIAL_BASE_FEE = portal.INITIAL_BASE_FEE(); - } - function test_sendMessage_benchmark_0() external { vm.pauseGasMetering(); - setPrevBaseFee(vm, address(portal), INITIAL_BASE_FEE); + setPrevBaseFee(vm, address(portal), 1 gwei); // The amount of data typically sent during a bridge deposit. bytes memory data = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; @@ -154,13 +143,9 @@ contract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer { } } - contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer { - uint128 internal INITIAL_BASE_FEE; - function setUp() public virtual override { super.setUp(); - INITIAL_BASE_FEE = portal.INITIAL_BASE_FEE(); deal(address(L1Token), alice, 100000, true); vm.startPrank(alice, alice); L1Token.approve(address(L1Bridge), type(uint256).max); @@ -168,7 +153,7 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer { function test_depositETH_benchmark_0() external { vm.pauseGasMetering(); - setPrevBaseFee(vm, address(portal), INITIAL_BASE_FEE); + setPrevBaseFee(vm, address(portal), 1 gwei); vm.resumeGasMetering(); L1Bridge.bridgeETH{ value: 500 }(50000, hex""); } @@ -182,7 +167,7 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer { function test_depositERC20_benchmark_0() external { vm.pauseGasMetering(); - setPrevBaseFee(vm, address(portal), INITIAL_BASE_FEE); + setPrevBaseFee(vm, address(portal), 1 gwei); vm.resumeGasMetering(); L1Bridge.bridgeERC20({ _localToken: address(L1Token), @@ -220,7 +205,7 @@ contract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer { vm.deal(address(L1Bridge.MESSENGER()), 100); } - function test_finalizeBridgeETH_benchmark() external { + function test_finalizeBridgeETH_benchmark() external { // TODO: Make this more accurate. It is underestimating the cost because it pranks // the call coming from the messenger, which bypasses the portal // and oracle. diff --git a/packages/contracts/contracts/test/CommonTest.t.sol b/packages/contracts/contracts/test/CommonTest.t.sol index fd6581cdd1..2f1683f36c 100644 --- a/packages/contracts/contracts/test/CommonTest.t.sol +++ b/packages/contracts/contracts/test/CommonTest.t.sol @@ -7,21 +7,24 @@ import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { Test, StdUtils } from "forge-std/Test.sol"; -import { CodeDeployer } from "../libraries/CodeDeployer.sol"; -import { Predeploys } from "../libraries/Predeploys.sol"; -import { Types } from "../libraries/Types.sol"; import { Colosseum } from "../L1/Colosseum.sol"; import { KromaPortal } from "../L1/KromaPortal.sol"; import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol"; import { L1ERC721Bridge } from "../L1/L1ERC721Bridge.sol"; import { L1StandardBridge } from "../L1/L1StandardBridge.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; +import { ResourceMetering } from "../L1/ResourceMetering.sol"; +import { SystemConfig } from "../L1/SystemConfig.sol"; import { ZKMerkleTrie } from "../L1/ZKMerkleTrie.sol"; import { ZKVerifier } from "../L1/ZKVerifier.sol"; import { L2CrossDomainMessenger } from "../L2/L2CrossDomainMessenger.sol"; import { L2ERC721Bridge } from "../L2/L2ERC721Bridge.sol"; -import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol"; import { L2StandardBridge } from "../L2/L2StandardBridge.sol"; +import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol"; +import { CodeDeployer } from "../libraries/CodeDeployer.sol"; +import { Constants } from "../libraries/Constants.sol"; +import { Predeploys } from "../libraries/Predeploys.sol"; +import { Types } from "../libraries/Types.sol"; import { KromaMintableERC20 } from "../universal/KromaMintableERC20.sol"; import { KromaMintableERC20Factory } from "../universal/KromaMintableERC20Factory.sol"; import { KromaMintableERC721Factory } from "../universal/KromaMintableERC721Factory.sol"; @@ -170,6 +173,7 @@ contract Portal_Initializer is L2OutputOracle_Initializer, Poseidon2Deployer { // Test target KromaPortal portalImpl; KromaPortal portal; + SystemConfig systemConfig; event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); event WithdrawalProven( @@ -181,9 +185,27 @@ contract Portal_Initializer is L2OutputOracle_Initializer, Poseidon2Deployer { function setUp() public virtual override { super.setUp(); + ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG(); + + systemConfig = new SystemConfig({ + _owner: address(1), + _overhead: 0, + _scalar: 10000, + _batcherHash: bytes32(0), + _gasLimit: 30_000_000, + _unsafeBlockSigner: address(0), + _config: config + }); + zkMerkleTrie = new ZKMerkleTrie(deployPoseidon2()); - portalImpl = new KromaPortal({ _l2Oracle: oracle, _guardian: guardian, _paused: true, _zkMerkleTrie: zkMerkleTrie }); + portalImpl = new KromaPortal({ + _l2Oracle: oracle, + _guardian: guardian, + _paused: true, + _config: systemConfig, + _zkMerkleTrie: zkMerkleTrie + }); Proxy proxy = new Proxy(multisig); vm.prank(multisig); proxy.upgradeToAndCall( @@ -410,7 +432,8 @@ contract ERC721Bridge_Initializer is Messenger_Initializer { contract Colosseum_Initializer is L2OutputOracle_Initializer { uint256 immutable CHAIN_ID = 901; - bytes32 immutable DUMMY_HASH = hex"8e556cf0e9ed5d6b6ad79247cddc30112cfee4a207fb13903eb834b447aebae9"; + bytes32 immutable DUMMY_HASH = + hex"8e556cf0e9ed5d6b6ad79247cddc30112cfee4a207fb13903eb834b447aebae9"; uint256 immutable MAX_TXS = 25; // Test target @@ -624,15 +647,9 @@ contract FFIInterface is Test { return abi.decode(result, (uint256, uint256)); } - function getMerkleTrieFuzzCase(string memory variant) - external - returns ( - bytes32, - bytes memory, - bytes memory, - bytes[] memory - ) - { + function getMerkleTrieFuzzCase( + string memory variant + ) external returns (bytes32, bytes memory, bytes memory, bytes[] memory) { string[] memory cmds = new string[](5); cmds[0] = "./test-case-generator/fuzz"; cmds[1] = "-m"; diff --git a/packages/contracts/contracts/test/KromaPortal.t.sol b/packages/contracts/contracts/test/KromaPortal.t.sol index b387f88c42..f3329bf66e 100644 --- a/packages/contracts/contracts/test/KromaPortal.t.sol +++ b/packages/contracts/contracts/test/KromaPortal.t.sol @@ -5,6 +5,7 @@ import { stdError } from "forge-std/Test.sol"; import { KromaPortal } from "../L1/KromaPortal.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; +import { ResourceMetering } from "../L1/ResourceMetering.sol"; import { Hashing } from "../libraries/Hashing.sol"; import { Types } from "../libraries/Types.sol"; import { Proxy } from "../universal/Proxy.sol"; @@ -1039,10 +1040,11 @@ contract KromaPortalUpgradeable_Test is Portal_Initializer { } function test_params_initValuesOnProxy_succeeds() external { - (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = KromaPortal( - payable(address(proxy)) - ).params(); - assertEq(prevBaseFee, portalImpl.INITIAL_BASE_FEE()); + KromaPortal p = KromaPortal(payable(address(proxy))); + (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = p.params(); + ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); + + assertEq(prevBaseFee, rcfg.minimumBaseFee); assertEq(prevBoughtGas, 0); assertEq(prevBlockNum, initialBlockNum); } diff --git a/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol b/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol index 84c40f9bed..1ecb87c8c2 100644 --- a/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol +++ b/packages/contracts/contracts/test/L2ToL1MessagePasser.t.sol @@ -21,7 +21,7 @@ contract L2ToL1MessagePasserTest is CommonTest { event WithdrawerBalanceBurnt(uint256 indexed amount); - function setUp() public override { + function setUp() public virtual override { super.setUp(); messagePasser = new L2ToL1MessagePasser(); } diff --git a/packages/contracts/contracts/test/ResourceMetering.t.sol b/packages/contracts/contracts/test/ResourceMetering.t.sol index b57d877bd0..4ed1d3ba5d 100644 --- a/packages/contracts/contracts/test/ResourceMetering.t.sol +++ b/packages/contracts/contracts/test/ResourceMetering.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { ResourceMetering } from "../L1/ResourceMetering.sol"; +import { Constants } from "../libraries/Constants.sol"; import { Proxy } from "../universal/Proxy.sol"; contract MeterUser is ResourceMetering { @@ -15,6 +16,19 @@ contract MeterUser is ResourceMetering { __ResourceMetering_init(); } + function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) { + return _resourceConfig(); + } + + function _resourceConfig() + internal + pure + override + returns (ResourceMetering.ResourceConfig memory) + { + return Constants.DEFAULT_RESOURCE_CONFIG(); + } + function use(uint64 _amount) public metered(_amount) {} function set( @@ -30,6 +44,11 @@ contract MeterUser is ResourceMetering { } } +/** + * @title ResourceConfig + * @notice The tests are based on the default config values. It is expected that + * the config values used in these tests are ran in production. + */ contract ResourceMetering_Test is Test { MeterUser internal meter; uint64 initialBlockNum; @@ -39,42 +58,15 @@ contract ResourceMetering_Test is Test { initialBlockNum = uint64(block.number); } - /** - * @notice The INITIAL_BASE_FEE must be less than the MAXIMUM_BASE_FEE - * and greater than the MINIMUM_BASE_FEE. - */ - function test_meter_initialBaseFee_succeeds() external { - uint256 max = uint256(meter.MAXIMUM_BASE_FEE()); - uint256 min = uint256(meter.MINIMUM_BASE_FEE()); - uint256 initial = uint256(meter.INITIAL_BASE_FEE()); - assertTrue(max >= initial); - assertTrue(min <= initial); - } - - /** - * @notice The MINIMUM_BASE_FEE must be less than the MAXIMUM_BASE_FEE. - */ - function test_meter_minBaseFeeLessThanMaxBaseFee_succeeds() external { - uint256 max = uint256(meter.MAXIMUM_BASE_FEE()); - uint256 min = uint256(meter.MINIMUM_BASE_FEE()); - assertTrue(max > min); - } - function test_meter_initialResourceParams_succeeds() external { (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params(); + ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); - assertEq(prevBaseFee, meter.INITIAL_BASE_FEE()); + assertEq(prevBaseFee, rcfg.minimumBaseFee); assertEq(prevBoughtGas, 0); assertEq(prevBlockNum, initialBlockNum); } - function test_meter_maxValue_succeeds() external { - uint256 max = uint256(meter.MAX_RESOURCE_LIMIT()); - uint256 target = uint256(meter.TARGET_RESOURCE_LIMIT()); - uint256 elasticity = uint256(meter.ELASTICITY_MULTIPLIER()); - assertEq(max / elasticity, target); - } - function test_meter_updateParamsNoChange_succeeds() external { meter.use(0); // equivalent to just updating the base fee and block number (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params(); @@ -117,8 +109,9 @@ contract ResourceMetering_Test is Test { } function test_meter_updateNoGasDelta_succeeds() external { - uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT())); - meter.use(target); + ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); + uint256 target = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier); + meter.use(uint64(target)); (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params(); assertEq(prevBaseFee, 1000000000); @@ -127,12 +120,13 @@ contract ResourceMetering_Test is Test { } function test_meter_useMax_succeeds() external { - uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT())); - uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER())); - meter.use(target * elasticity); + ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); + uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier); + uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier); + meter.use(target * elasticityMultiplier); (, uint64 prevBoughtGas, ) = meter.params(); - assertEq(prevBoughtGas, target * elasticity); + assertEq(prevBoughtGas, target * elasticityMultiplier); vm.roll(initialBlockNum + 1); meter.use(0); @@ -141,10 +135,12 @@ contract ResourceMetering_Test is Test { } function test_meter_useMoreThanMax_reverts() external { - uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT())); - uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER())); + ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); + uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier); + uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier); + vm.expectRevert("ResourceMetering: cannot buy more gas than available gas limit"); - meter.use(target * elasticity + 1); + meter.use(target * elasticityMultiplier + 1); } // Demonstrates that the resource metering arithmetic can tolerate very large gaps between @@ -154,15 +150,16 @@ contract ResourceMetering_Test is Test { // At 12 seconds per block, this number is effectively unreachable. vm.assume(_blockDiff < 433576281058164217753225238677900874458691); - uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT())); - uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER())); - vm.assume(_amount < target * elasticity); + ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); + uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier); + uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier); + + vm.assume(_amount < target * elasticityMultiplier); vm.roll(initialBlockNum + _blockDiff); meter.use(_amount); } } - /** * @title CustomMeterUser * @notice A simple wrapper around `ResourceMetering` that allows the initial @@ -184,6 +181,15 @@ contract CustomMeterUser is ResourceMetering { }); } + function _resourceConfig() + internal + pure + override + returns (ResourceMetering.ResourceConfig memory) + { + return Constants.DEFAULT_RESOURCE_CONFIG(); + } + function use(uint64 _amount) public returns (uint256) { uint256 initialGas = gasleft(); _metered(_amount, initialGas); @@ -226,10 +232,11 @@ contract ArtifactResourceMetering_Test is Test { vm.roll(1_000_000); MeterUser base = new MeterUser(); - minimumBaseFee = uint128(uint256(base.MINIMUM_BASE_FEE())); - maximumBaseFee = uint128(uint256(base.MAXIMUM_BASE_FEE())); - maxResourceLimit = uint64(uint256(base.MAX_RESOURCE_LIMIT())); - targetResourceLimit = uint64(uint256(base.TARGET_RESOURCE_LIMIT())); + ResourceMetering.ResourceConfig memory rcfg = base.resourceConfig(); + minimumBaseFee = uint128(rcfg.minimumBaseFee); + maximumBaseFee = rcfg.maximumBaseFee; + maxResourceLimit = uint64(rcfg.maxResourceLimit); + targetResourceLimit = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier); outfile = string.concat(vm.projectRoot(), "/.resource-metering.csv"); try vm.removeFile(outfile) {} catch {} diff --git a/packages/contracts/contracts/test/SystemConfig.t.sol b/packages/contracts/contracts/test/SystemConfig.t.sol index 2c249465da..f9ebda5e71 100644 --- a/packages/contracts/contracts/test/SystemConfig.t.sol +++ b/packages/contracts/contracts/test/SystemConfig.t.sol @@ -1,7 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +import { ResourceMetering } from "../L1/ResourceMetering.sol"; import { SystemConfig } from "../L1/SystemConfig.sol"; +import { Constants } from "../libraries/Constants.sol"; import { CommonTest } from "./CommonTest.t.sol"; contract SystemConfig_Init is CommonTest { @@ -9,30 +11,51 @@ contract SystemConfig_Init is CommonTest { function setUp() public virtual override { super.setUp(); + + ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ + maxResourceLimit: 20_000_000, + elasticityMultiplier: 10, + baseFeeMaxChangeDenominator: 8, + minimumBaseFee: 1 gwei, + systemTxMaxGas: 1_000_000, + maximumBaseFee: type(uint128).max + }); + sysConf = new SystemConfig({ _owner: alice, _overhead: 2100, _scalar: 1000000, _batcherHash: bytes32(hex"abcd"), - _gasLimit: 9_000_000, - _unsafeBlockSigner: address(1) + _gasLimit: 30_000_000, + _unsafeBlockSigner: address(1), + _config: config }); } } -contract SystemConfig_Initialize_TestFail is CommonTest { +contract SystemConfig_Initialize_TestFail is SystemConfig_Init { function test_initialize_lowGasLimit_reverts() external { + uint64 minimumGasLimit = sysConf.minimumGasLimit(); + + ResourceMetering.ResourceConfig memory cfg = ResourceMetering.ResourceConfig({ + maxResourceLimit: 20_000_000, + elasticityMultiplier: 10, + baseFeeMaxChangeDenominator: 8, + minimumBaseFee: 1 gwei, + systemTxMaxGas: 1_000_000, + maximumBaseFee: type(uint128).max + }); + vm.expectRevert("SystemConfig: gas limit too low"); - // The minimum gas limit defined in SystemConfig: - uint64 MINIMUM_GAS_LIMIT = 8_000_000; new SystemConfig({ _owner: alice, _overhead: 0, _scalar: 0, _batcherHash: bytes32(hex""), - _gasLimit: MINIMUM_GAS_LIMIT - 1, - _unsafeBlockSigner: address(1) + _gasLimit: minimumGasLimit - 1, + _unsafeBlockSigner: address(1), + _config: cfg }); } } @@ -57,6 +80,70 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { vm.expectRevert("Ownable: caller is not the owner"); sysConf.setUnsafeBlockSigner(address(0x20)); } + + function test_setResourceConfig_notOwner_reverts() external { + ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG(); + vm.expectRevert("Ownable: caller is not the owner"); + sysConf.setResourceConfig(config); + } + + function test_setResourceConfig_badMinMax_reverts() external { + ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ + maxResourceLimit: 20_000_000, + elasticityMultiplier: 10, + baseFeeMaxChangeDenominator: 8, + systemTxMaxGas: 1_000_000, + minimumBaseFee: 2 gwei, + maximumBaseFee: 1 gwei + }); + vm.prank(sysConf.owner()); + vm.expectRevert("SystemConfig: min base fee must be less than max base"); + sysConf.setResourceConfig(config); + } + + function test_setResourceConfig_zeroDenominator_reverts() external { + ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ + maxResourceLimit: 20_000_000, + elasticityMultiplier: 10, + baseFeeMaxChangeDenominator: 0, + systemTxMaxGas: 1_000_000, + minimumBaseFee: 1 gwei, + maximumBaseFee: 2 gwei + }); + vm.prank(sysConf.owner()); + vm.expectRevert("SystemConfig: denominator cannot be 0"); + sysConf.setResourceConfig(config); + } + + function test_setResourceConfig_lowGasLimit_reverts() external { + uint64 gasLimit = sysConf.gasLimit(); + + ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ + maxResourceLimit: uint32(gasLimit), + elasticityMultiplier: 10, + baseFeeMaxChangeDenominator: 8, + systemTxMaxGas: uint32(gasLimit), + minimumBaseFee: 1 gwei, + maximumBaseFee: 2 gwei + }); + vm.prank(sysConf.owner()); + vm.expectRevert("SystemConfig: gas limit too low"); + sysConf.setResourceConfig(config); + } + + function test_setResourceConfig_badPrecision_reverts() external { + ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ + maxResourceLimit: 20_000_000, + elasticityMultiplier: 11, + baseFeeMaxChangeDenominator: 8, + systemTxMaxGas: 1_000_000, + minimumBaseFee: 1 gwei, + maximumBaseFee: 2 gwei + }); + vm.prank(sysConf.owner()); + vm.expectRevert("SystemConfig: precision loss with target resource limit"); + sysConf.setResourceConfig(config); + } } contract SystemConfig_Setters_Test is SystemConfig_Init { @@ -90,7 +177,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { } function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external { - uint64 minimumGasLimit = sysConf.MINIMUM_GAS_LIMIT(); + uint64 minimumGasLimit = sysConf.minimumGasLimit(); newGasLimit = uint64( bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(type(uint64).max)) ); diff --git a/packages/contracts/contracts/test/invariants/SystemConfig.t.sol b/packages/contracts/contracts/test/invariants/SystemConfig.t.sol index 903f6ed73c..e0fac27f2a 100644 --- a/packages/contracts/contracts/test/invariants/SystemConfig.t.sol +++ b/packages/contracts/contracts/test/invariants/SystemConfig.t.sol @@ -3,18 +3,23 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { SystemConfig } from "../../L1/SystemConfig.sol"; +import { ResourceMetering } from "../../L1/ResourceMetering.sol"; +import { Constants } from "../../libraries/Constants.sol"; contract SystemConfig_GasLimitLowerBound_Invariant is Test { SystemConfig public config; function setUp() public { + ResourceMetering.ResourceConfig memory cfg = Constants.DEFAULT_RESOURCE_CONFIG(); + config = new SystemConfig({ _owner: address(0xbeef), _overhead: 2100, _scalar: 1000000, _batcherHash: bytes32(hex"abcd"), - _gasLimit: 8_000_000, - _unsafeBlockSigner: address(1) + _gasLimit: 30_000_000, + _unsafeBlockSigner: address(1), + _config: cfg }); // Set the target contract to the `config` @@ -38,6 +43,6 @@ contract SystemConfig_GasLimitLowerBound_Invariant is Test { * than the hard-coded lower bound. */ function invariant_gasLimitLowerBound() external { - assertTrue(config.gasLimit() >= config.MINIMUM_GAS_LIMIT()); + assertTrue(config.gasLimit() >= config.minimumGasLimit()); } } diff --git a/packages/contracts/contracts/universal/Proxy.sol b/packages/contracts/contracts/universal/Proxy.sol index f2fead040b..52944a97c8 100644 --- a/packages/contracts/contracts/universal/Proxy.sol +++ b/packages/contracts/contracts/universal/Proxy.sol @@ -84,7 +84,7 @@ contract Proxy { * * @param _implementation Address of the implementation contract. */ - function upgradeTo(address _implementation) external proxyCallIfNotAdmin { + function upgradeTo(address _implementation) public virtual proxyCallIfNotAdmin { _setImplementation(_implementation); } @@ -95,12 +95,10 @@ contract Proxy { * @param _implementation Address of the implementation contract. * @param _data Calldata to delegatecall the new implementation with. */ - function upgradeToAndCall(address _implementation, bytes calldata _data) - external - payable - proxyCallIfNotAdmin - returns (bytes memory) - { + function upgradeToAndCall( + address _implementation, + bytes calldata _data + ) public payable virtual proxyCallIfNotAdmin returns (bytes memory) { _setImplementation(_implementation); (bool success, bytes memory returndata) = _implementation.delegatecall(_data); require(success, "Proxy: delegatecall to new implementation contract failed"); @@ -112,7 +110,7 @@ contract Proxy { * * @param _admin New owner of the proxy contract. */ - function changeAdmin(address _admin) external proxyCallIfNotAdmin { + function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin { _changeAdmin(_admin); } @@ -121,7 +119,7 @@ contract Proxy { * * @return Owner address. */ - function admin() external proxyCallIfNotAdmin returns (address) { + function admin() public virtual proxyCallIfNotAdmin returns (address) { return _getAdmin(); } @@ -130,7 +128,7 @@ contract Proxy { * * @return Implementation address. */ - function implementation() external proxyCallIfNotAdmin returns (address) { + function implementation() public virtual proxyCallIfNotAdmin returns (address) { return _getImplementation(); } diff --git a/packages/contracts/deploy-config/devnetL1.json b/packages/contracts/deploy-config/devnetL1.json index c0456bc7c0..02bec3035a 100644 --- a/packages/contracts/deploy-config/devnetL1.json +++ b/packages/contracts/deploy-config/devnetL1.json @@ -13,7 +13,7 @@ "l2OutputOracleSubmissionInterval": 20, "l2OutputOracleStartingTimestamp": -1, "l2OutputOracleValidator": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - "l2GenesisBlockGasLimit": "0xE4E1C0", + "l2GenesisBlockGasLimit": "0x1c9c380", "l1BlockTime": 3, "cliqueSignerAddress": "0xca062b0fd91172d89bcd4bb084ac4e21972cc467", "protocolVaultRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", @@ -35,5 +35,6 @@ "l1GenesisBlockTimestamp": "0x638a4554", "l1StartingBlockTag": "earliest", "colosseumChallengeTimeout": 120, - "colosseumSegmentsLengths": "3,11" + "colosseumSegmentsLengths": "3,11", + "numDeployConfirmations": 1 } diff --git a/packages/contracts/deploy-config/easel.json b/packages/contracts/deploy-config/easel.json index 721e0455c7..7fff882611 100644 --- a/packages/contracts/deploy-config/easel.json +++ b/packages/contracts/deploy-config/easel.json @@ -22,7 +22,7 @@ "l2OutputOracleValidator": "0x496c79132B773940ca5B38EBcc0C56887a0ea164", "finalizationPeriodSeconds": 60, "proxyAdminOwner": "0x69487D0D1F969E99D3b68C4F79F0F47375c4Ee4A", - "l2GenesisBlockGasLimit": "0x17D7840", + "l2GenesisBlockGasLimit": "0x1c9c380", "l2GenesisBlockCoinbase": "0x4200000000000000000000000000000000000008", "l2GenesisBlockBaseFeePerGas": "0x3b9aca00", "l2GenesisBlueTimeOffset": "0x0", @@ -31,5 +31,6 @@ "eip1559Denominator": 50, "eip1559Elasticity": 10, "colosseumChallengeTimeout": 120, - "colosseumSegmentsLengths": "6,5" + "colosseumSegmentsLengths": "6,5", + "numDeployConfirmations": 1 } diff --git a/packages/contracts/deploy-config/sepolia.json b/packages/contracts/deploy-config/sepolia.json index a28291b98c..3c309c930f 100644 --- a/packages/contracts/deploy-config/sepolia.json +++ b/packages/contracts/deploy-config/sepolia.json @@ -21,7 +21,7 @@ "l2OutputOracleStartingTimestamp": -1, "l2OutputOracleValidator": "0xf921640daca3cbadc982e4cd3e1352dfc3a6b39e", "finalizationPeriodSeconds": 600, - "l2GenesisBlockGasLimit": "0x17D7840", + "l2GenesisBlockGasLimit": "0x1c9c380", "l2GenesisBlockCoinbase": "0x4200000000000000000000000000000000000008", "l2GenesisBlockBaseFeePerGas": "0x3b9aca00", "l2GenesisBlueTimeOffset": "0x34adf0", @@ -30,5 +30,6 @@ "eip1559Denominator": 50, "eip1559Elasticity": 10, "colosseumChallengeTimeout": 120, - "colosseumSegmentsLengths": "6,5" + "colosseumSegmentsLengths": "6,5", + "numDeployConfirmations": 1 } diff --git a/packages/contracts/deploy/000-ProxyAdmin.ts b/packages/contracts/deploy/000-ProxyAdmin.ts index bc3222d06a..aea776caf8 100644 --- a/packages/contracts/deploy/000-ProxyAdmin.ts +++ b/packages/contracts/deploy/000-ProxyAdmin.ts @@ -13,6 +13,6 @@ const deployFn: DeployFunction = async (hre) => { }) } -deployFn.tags = ['ProxyAdmin', 'setup'] +deployFn.tags = ['ProxyAdmin', 'setup', 'l1'] export default deployFn diff --git a/packages/contracts/deploy/001-Proxies.ts b/packages/contracts/deploy/001-Proxies.ts index d8c3e52922..cd9eca0c84 100644 --- a/packages/contracts/deploy/001-Proxies.ts +++ b/packages/contracts/deploy/001-Proxies.ts @@ -21,6 +21,6 @@ const deployFn: DeployFunction = async (hre) => { } } -deployFn.tags = [...PROXY_NAMES, 'setup'] +deployFn.tags = [...PROXY_NAMES, 'setup', 'l1'] export default deployFn diff --git a/packages/contracts/deploy/002-ZKMerkleTrie.ts b/packages/contracts/deploy/002-ZKMerkleTrie.ts index 4d31d13f9d..173d408f63 100644 --- a/packages/contracts/deploy/002-ZKMerkleTrie.ts +++ b/packages/contracts/deploy/002-ZKMerkleTrie.ts @@ -22,6 +22,6 @@ const deployFn: DeployFunction = async (hre) => { }) } -deployFn.tags = ['ZKMerkleTrie', 'Poseidon2', 'setup'] +deployFn.tags = ['ZKMerkleTrie', 'Poseidon2', 'setup', 'l1'] export default deployFn diff --git a/packages/contracts/deploy/003-L1CrossDomainMessenger.ts b/packages/contracts/deploy/003-L1CrossDomainMessenger.ts index 5b86eae6a6..0a7e6834ab 100644 --- a/packages/contracts/deploy/003-L1CrossDomainMessenger.ts +++ b/packages/contracts/deploy/003-L1CrossDomainMessenger.ts @@ -17,15 +17,11 @@ const deployFn: DeployFunction = async (hre) => { isProxyImpl: true, initArgs: [], postDeployAction: async (contract) => { - await assertContractVariable( - contract, - 'PORTAL', - KromaPortalProxy.address - ) + await assertContractVariable(contract, 'PORTAL', KromaPortalProxy.address) }, }) } -deployFn.tags = ['L1CrossDomainMessenger', 'setup'] +deployFn.tags = ['L1CrossDomainMessenger', 'setup', 'l1'] export default deployFn diff --git a/packages/contracts/deploy/004-L1StandardBridge.ts b/packages/contracts/deploy/004-L1StandardBridge.ts index 9ea9b89088..9b7ee7a691 100644 --- a/packages/contracts/deploy/004-L1StandardBridge.ts +++ b/packages/contracts/deploy/004-L1StandardBridge.ts @@ -31,6 +31,6 @@ const deployFn: DeployFunction = async (hre) => { }) } -deployFn.tags = ['L1StandardBridge', 'setup'] +deployFn.tags = ['L1StandardBridge', 'setup', 'l1'] export default deployFn diff --git a/packages/contracts/deploy/005-L1ERC721Bridge.ts b/packages/contracts/deploy/005-L1ERC721Bridge.ts index 410e6f359a..c17fcf564e 100644 --- a/packages/contracts/deploy/005-L1ERC721Bridge.ts +++ b/packages/contracts/deploy/005-L1ERC721Bridge.ts @@ -26,6 +26,6 @@ const deployFn: DeployFunction = async (hre) => { }) } -deployFn.tags = ['L1ERC721Bridge', 'setup'] +deployFn.tags = ['L1ERC721Bridge', 'setup', 'l1'] export default deployFn diff --git a/packages/contracts/deploy/006-KromaMintableERC20Factory.ts b/packages/contracts/deploy/006-KromaMintableERC20Factory.ts index 2288fa9a35..52534e8a38 100644 --- a/packages/contracts/deploy/006-KromaMintableERC20Factory.ts +++ b/packages/contracts/deploy/006-KromaMintableERC20Factory.ts @@ -25,6 +25,6 @@ const deployFn: DeployFunction = async (hre) => { }) } -deployFn.tags = ['KromaMintableERC20Factory', 'setup'] +deployFn.tags = ['KromaMintableERC20Factory', 'setup', 'l1'] export default deployFn diff --git a/packages/contracts/deploy/007-L2OutputOracle.ts b/packages/contracts/deploy/007-L2OutputOracle.ts index 13ea36e935..ec6ef739d0 100644 --- a/packages/contracts/deploy/007-L2OutputOracle.ts +++ b/packages/contracts/deploy/007-L2OutputOracle.ts @@ -69,6 +69,6 @@ const deployFn: DeployFunction = async (hre) => { }) } -deployFn.tags = ['L2OutputOracle', 'setup'] +deployFn.tags = ['L2OutputOracle', 'setup', 'l1'] export default deployFn diff --git a/packages/contracts/deploy/009-Colosseum.ts b/packages/contracts/deploy/009-Colosseum.ts index bee56ef1f2..2d8c3cda6b 100644 --- a/packages/contracts/deploy/009-Colosseum.ts +++ b/packages/contracts/deploy/009-Colosseum.ts @@ -47,6 +47,6 @@ const deployFn: DeployFunction = async (hre) => { }) } -deployFn.tags = ['Colosseum', 'ZKVerifier', 'setup'] +deployFn.tags = ['Colosseum', 'ZKVerifier', 'setup', 'l1'] export default deployFn diff --git a/packages/contracts/deploy/010-KromaPortal.ts b/packages/contracts/deploy/010-KromaPortal.ts index e9de34efd8..7de59c01c4 100644 --- a/packages/contracts/deploy/010-KromaPortal.ts +++ b/packages/contracts/deploy/010-KromaPortal.ts @@ -13,6 +13,10 @@ const deployFn: DeployFunction = async (hre) => { 'L2OutputOracleProxy' ) + const Artifact__SystemConfigProxy = await hre.deployments.get( + 'SystemConfigProxy' + ) + const ZKMerkleTrie = await getContractFromArtifact(hre, 'ZKMerkleTrie') await deploy(hre, 'KromaPortal', { @@ -20,6 +24,7 @@ const deployFn: DeployFunction = async (hre) => { L2OutputOracleProxy.address, hre.deployConfig.portalGuardian, false, + Artifact__SystemConfigProxy.address, ZKMerkleTrie.address, ], isProxyImpl: true, @@ -35,6 +40,11 @@ const deployFn: DeployFunction = async (hre) => { 'GUARDIAN', hre.deployConfig.portalGuardian ) + await assertContractVariable( + contract, + 'SYSTEM_CONFIG', + Artifact__SystemConfigProxy.address + ) await assertContractVariable( contract, 'ZK_MERKLE_TRIE', @@ -44,6 +54,6 @@ const deployFn: DeployFunction = async (hre) => { }) } -deployFn.tags = ['KromaPortal', 'setup'] +deployFn.tags = ['KromaPortal', 'setup', 'l1'] export default deployFn diff --git a/packages/contracts/deploy/011-SystemConfig.ts b/packages/contracts/deploy/011-SystemConfig.ts index 5dbbdbff0e..c07714aecf 100644 --- a/packages/contracts/deploy/011-SystemConfig.ts +++ b/packages/contracts/deploy/011-SystemConfig.ts @@ -1,8 +1,13 @@ +import assert from 'assert' + import '@kroma-network/hardhat-deploy-config' +import { ethers } from 'ethers' import { DeployFunction } from 'hardhat-deploy/dist/types' import { assertContractVariable, deploy } from '../src/deploy-utils' +const uint128Max = ethers.BigNumber.from('0xffffffffffffffffffffffffffffffff') + const deployFn: DeployFunction = async (hre) => { const batcherHash = hre.ethers.utils .hexZeroPad(hre.deployConfig.batchSenderAddress, 32) @@ -16,6 +21,14 @@ const deployFn: DeployFunction = async (hre) => { batcherHash, hre.deployConfig.l2GenesisBlockGasLimit, hre.deployConfig.p2pProposerAddress, + { + maxResourceLimit: 20_000_000, + elasticityMultiplier: 10, + baseFeeMaxChangeDenominator: 8, + systemTxMaxGas: 1_000_000, + minimumBaseFee: ethers.utils.parseUnits('1', 'gwei'), + maximumBaseFee: uint128Max, + }, ], isProxyImpl: true, initArgs: [ @@ -48,10 +61,18 @@ const deployFn: DeployFunction = async (hre) => { 'unsafeBlockSigner', hre.deployConfig.p2pProposerAddress ) + + const config = await contract.resourceConfig() + assert(config.maxResourceLimit === 20_000_000) + assert(config.elasticityMultiplier === 10) + assert(config.baseFeeMaxChangeDenominator === 8) + assert(config.systemTxMaxGas === 1_000_000) + assert(ethers.utils.parseUnits('1', 'gwei').eq(config.minimumBaseFee)) + assert(config.maximumBaseFee.eq(uint128Max)) }, }) } -deployFn.tags = ['SystemConfig', 'setup'] +deployFn.tags = ['SystemConfig', 'setup', 'l1'] export default deployFn diff --git a/packages/contracts/deploy/100-L1Block.ts b/packages/contracts/deploy/100-L1Block.ts new file mode 100644 index 0000000000..65f203dfc7 --- /dev/null +++ b/packages/contracts/deploy/100-L1Block.ts @@ -0,0 +1,23 @@ +import '@kroma-network/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { ethers } from 'ethers' +import { DeployFunction } from 'hardhat-deploy/dist/types' + +import { assertContractVariable, deploy } from '../src/deploy-utils' + +const deployFn: DeployFunction = async (hre) => { + await deploy(hre, 'L1Block', { + args: [], + postDeployAction: async (contract) => { + await assertContractVariable( + contract, + 'DEPOSITOR_ACCOUNT', + ethers.utils.getAddress('0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001') + ) + }, + }) +} + +deployFn.tags = ['L1Block', 'l2'] + +export default deployFn diff --git a/packages/contracts/deploy/101-L2CrossDomainMessenger.ts b/packages/contracts/deploy/101-L2CrossDomainMessenger.ts new file mode 100644 index 0000000000..3d195eb352 --- /dev/null +++ b/packages/contracts/deploy/101-L2CrossDomainMessenger.ts @@ -0,0 +1,27 @@ +import '@kroma-network/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { ethers } from 'ethers' +import { DeployFunction } from 'hardhat-deploy/dist/types' + +import { assertContractVariable, deploy } from '../src/deploy-utils' + +const deployFn: DeployFunction = async (hre) => { + const Artifact__L1CrossDomainMessenger = await hre.companionNetworks[ + 'l1' + ].deployments.get('L1CrossDomainMessengerProxy') + + await deploy(hre, 'L2CrossDomainMessenger', { + args: [Artifact__L1CrossDomainMessenger.address], + postDeployAction: async (contract) => { + await assertContractVariable( + contract, + 'OTHER_MESSENGER', + ethers.utils.getAddress(Artifact__L1CrossDomainMessenger.address) + ) + }, + }) +} + +deployFn.tags = ['L2CrossDomainMessenger', 'l2'] + +export default deployFn diff --git a/packages/contracts/deploy/102-L2StandardBridge.ts b/packages/contracts/deploy/102-L2StandardBridge.ts new file mode 100644 index 0000000000..1e17b16023 --- /dev/null +++ b/packages/contracts/deploy/102-L2StandardBridge.ts @@ -0,0 +1,27 @@ +import '@kroma-network/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { ethers } from 'ethers' +import { DeployFunction } from 'hardhat-deploy/dist/types' + +import { assertContractVariable, deploy } from '../src/deploy-utils' + +const deployFn: DeployFunction = async (hre) => { + const Artifact__L1StandardBridge = await hre.companionNetworks[ + 'l1' + ].deployments.get('L1StandardBridgeProxy') + + await deploy(hre, 'L2StandardBridge', { + args: [Artifact__L1StandardBridge.address], + postDeployAction: async (contract) => { + await assertContractVariable( + contract, + 'OTHER_BRIDGE', + ethers.utils.getAddress(Artifact__L1StandardBridge.address) + ) + }, + }) +} + +deployFn.tags = ['L2StandardBridge', 'l2'] + +export default deployFn diff --git a/packages/contracts/deploy/103-L2ToL1MessagePasser.ts b/packages/contracts/deploy/103-L2ToL1MessagePasser.ts new file mode 100644 index 0000000000..1d1a32a0bc --- /dev/null +++ b/packages/contracts/deploy/103-L2ToL1MessagePasser.ts @@ -0,0 +1,18 @@ +import '@kroma-network/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { DeployFunction } from 'hardhat-deploy/dist/types' + +import { assertContractVariable, deploy } from '../src/deploy-utils' + +const deployFn: DeployFunction = async (hre) => { + await deploy(hre, 'L2ToL1MessagePasser', { + args: [], + postDeployAction: async (contract) => { + await assertContractVariable(contract, 'MESSAGE_VERSION', 0) + }, + }) +} + +deployFn.tags = ['L2ToL1MessagePasser', 'l2'] + +export default deployFn diff --git a/packages/contracts/deploy/104-L2ERC721Bridge.ts b/packages/contracts/deploy/104-L2ERC721Bridge.ts new file mode 100644 index 0000000000..c4ec9e2805 --- /dev/null +++ b/packages/contracts/deploy/104-L2ERC721Bridge.ts @@ -0,0 +1,33 @@ +import '@kroma-network/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { ethers } from 'ethers' +import { DeployFunction } from 'hardhat-deploy/dist/types' + +import { predeploys } from '../src/constants' +import { assertContractVariable, deploy } from '../src/deploy-utils' + +const deployFn: DeployFunction = async (hre) => { + const Artifact__L1ERC721Bridge = await hre.companionNetworks[ + 'l1' + ].deployments.get('L1ERC721BridgeProxy') + + await deploy(hre, 'L2ERC721Bridge', { + args: [predeploys.L2CrossDomainMessenger, Artifact__L1ERC721Bridge.address], + postDeployAction: async (contract) => { + await assertContractVariable( + contract, + 'MESSENGER', + ethers.utils.getAddress(predeploys.L2CrossDomainMessenger) + ) + await assertContractVariable( + contract, + 'OTHER_BRIDGE', + ethers.utils.getAddress(Artifact__L1ERC721Bridge.address) + ) + }, + }) +} + +deployFn.tags = ['L2ERC721Bridge', 'l2'] + +export default deployFn diff --git a/packages/contracts/deploy/105-GasPriceOracle.ts b/packages/contracts/deploy/105-GasPriceOracle.ts new file mode 100644 index 0000000000..aaf17f7200 --- /dev/null +++ b/packages/contracts/deploy/105-GasPriceOracle.ts @@ -0,0 +1,18 @@ +import '@kroma-network/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { DeployFunction } from 'hardhat-deploy/dist/types' + +import { assertContractVariable, deploy } from '../src/deploy-utils' + +const deployFn: DeployFunction = async (hre) => { + await deploy(hre, 'GasPriceOracle', { + args: [], + postDeployAction: async (contract) => { + await assertContractVariable(contract, 'DECIMALS', 6) + }, + }) +} + +deployFn.tags = ['GasPriceOracle', 'l2'] + +export default deployFn diff --git a/packages/contracts/deploy/106-ValidatorRewardVault.ts b/packages/contracts/deploy/106-ValidatorRewardVault.ts new file mode 100644 index 0000000000..b88be4e519 --- /dev/null +++ b/packages/contracts/deploy/106-ValidatorRewardVault.ts @@ -0,0 +1,32 @@ +import '@kroma-network/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { ethers } from 'ethers' +import { DeployFunction } from 'hardhat-deploy/dist/types' + +import { assertContractVariable, deploy } from '../src/deploy-utils' + +const deployFn: DeployFunction = async (hre) => { + const l1 = hre.network.companionNetworks['l1'] + const deployConfig = hre.getDeployConfig(l1) + + const validatorRewardVaultRecipient = + deployConfig.validatorRewardVaultRecipient + if (validatorRewardVaultRecipient === ethers.constants.AddressZero) { + throw new Error(`ValidatorRewardVault RECIPIENT zero address`) + } + + await deploy(hre, 'ValidatorRewardVault', { + args: [validatorRewardVaultRecipient], + postDeployAction: async (contract) => { + await assertContractVariable( + contract, + 'RECIPIENT', + ethers.utils.getAddress(validatorRewardVaultRecipient) + ) + }, + }) +} + +deployFn.tags = ['ValidatorRewardVault', 'l2'] + +export default deployFn diff --git a/packages/contracts/deploy/107-ProtocolVault.ts b/packages/contracts/deploy/107-ProtocolVault.ts new file mode 100644 index 0000000000..6bc14dbf53 --- /dev/null +++ b/packages/contracts/deploy/107-ProtocolVault.ts @@ -0,0 +1,31 @@ +import '@kroma-network/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { ethers } from 'ethers' +import { DeployFunction } from 'hardhat-deploy/dist/types' + +import { assertContractVariable, deploy } from '../src/deploy-utils' + +const deployFn: DeployFunction = async (hre) => { + const l1 = hre.network.companionNetworks['l1'] + const deployConfig = hre.getDeployConfig(l1) + + const protocolVaultRecipient = deployConfig.protocolVaultRecipient + if (protocolVaultRecipient === ethers.constants.AddressZero) { + throw new Error('ProtocolVault RECIPIENT zero address') + } + + await deploy(hre, 'ProtocolVault', { + args: [protocolVaultRecipient], + postDeployAction: async (contract) => { + await assertContractVariable( + contract, + 'RECIPIENT', + ethers.utils.getAddress(protocolVaultRecipient) + ) + }, + }) +} + +deployFn.tags = ['ProtocolVault', 'l2'] + +export default deployFn diff --git a/packages/contracts/deploy/108-ProposerRewardVault.ts b/packages/contracts/deploy/108-ProposerRewardVault.ts new file mode 100644 index 0000000000..10be1769e1 --- /dev/null +++ b/packages/contracts/deploy/108-ProposerRewardVault.ts @@ -0,0 +1,31 @@ +import '@kroma-network/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { ethers } from 'ethers' +import { DeployFunction } from 'hardhat-deploy/dist/types' + +import { assertContractVariable, deploy } from '../src/deploy-utils' + +const deployFn: DeployFunction = async (hre) => { + const l1 = hre.network.companionNetworks['l1'] + const deployConfig = hre.getDeployConfig(l1) + + const ProposerRewardVaultRecipient = deployConfig.ProposerRewardVaultRecipient + if (ProposerRewardVaultRecipient === ethers.constants.AddressZero) { + throw new Error('ProposerRewardVault RECIPIENT zero address') + } + + await deploy(hre, 'ProposerRewardVault', { + args: [ProposerRewardVaultRecipient], + postDeployAction: async (contract) => { + await assertContractVariable( + contract, + 'RECIPIENT', + ethers.utils.getAddress(ProposerRewardVaultRecipient) + ) + }, + }) +} + +deployFn.tags = ['ProposerRewardVault', 'l2'] + +export default deployFn diff --git a/packages/contracts/deploy/109-KromaMintableERC20Factory.ts b/packages/contracts/deploy/109-KromaMintableERC20Factory.ts new file mode 100644 index 0000000000..b7a663bcc2 --- /dev/null +++ b/packages/contracts/deploy/109-KromaMintableERC20Factory.ts @@ -0,0 +1,24 @@ +import '@kroma-network/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { ethers } from 'ethers' +import { DeployFunction } from 'hardhat-deploy/dist/types' + +import { predeploys } from '../src/constants' +import { assertContractVariable, deploy } from '../src/deploy-utils' + +const deployFn: DeployFunction = async (hre) => { + await deploy(hre, 'KromaMintableERC20Factory', { + args: [predeploys.L2StandardBridge], + postDeployAction: async (contract) => { + await assertContractVariable( + contract, + 'BRIDGE', + ethers.utils.getAddress(predeploys.L2StandardBridge) + ) + }, + }) +} + +deployFn.tags = ['KromaMintableERC20Factory', 'l2'] + +export default deployFn diff --git a/packages/contracts/deploy/110-KromaMintableERC721Factory.ts b/packages/contracts/deploy/110-KromaMintableERC721Factory.ts new file mode 100644 index 0000000000..3bebd63887 --- /dev/null +++ b/packages/contracts/deploy/110-KromaMintableERC721Factory.ts @@ -0,0 +1,31 @@ +import '@kroma-network/hardhat-deploy-config' +import '@nomiclabs/hardhat-ethers' +import { ethers } from 'ethers' +import { DeployFunction } from 'hardhat-deploy/dist/types' + +import { predeploys } from '../src/constants' +import { assertContractVariable, deploy } from '../src/deploy-utils' + +const deployFn: DeployFunction = async (hre) => { + const KromaMintableERC721Factory = await hre.ethers.getContractAt( + 'KromaMintableERC721Factory', + predeploys.KromaMintableERC721Factory + ) + const remoteChainId = await KromaMintableERC721Factory.REMOTE_CHAIN_ID() + + await deploy(hre, 'KromaMintableERC721Factory', { + args: [predeploys.L2StandardBridge, remoteChainId], + postDeployAction: async (contract) => { + await assertContractVariable( + contract, + 'BRIDGE', + ethers.utils.getAddress(predeploys.L2StandardBridge) + ) + await assertContractVariable(contract, 'REMOTE_CHAIN_ID', remoteChainId) + }, + }) +} + +deployFn.tags = ['KromaMintableERC721Factory', 'l2'] + +export default deployFn diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts index a8fbf0d332..c0b29ef45f 100644 --- a/packages/contracts/hardhat.config.ts +++ b/packages/contracts/hardhat.config.ts @@ -37,6 +37,19 @@ const config: HardhatUserConfig = { accounts: [ process.env.PRIVATE_KEY_DEPLOYER_SEPOLIA || ethers.constants.HashZero, ], + companionNetworks: { + l2: 'kromaSepolia', + }, + }, + kromaSepolia: { + chainId: 2357, + url: process.env.L2_RPC_KROMA_SEPOLIA || '', + accounts: [ + process.env.PRIVATE_KEY_DEPLOYER_SEPOLIA || ethers.constants.HashZero, + ], + companionNetworks: { + l1: 'sepolia', + }, }, devnetL1: { live: false, diff --git a/packages/contracts/invariant-docs/Burn.md b/packages/contracts/invariant-docs/Burn.md index 9e0c75fae7..fa7bd665c6 100644 --- a/packages/contracts/invariant-docs/Burn.md +++ b/packages/contracts/invariant-docs/Burn.md @@ -1,12 +1,12 @@ # `Burn` Invariants ## `eth(uint256)` always burns the exact amount of eth passed. -**Test:** [`FuzzBurn.sol#L35`](../contracts/echidna/FuzzBurn.sol#L35) +**Test:** [`FuzzBurn.sol#L36`](../contracts/echidna/FuzzBurn.sol#L36) Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount of ETH passed to the function. ## `gas(uint256)` always burns at least the amount of gas passed. -**Test:** [`FuzzBurn.sol#L77`](../contracts/echidna/FuzzBurn.sol#L77) +**Test:** [`FuzzBurn.sol#L78`](../contracts/echidna/FuzzBurn.sol#L78) Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount of gas passed to the function. diff --git a/packages/contracts/invariant-docs/KromaPortal.md b/packages/contracts/invariant-docs/KromaPortal.md index 5fb5813516..fb6d71fde9 100644 --- a/packages/contracts/invariant-docs/KromaPortal.md +++ b/packages/contracts/invariant-docs/KromaPortal.md @@ -1,8 +1,24 @@ # `KromaPortal` Invariants +## `finalizeWithdrawalTransaction` should revert if the finalization period has not elapsed. +**Test:** [`KromaPortal.t.sol#L86`](../contracts/test/invariants/KromaPortal.t.sol#L86) + +A withdrawal that has been proven should not be able to be finalized until after the finalization period has elapsed. + + +## `finalizeWithdrawalTransaction` should revert if the withdrawal has already been finalized. +**Test:** [`KromaPortal.t.sol#L123`](../contracts/test/invariants/KromaPortal.t.sol#L123) + +Ensures that there is no chain of calls that can be made that allows a withdrawal to be finalized twice. + + +## A withdrawal should **always** be able to be finalized `FINALIZATION_PERIOD_SECONDS` after it was successfully proven. +**Test:** [`KromaPortal.t.sol#L158`](../contracts/test/invariants/KromaPortal.t.sol#L158) + +This invariant asserts that there is no chain of calls that can be made that will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS` after it was successfully proven. ## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`. -**Test:** [`FuzzKromaPortal.sol#L38`](../contracts/echidna/FuzzKromaPortal.sol#L38) +**Test:** [`FuzzKromaPortal.sol#L58`](../contracts/echidna/FuzzKromaPortal.sol#L58) All deposits, barring creation transactions and transactions sent to `address(0)`, should always succeed. diff --git a/packages/contracts/invariant-docs/L2OutputOracle.md b/packages/contracts/invariant-docs/L2OutputOracle.md index 90ec816840..626d2e74cb 100644 --- a/packages/contracts/invariant-docs/L2OutputOracle.md +++ b/packages/contracts/invariant-docs/L2OutputOracle.md @@ -1,6 +1,6 @@ # `L2OutputOracle` Invariants -## The block number of the output root proposals should monotonically increase. -**Test:** [`L2OutputOracle.t.sol#L36`](../contracts/test/invariants/L2OutputOracle.t.sol#L36) +## The block number of the checkpoint output should monotonically increase. +**Test:** [`L2OutputOracle.t.sol#L64`](../contracts/test/invariants/L2OutputOracle.t.sol#L64) When a new output is submitted, it should never be allowed to correspond to a block number that is less than the current output. diff --git a/packages/contracts/invariant-docs/README.md b/packages/contracts/invariant-docs/README.md index 184d8387fd..37f751d08d 100644 --- a/packages/contracts/invariant-docs/README.md +++ b/packages/contracts/invariant-docs/README.md @@ -14,6 +14,7 @@ This directory contains documentation for all defined invariant tests within `co - [KromaPortal](./KromaPortal.md) - [L2OutputOracle](./L2OutputOracle.md) - [ResourceMetering](./ResourceMetering.md) +- [SafeCall](./SafeCall.md) - [SystemConfig](./SystemConfig.md) diff --git a/packages/contracts/invariant-docs/ResourceMetering.md b/packages/contracts/invariant-docs/ResourceMetering.md index b43558cfb0..3284ccfc97 100644 --- a/packages/contracts/invariant-docs/ResourceMetering.md +++ b/packages/contracts/invariant-docs/ResourceMetering.md @@ -1,42 +1,42 @@ # `ResourceMetering` Invariants ## The base fee should increase if the last block used more than the target amount of gas -**Test:** [`FuzzResourceMetering.sol#L139`](../contracts/echidna/FuzzResourceMetering.sol#L139) +**Test:** [`FuzzResourceMetering.sol#L159`](../contracts/echidna/FuzzResourceMetering.sol#L159) If the last block used more than the target amount of gas (and there were no empty blocks in between), ensure this block's baseFee increased, but not by more than the max amount per block. ## The base fee should decrease if the last block used less than the target amount of gas -**Test:** [`FuzzResourceMetering.sol#L150`](../contracts/echidna/FuzzResourceMetering.sol#L150) +**Test:** [`FuzzResourceMetering.sol#L170`](../contracts/echidna/FuzzResourceMetering.sol#L170) If the previous block used less than the target amount of gas, the base fee should decrease, but not more than the max amount. ## A block's base fee should never be below `MINIMUM_BASE_FEE` -**Test:** [`FuzzResourceMetering.sol#L160`](../contracts/echidna/FuzzResourceMetering.sol#L160) +**Test:** [`FuzzResourceMetering.sol#L180`](../contracts/echidna/FuzzResourceMetering.sol#L180) This test asserts that a block's base fee can never drop below the `MINIMUM_BASE_FEE` threshold. ## A block can never consume more than `MAX_RESOURCE_LIMIT` gas. -**Test:** [`FuzzResourceMetering.sol#L170`](../contracts/echidna/FuzzResourceMetering.sol#L170) +**Test:** [`FuzzResourceMetering.sol#L190`](../contracts/echidna/FuzzResourceMetering.sol#L190) This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT` gas threshold. ## The base fee can never be raised more than the max base fee change. -**Test:** [`FuzzResourceMetering.sol#L181`](../contracts/echidna/FuzzResourceMetering.sol#L181) +**Test:** [`FuzzResourceMetering.sol#L201`](../contracts/echidna/FuzzResourceMetering.sol#L201) After a block consumes more gas than the target gas, the base fee cannot be raised more than the maximum amount allowed. The max base fee change (per-block) is derived as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR` ## The base fee can never be lowered more than the max base fee change. -**Test:** [`FuzzResourceMetering.sol#L192`](../contracts/echidna/FuzzResourceMetering.sol#L192) +**Test:** [`FuzzResourceMetering.sol#L212`](../contracts/echidna/FuzzResourceMetering.sol#L212) After a block consumes less than the target gas, the base fee cannot be lowered more than the maximum amount allowed. The max base fee change (per-block) is derived as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR` ## The `maxBaseFeeChange` calculation over multiple blocks can never underflow. -**Test:** [`FuzzResourceMetering.sol#L203`](../contracts/echidna/FuzzResourceMetering.sol#L203) +**Test:** [`FuzzResourceMetering.sol#L223`](../contracts/echidna/FuzzResourceMetering.sol#L223) When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation should never be allowed to underflow. diff --git a/packages/contracts/invariant-docs/SafeCall.md b/packages/contracts/invariant-docs/SafeCall.md new file mode 100644 index 0000000000..afb8ecdf43 --- /dev/null +++ b/packages/contracts/invariant-docs/SafeCall.md @@ -0,0 +1,12 @@ +# `SafeCall` Invariants + +## If `callWithMinGas` performs a call, then it must always provide at least the specified minimum gas limit to the subcontext. +**Test:** [`SafeCall.t.sol#L31`](../contracts/test/invariants/SafeCall.t.sol#L31) + +If the check for remaining gas in `SafeCall.callWithMinGas` passes, the subcontext of the call below it must be provided at least `minGas` gas. + + +## `callWithMinGas` reverts if there is not enough gas to pass to the subcontext. +**Test:** [`SafeCall.t.sol#L62`](../contracts/test/invariants/SafeCall.t.sol#L62) + +If there is not enough gas in the callframe to ensure that `callWithMinGas` can provide the specified minimum gas limit to the subcontext of the call, then `callWithMinGas` must revert. diff --git a/packages/contracts/invariant-docs/SystemConfig.md b/packages/contracts/invariant-docs/SystemConfig.md index c08f8f7780..358713f68c 100644 --- a/packages/contracts/invariant-docs/SystemConfig.md +++ b/packages/contracts/invariant-docs/SystemConfig.md @@ -1,5 +1,5 @@ # `SystemConfig` Invariants ## The gas limit of the `SystemConfig` contract can never be lower than the hard-coded lower bound. -**Test:** [`SystemConfig.t.sol#L40`](../contracts/test/invariants/SystemConfig.t.sol#L40) +**Test:** [`SystemConfig.t.sol#L45`](../contracts/test/invariants/SystemConfig.t.sol#L45) diff --git a/packages/contracts/package.json b/packages/contracts/package.json index f2f7c077ee..fee77e5b3e 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -32,6 +32,7 @@ "storage-snapshot": "bash ./scripts/storage-snapshot.sh", "validate-spacers": "hardhat compile && hardhat validate-spacers", "slither": "bash ./scripts/slither.sh", + "slither:triage": "TRIAGE_MODE=1 bash ./scripts/slither.sh", "clean": "rm -rf ./dist ./artifacts ./forge-artifacts ./cache ./tsconfig.tsbuildinfo ./tsconfig.build.tsbuildinfo ./src/contract-artifacts.ts ./test-case-generator/fuzz", "lint:ts:check": "eslint . --max-warnings=0", "lint:forge-tests:check": "ts-node scripts/forge-test-names.ts", @@ -78,7 +79,7 @@ "ds-test": "https://github.com/dapphub/ds-test.git#9310e879db8ba3ea6d5c6489a579118fd264a3f5", "ethereum-waffle": "^3.0.0", "ethereumjs-wallet": "^1.0.2", - "forge-std": "https://github.com/foundry-rs/forge-std.git#fd86115ed6aba8e234ee0fb86c12fe35eff0b2a0", + "forge-std": "https://github.com/foundry-rs/forge-std.git#46264e9788017fc74f9f58b7efa0bc6e1df6d410", "glob": "^7.1.6", "hardhat-deploy": "^0.11.4", "solhint": "^3.3.7", diff --git a/packages/contracts/scripts/FeeVaultWithdrawal.s.sol b/packages/contracts/scripts/FeeVaultWithdrawal.s.sol new file mode 100644 index 0000000000..bbfa02e217 --- /dev/null +++ b/packages/contracts/scripts/FeeVaultWithdrawal.s.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +/* solhint-disable no-console */ +import { console } from "forge-std/console.sol"; +import { Script } from "forge-std/Script.sol"; +import { IMulticall3 } from "forge-std/interfaces/IMulticall3.sol"; + +import { Predeploys } from "../contracts/libraries/Predeploys.sol"; +import { FeeVault } from "../contracts/universal/FeeVault.sol"; + +/** + * @title FeeVaultWithdrawal + * @notice A script to make it very simple to withdraw from the fee vaults. + * The usage is as follows: + * $ forge script scripts/FeeVaultWithdrawal.s.sol \ + * --rpc-url $ETH_RPC_URL --broadcast \ + * --private-key $PRIVATE_KEY + */ +contract FeeVaultWithdrawal is Script { + IMulticall3 private constant MULTICALL = IMulticall3(MULTICALL3_ADDRESS); + IMulticall3.Call3[] internal calls; + + /** + * @notice The entrypoint function. Determines which FeeVaults can be withdrawn from and then + * will send the transaction via Multicall3 to withdraw all FeeVaults. + */ + function run() external { + require(address(MULTICALL).code.length > 0); + + address[] memory vaults = new address[](3); + vaults[0] = Predeploys.VALIDATOR_REWARD_VAULT; + vaults[1] = Predeploys.PROTOCOL_VAULT; + vaults[2] = Predeploys.PROPOSER_REWARD_VAULT; + + for (uint256 i; i < vaults.length; i++) { + address vault = vaults[i]; + bool shouldCall = canWithdrawal(vault); + if (shouldCall) { + calls.push( + IMulticall3.Call3({ + target: vault, + allowFailure: false, + callData: abi.encodeWithSelector(FeeVault.withdraw.selector) + }) + ); + + address recipient = FeeVault(payable(vault)).RECIPIENT(); + uint256 balance = vault.balance; + log(balance, recipient, vault); + } else { + string memory logline = string.concat( + vm.toString(vault), + " does not have a large enough balance to withdraw." + ); + console.log(logline); + } + } + + if (calls.length > 0) { + vm.broadcast(); + MULTICALL.aggregate3(calls); + console.log("Success."); + } + } + + /** + * @notice Checks whether or not a FeeVault can be withdrawn. The balance of the account must + * be larger than the `MIN_WITHDRAWAL_AMOUNT`. + */ + function canWithdrawal(address _vault) internal view returns (bool) { + uint256 minWithdrawalAmount = FeeVault(payable(_vault)).MIN_WITHDRAWAL_AMOUNT(); + uint256 balance = _vault.balance; + return balance >= minWithdrawalAmount; + } + + /** + * @notice Logs the information relevant to the user. + */ + function log(uint256 _balance, address _recipient, address _vault) internal view { + string memory logline = string.concat( + "Withdrawing ", + vm.toString(_balance), + " to ", + vm.toString(_recipient), + " from ", + vm.toString(_vault) + ); + console.log(logline); + } +} diff --git a/packages/contracts/scripts/slither.sh b/packages/contracts/scripts/slither.sh index 74ed1dfd76..f557275241 100755 --- a/packages/contracts/scripts/slither.sh +++ b/packages/contracts/scripts/slither.sh @@ -2,11 +2,26 @@ rm -rf artifacts forge-artifacts -# Handle slither bug unable to work with the foundry tests -TEMP=$(mktemp -d) -mv contracts/test $TEMP/test +# See slither.config.json for slither settings +if [[ -z "$TRIAGE_MODE" ]]; then + echo "Running slither" + slither . +else + echo "Running slither in triage mode" + # Slither's triage mode will run an 'interview' in the terminal, allowing you to review each of + # its findings, and specify which should be ignored in future runs of slither. This will update + # (or create) the slither.db.json file. This DB is a cleaner alternative to adding slither-disable + # comments throughout the codebase. + # Triage mode should only be run manually, and can be used to update the db when new findings are + # causing a CI failure. + slither . --triage-mode -slither . --foundry-out-directory artifacts - -mv $TEMP/test contracts/test -pd + # For whatever reason the slither db contains a filename_absolute property which includes the full + # local path to source code on the machine where it was generated. This property does not + # seem to be required for slither to run, so we remove it. + DB=slither.db.json + TEMP_DB=temp-slither.db.json + mv $DB $TEMP_DB + jq 'walk(if type == "object" then del(.filename_absolute) else . end)' $TEMP_DB >$DB + rm -f $TEMP_DB +fi diff --git a/packages/contracts/slither.config.json b/packages/contracts/slither.config.json index f48a7929c0..21d9650577 100644 --- a/packages/contracts/slither.config.json +++ b/packages/contracts/slither.config.json @@ -1,12 +1,13 @@ { - "detectors_to_exclude": "assembly-usage,block-timestamp,naming-convention,solc-version", - "exclude_informational": false, - "exclude_low": false, - "exclude_medium": false, + "detectors_to_exclude": "assembly-usage,block-timestamp,naming-convention,solc-version,low-level-calls,boolean-equality", + "exclude_informational": true, + "exclude_low": true, + "exclude_medium": true, "exclude_high": false, "solc_disable_warnings": false, "hardhat_ignore_compile": false, "disable_color": false, - "exclude_dependencies": false, - "filter_paths": "contracts/test|lib" + "exclude_dependencies": true, + "filter_paths": "contracts/test,contracts/vendor,contracts/echidna,node_modules", + "foundry_out_directory": "artifacts" } diff --git a/packages/contracts/src/deploy-config.ts b/packages/contracts/src/deploy-config.ts index 94681dbe3e..c6d2226a79 100644 --- a/packages/contracts/src/deploy-config.ts +++ b/packages/contracts/src/deploy-config.ts @@ -91,7 +91,7 @@ interface RequiredDeployConfig { /** * Maximum the number of transaction are allowed in a block. */ - maxTxs: string + maxTxs: number /** * Output Oracle submission interval in L2 blocks. @@ -126,6 +126,26 @@ interface RequiredDeployConfig { * A value represented by a comma-separated string like `9,6,5,6` */ colosseumSegmentsLengths: string + + /** + * Owner of the ProxyAdmin contract. + */ + proxyAdminOwner: string + + /** + * L1 recipient of fees accumulated in the ProtocolVault. + */ + protocolVaultRecipient: string + + /** + * L1 recipient of fees accumulated in the ProposerRewardVault. + */ + ProposerRewardVaultRecipient: string + + /** + * L1 recipient of fees accumulated in the ValidatorRewardVault. + */ + validatorRewardVaultRecipient: string } /** @@ -158,6 +178,9 @@ interface OptionalL2DeployConfig { l2GenesisBlockParentHash: string l2GenesisBlockBaseFeePerGas: string l2GenesisBlueTimeOffset: string + l2GenesisBlockCoinbase: string + eip1559Denominator: number + eip1559Elasticity: number gasPriceOracleOverhead: number gasPriceOracleScalar: number colosseumChallengeTimeout: number @@ -244,6 +267,18 @@ export const deployConfigSpec: { type: 'number', default: 2, }, + proxyAdminOwner: { + type: 'address', + }, + protocolVaultRecipient: { + type: 'address', + }, + ProposerRewardVaultRecipient: { + type: 'address', + }, + validatorRewardVaultRecipient: { + type: 'address', + }, cliqueSignerAddress: { type: 'address', default: ethers.constants.AddressZero, diff --git a/packages/contracts/src/deploy-utils.ts b/packages/contracts/src/deploy-utils.ts index f935a9f0e3..f3386407c3 100644 --- a/packages/contracts/src/deploy-utils.ts +++ b/packages/contracts/src/deploy-utils.ts @@ -6,9 +6,9 @@ import { sleep } from '@kroma-network/core-utils' import '@kroma-network/hardhat-deploy-config' import '@nomiclabs/hardhat-ethers' import { Contract, ethers } from 'ethers' +import { ArtifactData } from 'hardhat-deploy/dist/types' import { HardhatRuntimeEnvironment } from 'hardhat/types' import 'hardhat-deploy' -import { ArtifactData } from 'hardhat-deploy/dist/types' const IMPLEMENTATION_SLOT = '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' @@ -57,12 +57,20 @@ export const deploy = async ( return null } + // Wrap in a try/catch in case there is not a deployConfig for the current network. + let numDeployConfirmations: number + try { + numDeployConfirmations = hre.deployConfig.numDeployConfirmations + } catch (e) { + numDeployConfirmations = 1 + } + const result = await hre.deployments.deploy(name, { contract: opts.contract, from: deployer, args: opts.args, log: true, - waitConfirmations: hre.deployConfig.numDeployConfirmations, + waitConfirmations: numDeployConfirmations, }) console.log(`deployed ${name} at ${result.address}`) @@ -77,7 +85,7 @@ export const deploy = async ( // Create the contract object to return. const created = asAdvancedContract({ - confirmations: hre.deployConfig.numDeployConfirmations, + confirmations: numDeployConfirmations, contract: new Contract( result.address, result.abi, @@ -175,7 +183,6 @@ export const asAdvancedContract = (opts: { // Now reset Object.defineProperty Object.defineProperty = def - // Override each function call to also `.wait()` so as to simplify the deploy scripts' syntax. for (const fnName of Object.keys(contract.functions)) { const fn = contract[fnName].bind(contract) ;(contract as any)[fnName] = async (...args: any) => { @@ -255,8 +262,15 @@ export const getContractFromArtifact = async ( } } + let numDeployConfirmations: number + try { + numDeployConfirmations = hre.deployConfig.numDeployConfirmations + } catch (e) { + numDeployConfirmations = 1 + } + return asAdvancedContract({ - confirmations: hre.deployConfig.numDeployConfirmations, + confirmations: numDeployConfirmations, contract: new hre.ethers.Contract( artifact.address, iface, diff --git a/packages/contracts/tasks/check-l2.ts b/packages/contracts/tasks/check-l2.ts index a171c10851..26a3b37cdd 100644 --- a/packages/contracts/tasks/check-l2.ts +++ b/packages/contracts/tasks/check-l2.ts @@ -1,7 +1,7 @@ import assert from 'assert' import '@nomiclabs/hardhat-ethers' -import { Contract, providers, Signer, Wallet } from 'ethers' +import { Contract, Signer, Wallet, providers } from 'ethers' import { task, types } from 'hardhat/config' import { HardhatRuntimeEnvironment } from 'hardhat/types' import 'hardhat-deploy' @@ -349,10 +349,7 @@ const check = { signer ) - await assertSemver( - KromaMintableERC721Factory, - 'KromaMintableERC721Factory' - ) + await assertSemver(KromaMintableERC721Factory, 'KromaMintableERC721Factory') const BRIDGE = await KromaMintableERC721Factory.BRIDGE() assert(BRIDGE !== hre.ethers.constants.AddressZero) diff --git a/packages/contracts/tasks/deposits.ts b/packages/contracts/tasks/deposits.ts index bf96634100..40a67e9172 100644 --- a/packages/contracts/tasks/deposits.ts +++ b/packages/contracts/tasks/deposits.ts @@ -1,7 +1,7 @@ import { DepositTx } from '@kroma-network/core-utils' import '@nomiclabs/hardhat-ethers' import dotenv from 'dotenv' -import { Event, providers, utils, Wallet } from 'ethers' +import { Event, Wallet, providers, utils } from 'ethers' import { task, types } from 'hardhat/config' import 'hardhat-deploy' diff --git a/packages/contracts/tasks/generate-deploy-config.ts b/packages/contracts/tasks/generate-deploy-config.ts new file mode 100644 index 0000000000..f32108e255 --- /dev/null +++ b/packages/contracts/tasks/generate-deploy-config.ts @@ -0,0 +1,26 @@ +import fs from 'fs' +import path from 'path' + +import { task } from 'hardhat/config' +import { HardhatRuntimeEnvironment } from 'hardhat/types' + +task( + 'generate-deploy-config', + 'generates a json config file for the current network' + // eslint-disable-next-line no-empty-pattern +).setAction(async ({}, hre: HardhatRuntimeEnvironment) => { + try { + const base = path.join(hre.config.paths.deployConfig, hre.network.name) + if (fs.existsSync(`${base}.ts`)) { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const config = require(`${base}.ts`).default + fs.writeFileSync(`${base}.json`, JSON.stringify(config, null, 2), 'utf8') + } else { + throw new Error('not found') + } + } catch (err) { + throw new Error( + `error while loading deploy config for network: ${hre.network.name}, ${err}` + ) + } +}) diff --git a/packages/contracts/tasks/index.ts b/packages/contracts/tasks/index.ts index 9ddc7aa104..76c4e34666 100644 --- a/packages/contracts/tasks/index.ts +++ b/packages/contracts/tasks/index.ts @@ -7,3 +7,4 @@ import './validate-spacers' import './solidity' import './accounts' import './check-l2' +import './generate-deploy-config' diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json index b3d377ea0d..8cb6856ee5 100644 --- a/packages/contracts/tsconfig.json +++ b/packages/contracts/tsconfig.json @@ -5,6 +5,7 @@ }, "include": [ "src/**/*", + "deploy/**/*", "deploy-config/**/*", "deploy-config/**/*.json", "tasks/**/*", diff --git a/packages/core-utils/.eslintrc.js b/packages/core-utils/.eslintrc.js index bfd2057be8..fe91b823c7 100644 --- a/packages/core-utils/.eslintrc.js +++ b/packages/core-utils/.eslintrc.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-undef module.exports = { extends: '../../.eslintrc.js', } diff --git a/packages/core-utils/src/kroma/hashing.ts b/packages/core-utils/src/kroma/hashing.ts index 12fd431007..6260806854 100644 --- a/packages/core-utils/src/kroma/hashing.ts +++ b/packages/core-utils/src/kroma/hashing.ts @@ -21,7 +21,8 @@ export interface OutputRootProof { version: string stateRoot: string messagePasserStorageRoot: string - latestBlockhash: string + blockHash: string + nextBlockHash: string } /** @@ -133,6 +134,21 @@ export const hashWithdrawal = ( * @param proof OutputRootProof */ export const hashOutputRootProof = (proof: OutputRootProof): string => { + const version = parseInt(proof.version, 10) + if (version === 0) { + return hashOutputRootProofV0(proof) + } else if (version === 1) { + return hashOutputRootProofV1(proof) + } + throw new Error(`unknown version ${version.toString()}`) +} + +/** + * Hashes a V0 output root proof + * + * @param proof OutputRootProof + */ +export const hashOutputRootProofV0 = (proof: OutputRootProof): string => { return keccak256( defaultAbiCoder.encode( ['bytes32', 'bytes32', 'bytes32', 'bytes32'], @@ -140,7 +156,27 @@ export const hashOutputRootProof = (proof: OutputRootProof): string => { proof.version, proof.stateRoot, proof.messagePasserStorageRoot, - proof.latestBlockhash, + proof.blockHash, + ] + ) + ) +} + +/** + * Hashes a V1 output root proof + * + * @param proof OutputRootProof + */ +export const hashOutputRootProofV1 = (proof: OutputRootProof): string => { + return keccak256( + defaultAbiCoder.encode( + ['bytes32', 'bytes32', 'bytes32', 'bytes32', 'bytes32'], + [ + proof.version, + proof.stateRoot, + proof.messagePasserStorageRoot, + proof.blockHash, + proof.nextBlockHash, ] ) ) diff --git a/packages/hardhat-deploy-config/.eslintrc.js b/packages/hardhat-deploy-config/.eslintrc.js index bfd2057be8..fe91b823c7 100644 --- a/packages/hardhat-deploy-config/.eslintrc.js +++ b/packages/hardhat-deploy-config/.eslintrc.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-undef module.exports = { extends: '../../.eslintrc.js', } diff --git a/packages/hardhat-deploy-config/src/plugin.ts b/packages/hardhat-deploy-config/src/plugin.ts index 19e0da42e5..40d7af1795 100644 --- a/packages/hardhat-deploy-config/src/plugin.ts +++ b/packages/hardhat-deploy-config/src/plugin.ts @@ -1,14 +1,14 @@ -import * as path from 'path' import * as fs from 'fs' +import * as path from 'path' import { ethers } from 'ethers' import { extendConfig, extendEnvironment } from 'hardhat/config' +import { lazyFunction, lazyObject } from 'hardhat/plugins' import { HardhatConfig, HardhatRuntimeEnvironment, HardhatUserConfig, } from 'hardhat/types' -import { lazyObject } from 'hardhat/plugins' // From: https://github.com/wighawag/hardhat-deploy/blob/master/src/index.ts#L63-L76 const normalizePath = ( @@ -26,10 +26,13 @@ const normalizePath = ( return userPath } -export const loadDeployConfig = (hre: HardhatRuntimeEnvironment): any => { +const getDeployConfig = ( + dir: string, + network: string +): { [key: string]: any } => { let config: any try { - const base = `${hre.config.paths.deployConfig}/${hre.network.name}` + const base = `${dir}/${network}` if (fs.existsSync(`${base}.ts`)) { // eslint-disable-next-line @typescript-eslint/no-var-requires config = require(`${base}.ts`).default @@ -41,18 +44,24 @@ export const loadDeployConfig = (hre: HardhatRuntimeEnvironment): any => { } } catch (err) { throw new Error( - `error while loading deploy config for network: ${hre.network.name}, ${err}` + `error while loading deploy config for network: ${network}, ${err}` ) } + return config +} - return new Proxy(parseDeployConfig(hre, config), { +export const loadDeployConfig = (hre: HardhatRuntimeEnvironment): any => { + const paths = hre.config.paths.deployConfig + const conf = getDeployConfig(paths, hre.network.name) + const spec = parseDeployConfig(hre, conf) + + return new Proxy(spec, { get: (target, prop) => { - if (target.hasOwnProperty(prop)) { + if (Object.prototype.hasOwnProperty.call(target, prop)) { return target[prop] } - // Explicitly throw if the property is not found since I can't yet figure out a good way to - // handle the necessary typings. + // Explicitly throw if the property is not found throw new Error( `property does not exist in deploy config: ${String(prop)}` ) @@ -114,4 +123,8 @@ extendConfig( extendEnvironment((hre) => { hre.deployConfig = lazyObject(() => loadDeployConfig(hre)) + hre.getDeployConfig = lazyFunction(() => { + const paths = hre.config.paths.deployConfig + return (network: string) => getDeployConfig(paths, network) + }) }) diff --git a/packages/hardhat-deploy-config/src/type-extensions.ts b/packages/hardhat-deploy-config/src/type-extensions.ts index ffbf40185a..85f1600645 100644 --- a/packages/hardhat-deploy-config/src/type-extensions.ts +++ b/packages/hardhat-deploy-config/src/type-extensions.ts @@ -24,8 +24,8 @@ declare module 'hardhat/types/config' { declare module 'hardhat/types/runtime' { interface HardhatRuntimeEnvironment { deployConfig: { - // TODO: Is there any good way to type this? [key: string]: any } + getDeployConfig(network: string): { [key: string]: any } } } diff --git a/packages/sdk/.eslintrc.js b/packages/sdk/.eslintrc.js index 3703fb6246..5b8e4ffaf1 100644 --- a/packages/sdk/.eslintrc.js +++ b/packages/sdk/.eslintrc.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-undef module.exports = { extends: '../../.eslintrc.js', ignorePatterns: ['hardhat.config.ts'], diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 98921746f0..397463d428 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -17,6 +17,7 @@ You can use this class to, for example, initiate a withdrawal of ERC20 tokens fr track when the withdrawal is ready to be finalized on Ethereum, and execute the finalization transaction after the challenge period has elapsed. The `CrossChainMessenger` can handle deposits and withdrawals of ETH and any ERC20-compatible token. +Detailed API descriptions can be found at [sdk.optimism.io](https://sdk.optimism.io/classes/crosschainmessenger). The `CrossChainMessenger` automatically connects to all relevant contracts so complex configuration is not necessary. [`CrossChainMessenger`]: ./src/cross-chain-messenger.ts diff --git a/packages/sdk/hardhat.config.ts b/packages/sdk/hardhat.config.ts index f647d6438b..1f9096f66d 100644 --- a/packages/sdk/hardhat.config.ts +++ b/packages/sdk/hardhat.config.ts @@ -22,7 +22,7 @@ const config: HardhatUserConfig = { chainId: 11155111, accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [], }, - sepoliaKroma: { + kromaSepolia: { url: 'https://api.sepolia.kroma.network', chainId: 2357, accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [], diff --git a/packages/sdk/src/cross-chain-messenger.ts b/packages/sdk/src/cross-chain-messenger.ts index 5274b7790a..477080d48a 100644 --- a/packages/sdk/src/cross-chain-messenger.ts +++ b/packages/sdk/src/cross-chain-messenger.ts @@ -946,12 +946,20 @@ export class CrossChainMessenger { false, ]) + const nextBlock = await ( + this.l2Provider as ethers.providers.JsonRpcProvider + ).send('eth_getBlockByNumber', [ + toRpcHexString(output.l2BlockNumber + 1), + false, + ]) + return { outputRootProof: { version: ethers.constants.HashZero, stateRoot: block.stateRoot, messagePasserStorageRoot: stateTrieProof.storageRoot, - latestBlockhash: block.hash, + blockHash: block.hash, + nextBlockHash: nextBlock.hash, }, withdrawalProof: stateTrieProof.storageProof, l2OutputIndex: output.l2OutputIndex, @@ -1326,7 +1334,8 @@ export class CrossChainMessenger { proof.outputRootProof.version, proof.outputRootProof.stateRoot, proof.outputRootProof.messagePasserStorageRoot, - proof.outputRootProof.latestBlockhash, + proof.outputRootProof.blockHash, + proof.outputRootProof.nextBlockHash, ], proof.withdrawalProof, opts?.overrides || {} diff --git a/specs/bridges.md b/specs/bridges.md index f4aef7770e..aab840bb96 100644 --- a/specs/bridges.md +++ b/specs/bridges.md @@ -110,7 +110,7 @@ interface StandardBridge { ## Token Depositing The `bridgeERC20` function is used to send a token from one domain to another -domain. An `KromaMintableERC20` token contract must exist on the remote +domain. A `KromaMintableERC20` token contract must exist on the remote domain to be able to deposit tokens to that domain. One of these tokens can be deployed using the `KromaMintableERC20Factory` contract. diff --git a/specs/deposits.md b/specs/deposits.md index c8339e6817..374655f4b6 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -119,8 +119,9 @@ Although we define only one new transaction type, we can distinguish between two transactions, based on their positioning in the L2 block: 1. The first transaction MUST be a [L1 attributes deposited transaction][l1-attr-deposit], followed by -2. an array of zero-or-more [user-deposited transactions][user-deposited] submitted to the deposit - feed contract on L1. User-deposited transactions are only present in the first block of a L2 epoch. +2. an array of zero-or-more [user-deposited transactions][user-deposited] + submitted to the deposit feed contract on L1 (called `KromaPortal`). + User-deposited transactions are only present in the first block of a L2 epoch. We only define a single new transaction type in order to minimize modifications to L1 client software, and complexity in general. @@ -273,8 +274,8 @@ The predeploy stores the following values: and reset to 0 at the start of a new epoch. - System configurables tied to the L1 block, see [System configuration specification](./system-config.md): - `batcherHash` (`bytes32`): A versioned commitment to the batch-submitter(s) currently operating. - - `l1FeeOverhead` (`uint256`): The L1 fee overhead to apply to L1 cost computation of transactions in this L2 block. - - `l1FeeScalar` (`uint256`): The L1 fee scalar to apply to L1 cost computation of transactions in this L2 block. + - `overhead` (`uint256`): The L1 fee overhead to apply to L1 cost computation of transactions in this L2 block. + - `scalar` (`uint256`): The L1 fee scalar to apply to L1 cost computation of transactions in this L2 block. The contract implements an authorization scheme, such that it only accepts state-changing calls from the [depositor account][depositor-account]. @@ -305,8 +306,8 @@ generated by the [L2 Chain Derivation][g-derivation] process. The content of eac transaction are determined by the corresponding `TransactionDeposited` event emitted by the [deposit contract][deposit-contract] on L1. -1. `from` is unchanged from the emitted value (though it may have been transformed to an alias in - the deposit feed contract). +1. `from` is unchanged from the emitted value (though it may + have been transformed to an alias in `KromaPortal`, the deposit feed contract). 2. `to` is any 20-byte address (including the zero address) - In case of a contract creation (cf. `isCreation`), this address is set to `null`. 3. `mint` is set to the emitted value. diff --git a/specs/derivation.md b/specs/derivation.md index a4548a6173..7841d58142 100644 --- a/specs/derivation.md +++ b/specs/derivation.md @@ -39,7 +39,6 @@ [g-unsafe-l2-block]: glossary.md#unsafe-l2-block [g-unsafe-sync]: glossary.md#unsafe-sync [g-user-deposited]: glossary.md#user-deposited-transaction -[g-validator]: glossary.md#validator [g-zk-fault-proof]: glossary.md#zk-fault-proof @@ -280,9 +279,7 @@ As for the comment on "security types", it explains the classification of blocks - [Unsafe L2 blocks][g-unsafe-l2-block]: - [Safe L2 blocks][g-safe-l2-block]: -- Finalized L2 blocks: currently the same as the safe L2 block, but could be changed in the future to refer to block - that have been derived from [finalized][g-finalized-l2-head] L1 data, or alternatively, from L1 blacks that are older - than the [challenge period]. +- Finalized L2 blocks: refer to block that have been derived from [finalized][g-finalized-l2-head] L1 data. These security levels map to the `headBlockHash`, `safeBlockHash` and `finalizedBlockHash` values transmitted when interacting with the [execution-engine API][exec-engine]. @@ -296,7 +293,7 @@ Batcher transactions are encoded as `version_byte ++ rollup_payload` (where `++` | 0 | `frame ...` (one or more frames, concatenated) | Unknown versions make the batcher transaction invalid (it must be ignored by the rollup node). -All frames in a batcher transaction must be parseable. If any one frame fails to parse, the all frames in the +All frames in a batcher transaction must be parsable. If any one frame fails to parse, the all frames in the transaction are rejected. Batch transactions are authenticated by verifying that the `to` address of the transaction matches the batch inbox diff --git a/specs/glossary.md b/specs/glossary.md index 21bdf64c24..e35245743c 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -802,7 +802,7 @@ See the [Engine Queue section][engine-queue] of the [L2 chain derivation spec][d The finalized L2 head is the highest [L2] block that can be derived from _[finalized][finality]_ L1 blocks — i.e. L1 blocks older than two L1 epochs (64 L1 [time slots][time-slot]). -[finality]: _finalized_ L1 data. +[finality]: https://hackmd.io/@prysmaticlabs/finality ------------------------------------------------------------------------------------------------------------------------ diff --git a/specs/guaranteed-gas-market.md b/specs/guaranteed-gas-market.md index 6c294d7b9a..9be913a42e 100644 --- a/specs/guaranteed-gas-market.md +++ b/specs/guaranteed-gas-market.md @@ -5,8 +5,10 @@ **Table of Contents** - [Gas Stipend](#gas-stipend) +- [Default Values](#default-values) - [Limiting Guaranteed Gas](#limiting-guaranteed-gas) - [Rationale for burning L1 Gas](#rationale-for-burning-l1-gas) +- [On Preventing Griefing Attacks](#on-preventing-griefing-attacks) @@ -36,6 +38,17 @@ the L2 gas, where `gas spent` is the amount of L1 gas spent processing the depos of this credit is greater than the ETH value of the requested guaranteed gas (`requested guaranteed gas * L2 gas price`), no L1 gas is burnt. +## Default Values + +| Variable | Value | +| ------------------------------- | ----------------- | +| Max Resource Limit | 20,000,000 | +| Elasticity Multiplier | 10 | +| Base Fee Max Change Denominator | 8 | +| Minimum Base Fee | 1 gwei | +| Maximum Base Fee | type(uint128).max | +| System Tx Max Gas | 1,000,000 | + ## Limiting Guaranteed Gas The total amount of guaranteed gas that can be bought in a single L1 block must be limited to @@ -123,3 +136,20 @@ The payable version (Option 2) will likely have discount applied to it (or conve premium applied to it). For the initial release, only #1 is supported. + +## On Preventing Griefing Attacks + +The cost of purchasing all of the deposit gas in every block must be expensive +enough to prevent attackers from griefing all deposits to the network. +An attacker would observe a deposit in the mempool and frontrun it with a deposit +that purchases enough gas such that the other deposit reverts. +The smaller the max resource limit is, the easier this attack is to pull off. +This attack is mitigated by having a large resource limit as well as a large +elasticity multiplier. This means that the target resource usage is kept small, +giving a lot of room for the deposit base fee to rise when the max resource limit +is being purchased. + +This attack should be too expensive to pull off in practice, but if an extremely +wealthy adversary does decide to grief network deposits for an extended period +of time, efforts will be placed to ensure that deposits are able to be processed +on the network. diff --git a/specs/introduction.md b/specs/introduction.md index 44ff4614e9..03c0403183 100644 --- a/specs/introduction.md +++ b/specs/introduction.md @@ -107,7 +107,7 @@ liveness, availability, and validity. - All information required to derive the chain is embedded into layer 1 blocks. That way as long as the layer 1 chain is available, so is the rollup. 3. **Validity** - All transactions must be correctly executed and all withdrawals correctly processed. - - The rollup state and withdrawals are managed on an L1 contract called the `L2 Output Oracle`. This oracle is + - The rollup state and withdrawals are managed on an L1 contract called the `L2OutputOracle`. This oracle is guaranteed to _only_ finalize correct (ie. valid) rollup block hashes given a **single honest validator** assumption. If there is ever an invalid block hash asserted on layer 1, an honest validator will prove it is invalid and win a bond. diff --git a/specs/meta/devnet.md b/specs/meta/devnet.md index 8a0356cbb2..595b8a675d 100644 --- a/specs/meta/devnet.md +++ b/specs/meta/devnet.md @@ -24,7 +24,7 @@ Then, run the following: > make devnet-clean # removes the devnet by deleting images and persistent volumes ``` -L1 is accessible at `http://localhost:8545`, and L2 is accessible at `http://localhost:8546`. +L1 is accessible at `http://localhost:8545`, and L2 is accessible at `http://localhost:9545`. Any Ethereum tool - Metamask, `seth`, etc. - can use these endpoints. Note that you will need to specify the L2 chain ID manually if you use Metamask. The devnet's L2 chain ID is 901. @@ -44,7 +44,7 @@ You'll need a `.env` with the following contents: ```bash L1_PROVIDER_URL=http://localhost:8545 -L2_PROVIDER_URL=http://localhost:8546 +L2_PROVIDER_URL=http://localhost:9545 PRIVATE_KEY=bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7 ``` diff --git a/specs/rollup-node-p2p.md b/specs/rollup-node-p2p.md index de203ab49b..f79fded33e 100644 --- a/specs/rollup-node-p2p.md +++ b/specs/rollup-node-p2p.md @@ -332,7 +332,7 @@ except the trailing encoding schema part, which is now message-specific: /ProtocolPrefix/MessageName/SchemaVersion/ ``` -The req-resp protocols served by the kroma-node all have `/ProtocolPrefix` set to `/opstack/req`. +The req-resp protocols served by the kroma-node all have `/ProtocolPrefix` set to `/kroma-stack/req`. Individual methods may include the chain ID as part of the `/MessageName` segment, so it's immediately clear which chain the method applies to, if the communication is chain-specific. @@ -346,7 +346,7 @@ Each segment starts with a `/`, and may contain multiple `/`, and the final prot This is an optional chain syncing method, to request/serve execution payloads by number. This serves as a method to fill gaps upon missed gossip, and sync short to medium ranges of unsafe L2 blocks. -Protocol ID: `/opstack/req/payload_by_number//0/` +Protocol ID: `/kroma-stack/req/payload_by_number//0/` - `/MessageName` is `/block_by_number/` where `` is set to the kroma-node L2 chain ID. - `/SchemaVersion` is `/0` diff --git a/specs/system-config.md b/specs/system-config.md index 171c088781..3caec7abcf 100644 --- a/specs/system-config.md +++ b/specs/system-config.md @@ -12,7 +12,7 @@ - [System config contents (version 0)](#system-config-contents-version-0) - [`batcherHash` (`bytes32`)](#batcherhash-bytes32) - - [`l1FeeOverhead` and `l1FeeScalar` (`uint256,uint256`)](#l1feeoverhead-and-l1feescalar-uint256uint256) + - [`overhead` and `scalar` (`uint256,uint256`)](#overhead-and-scalar-uint256uint256) - [`gasLimit` (`uint64`)](#gaslimit-uint64) - [`unsafeBlockSigner` (`address`)](#unsafeblocksigner-address) - [Writing the system config](#writing-the-system-config) @@ -37,7 +37,7 @@ Version `0` embeds the current batch submitter ethereum address (`bytes20`) in t In the future, this versioned hash may become a commitment to a more extensive configuration, to enable more extensive redundancy and/or rotation configurations. -### `l1FeeOverhead` and `l1FeeScalar` (`uint256,uint256`) +### `overhead` and `scalar` (`uint256,uint256`) The L1 fee parameters, also known as [Gas Price Oracle (GPO)](predeploys.md#gaspriceoracle) parameters, are updated in conjunction and apply new [L1][g-l1] costs to the [L2][g-l2] transactions. @@ -76,7 +76,7 @@ A rollup node initializes its derivation process by finding a starting point bas - When started from L2 genesis, the initial system configuration is retrieved from the rollup chain configuration. - When started from an existing L2 chain, a previously included L1 block is determined as derivation starting point, and the system config can thus be retrieved from the last L2 block that referenced the L1 block as L1 origin: - - `batcherHash`, `l1FeeOverhead` and `l1FeeScalar` are retrieved from the L1 block info transaction. + - `batcherHash`, `overhead` and `scalar` are retrieved from the L1 block info transaction. - `gasLimit` is retrieved from the L2 block header. - other future variables may also be retrieved from other contents of the L2 block, such as the header. @@ -92,8 +92,9 @@ The contained log events are filtered and processed as follows: - the remaining event data is opaque, encoded as ABI bytes (i.e. includes offset and length data), and encodes the configuration update. In version `0` the following types are supported: - type `0`: `batcherHash` overwrite, as `bytes32` payload. - - type `1`: `l1FeeOverhead` and `l1FeeScalar` overwrite, as two packed `uint256` entries. + - type `1`: `overhead` and `scalar` overwrite, as two packed `uint256` entries. - type `2`: `gasLimit` overwrite, as `uint64` payload. + - type `3`: `unsafeBlockSigner` overwrite, as `address` payload. Note that individual derivation stages may be processing different L1 blocks, and should thus maintain individual system configuration copies, diff --git a/specs/validations.md b/specs/validations.md index cf81ea4942..e39acb3544 100644 --- a/specs/validations.md +++ b/specs/validations.md @@ -15,7 +15,7 @@ - [L2 Output Commitment Construction](#l2-output-commitment-construction) - [Output Payload(Version 0)](#output-payloadversion-0) - [Output Payload(Version 1)](#output-payloadversion-1) -- [The L2 Output Oracle Contract](#the-l2-output-oracle-contract) +- [L2 Output Oracle Smart Contract](#l2-output-oracle-smart-contract) - [Configuration](#configuration) - [Security Considerations](#security-considerations) - [L1 Reorgs](#l1-reorgs) @@ -27,27 +27,48 @@ ![Validation Overview](assets/verifier-proving-fault-proof.svg) After processing one or more blocks, the outputs will need to be synchronized with [L1][g-l1] for trustless execution of -L2-to-L1 messaging, such as withdrawals. Outputs are hashed in a tree-structured form which minimizes the cost of -proving any piece of data captured by the outputs. -Validators submit the output roots to L1 and can be contested with a [ZK fault proof][g-zk-fault-proof], +L2-to-L1 messaging, such as withdrawals. +These output proposals act as the bridge's view into the L2 state. +Actors called "Validators" submit the output roots to L1 and can be contested with a [ZK fault proof][g-zk-fault-proof], with a bond at stake if the proof is wrong. ## Submitting L2 Output Commitments -The validator's role is to construct and submit output roots, which are commitments made on a configurable interval, -to the `L2OutputOracle` contract running on L1. It does this by running the [validator](../components/validator/), -a service which periodically queries the rollup node's -[`kroma_outputAtBlock` rpc method](./rollup-node.md#l2-output-rpc-method) for the latest output root derived -from the latest [finalized](rollup-node.md#finalization-guarantees) L1 block. The construction of this output root is -described [below](#l2-output-commitment-construction). - -If there is no newly finalized output, the service continues querying until it receives one. It then submits this -output, and the appropriate timestamp, to the [L2 Output Oracle](#the-l2-output-oracle-contract) contract's -`submitL2Output()` function. The block number must correspond to the `startingBlockNumber` plus the next -multiple of the `SUBMISSION_INTERVAL` value. +The validator's role is to construct and submit output roots, which are commitments to the L2's state, +to the `L2OutputOracle` contract on L1. To do this, the validator periodically +queries the [rollup node](./rollup-node.md) for the latest output root derived from the latest +[finalized][finality] L1 block. It then takes the output root and +submits it to the `L2OutputOracle` contract on L1. + +[finality]: https://hackmd.io/@prysmaticlabs/finality + +The submission of output roots is permitted to a single account. It is expected that this +account continues to submit output roots over time to ensure that user withdrawals do not halt. + +The [validator](../components/validator/) is expected to submit output roots on a deterministic +interval based on the configured `SUBMISSION_INTERVAL` in the `L2OutputOracle`. The larger +the `SUBMISSION_INTERVAL`, the less often L1 transactions need to be sent to the `L2OutputOracle` +contract, but L2 users will need to wait a bit longer for an output root to be included in L1 +that includes their intention to withdrawal from the system. + +The honest `kroma-validator` algorithm assumes a connection to the `L2OutputOracle` contract to know +the L2 block number that corresponds to the next output root that must be submitted. It also +assumes a connection to an `kroma-node` to be able to query the `kroma_syncStatus` RPC endpoint. + +```python +import time + +while True: + next_checkpoint_block = L2OutputOracle.nextBlockNumber() + rollup_status = kroma_node_client.sync_status() + if rollup_status.finalized_l2.number >= next_checkpoint_block: + output = kroma_node_client.output_at_block(next_checkpoint_block) + tx = send_transaction(output) + time.sleep(poll_interval) +``` -The validator may also delete multiple output roots by calling the `deleteL2Outputs()` function and specifying the -index of the first output to delete, this will also delete all subsequent outputs. +The validator may also delete multiple output roots by calling the `deleteL2Outputs()` function +and specifying the index of the first output to delete, this will also delete all subsequent outputs. ## L2 Output Commitment Construction @@ -101,12 +122,12 @@ where: Starting from version 1, the height of the block where the output is submitted has been delayed by one. -## The L2 Output Oracle Contract +## 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` which is based on a number of blocks. -The L2 Output Oracle contract implements the following interface: +L2 Output Oracle Smart Contract implements the following interface: ```solidity interface L2OutputOracle { @@ -136,7 +157,7 @@ The first `outputRoot` submitted will thus be at height `startingBlockNumber + S If the L1 has a reorg after an output has been generated and submitted, the L2 state and correct output may change leading to a misbehavior. This is mitigated against by allowing the validator to submit an -L1 block number and hash to the [L2 Output Oracle](#the-l2-output-oracle-contract) when appending a new output; +L1 block number and hash to the [L2 Output Oracle](#l2-output-oracle-smart-contract) when appending a new output; in the event of a reorg, the block hash will not match that of the block with that number and the call will revert. ## Summary of Definitions diff --git a/specs/withdrawals.md b/specs/withdrawals.md index 732b79fa9c..af10f12fda 100644 --- a/specs/withdrawals.md +++ b/specs/withdrawals.md @@ -133,29 +133,8 @@ The Kroma Portal serves as both the entry and exit point to the Kroma L2. It is the [KromaPortal](./deposits.md#deposit-contract) contract, and in addition provides the following interface for withdrawals: -- `Types.WithdrawalTransaction` type - - ```solidity - struct WithdrawalTransaction { - uint256 nonce; - address sender; - address target; - uint256 value; - uint256 gasLimit; - bytes data; - } - ``` - -- `Types.OutputRootProof` type - - ```solidity - struct OutputRootProof { - bytes32 version; - bytes32 stateRoot; - bytes32 messagePasserStorageRoot; - bytes32 latestBlockhash; - } - ``` +- [`WithdrawalTransaction` type] +- [`OutputRootProof` type] ```solidity interface KromaPortal { @@ -237,3 +216,6 @@ contracts if desired. | `FINALIZATION_PERIOD` | `604_800` | seconds | This `FINALIZATION_PERIOD` value is equivalent to 7 days. + +[`WithdrawalTransaction` type]: https://github.com/kroma-network/kroma/blob/7a4126dcc30d10f4ebf881f681296d3fbe308eaf/packages/contracts/contracts/libraries/Types.sol#L131-L138 +[`OutputRootProof` type]: https://github.com/kroma-network/kroma/blob/7a4126dcc30d10f4ebf881f681296d3fbe308eaf/packages/contracts/contracts/libraries/Types.sol#L34-L40 diff --git a/utils/chain-ops/genesis/config.go b/utils/chain-ops/genesis/config.go index 39dc6f515c..6d983d9535 100644 --- a/utils/chain-ops/genesis/config.go +++ b/utils/chain-ops/genesis/config.go @@ -216,6 +216,11 @@ func (d *DeployConfig) Check() error { if d.L2GenesisBlockGasLimit == 0 { return fmt.Errorf("%w: L2 genesis block gas limit cannot be 0", ErrInvalidDeployConfig) } + // When the initial resource config is made to be configurable by the DeployConfig, ensure + // that this check is updated to use the values from the DeployConfig instead of the defaults. + if uint64(d.L2GenesisBlockGasLimit) < uint64(defaultResourceConfig.MaxResourceLimit+defaultResourceConfig.SystemTxMaxGas) { + return fmt.Errorf("%w: L2 genesis block gas limit is too small", ErrInvalidDeployConfig) + } if d.L2GenesisBlockBaseFeePerGas == nil { return fmt.Errorf("%w: L2 genesis block base fee per gas cannot be nil", ErrInvalidDeployConfig) } @@ -372,7 +377,7 @@ func NewDeployConfigWithNetwork(network, path string) (*DeployConfig, error) { } // NewL2ImmutableConfig will create an ImmutableConfig given an instance of a -// Hardhat and a DeployConfig. +// DeployConfig and a block. func NewL2ImmutableConfig(config *DeployConfig, block *types.Block) (immutables.ImmutableConfig, error) { immutable := make(immutables.ImmutableConfig) diff --git a/utils/chain-ops/genesis/genesis.go b/utils/chain-ops/genesis/genesis.go index 8574f399d5..6f62a1b87a 100644 --- a/utils/chain-ops/genesis/genesis.go +++ b/utils/chain-ops/genesis/genesis.go @@ -13,7 +13,8 @@ import ( "github.com/ethereum/go-ethereum/params" ) -const defaultL2GasLimit = 15_000_000 +// defaultL2GasLimit represents the default gas limit for an L2 block. +const defaultL2GasLimit = 30_000_000 // NewL2Genesis will create a new L2 genesis func NewL2Genesis(config *DeployConfig, block *types.Block, zktrie bool) (*core.Genesis, error) { diff --git a/utils/chain-ops/genesis/layer_one.go b/utils/chain-ops/genesis/layer_one.go index cb373f91c2..224ffa2215 100644 --- a/utils/chain-ops/genesis/layer_one.go +++ b/utils/chain-ops/genesis/layer_one.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" @@ -22,20 +23,46 @@ import ( "github.com/kroma-network/kroma/utils/chain-ops/state" ) -var proxies = []string{ - "SystemConfigProxy", - "L2OutputOracleProxy", - "L1CrossDomainMessengerProxy", - "L1StandardBridgeProxy", - "KromaPortalProxy", - "KromaMintableERC20FactoryProxy", - "ColosseumProxy", -} - -var portalMeteringSlot = common.Hash{31: 0x01} +var ( + // proxies represents the set of proxies in front of contracts. + proxies = []string{ + "SystemConfigProxy", + "L2OutputOracleProxy", + "L1CrossDomainMessengerProxy", + "L1StandardBridgeProxy", + "KromaPortalProxy", + "KromaMintableERC20FactoryProxy", + "ColosseumProxy", + } + // portalMeteringSlot is the storage slot containing the metering params. + portalMeteringSlot = common.Hash{31: 0x01} + // zeroHash represents the zero value for a hash. + zeroHash = common.Hash{} + // uint128Max is type(uint128).max and is set in the init function. + uint128Max = new(big.Int) + // The default values for the ResourceConfig, used as part of + // an EIP-1559 curve for deposit gas. + defaultResourceConfig = bindings.ResourceMeteringResourceConfig{ + MaxResourceLimit: 20_000_000, + ElasticityMultiplier: 10, + BaseFeeMaxChangeDenominator: 8, + MinimumBaseFee: params.GWei, + SystemTxMaxGas: 1_000_000, + } +) -var zeroHash common.Hash +func init() { + var ok bool + uint128Max, ok = new(big.Int).SetString("ffffffffffffffffffffffffffffffff", 16) + if !ok { + panic("bad uint128Max") + } + // Set the maximum base fee on the default config. + defaultResourceConfig.MaximumBaseFee = uint128Max +} +// BuildL1DeveloperGenesis will create a L1 genesis block after creating +// all of the state required for a Kroma network to function. func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) { if config.L2OutputOracleStartingTimestamp != -1 { return nil, errors.New("l2oo starting timestamp must be -1") @@ -68,6 +95,26 @@ func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) { if err != nil { return nil, err } + + portalABI, err := bindings.KromaPortalMetaData.GetAbi() + if err != nil { + return nil, err + } + // Initialize the KromaPortal without being paused + data, err := portalABI.Pack("initialize", false) + if err != nil { + return nil, fmt.Errorf("cannot abi encode initialize for KromaPortal: %w", err) + } + if _, err := upgradeProxy( + backend, + opts, + depsByName["KromaPortalProxy"].Address, + depsByName["KromaPortal"].Address, + data, + ); err != nil { + return nil, fmt.Errorf("cannot upgrade KromaPortalProxy: %w", err) + } + sysCfgABI, err := bindings.SystemConfigMetaData.GetAbi() if err != nil { return nil, err @@ -76,7 +123,8 @@ func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) { if gasLimit == 0 { gasLimit = defaultL2GasLimit } - data, err := sysCfgABI.Pack( + + data, err = sysCfgABI.Pack( "initialize", config.FinalSystemOwner, uint642Big(config.GasPriceOracleOverhead), @@ -84,6 +132,7 @@ func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) { config.BatchSenderAddress.Hash(), gasLimit, config.P2PProposerAddress, + defaultResourceConfig, ) if err != nil { return nil, fmt.Errorf("cannot abi encode initialize for SystemConfig: %w", err) @@ -95,7 +144,7 @@ func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) { depsByName["SystemConfig"].Address, data, ); err != nil { - return nil, err + return nil, fmt.Errorf("cannot upgrade SystemConfigProxy: %w", err) } l2ooABI, err := bindings.L2OutputOracleMetaData.GetAbi() @@ -138,23 +187,6 @@ func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) { return nil, err } - portalABI, err := bindings.KromaPortalMetaData.GetAbi() - if err != nil { - return nil, err - } - data, err = portalABI.Pack("initialize", false) - if err != nil { - return nil, fmt.Errorf("cannot abi encode initialize for KromaPortal: %w", err) - } - if _, err := upgradeProxy( - backend, - opts, - depsByName["KromaPortalProxy"].Address, - depsByName["KromaPortal"].Address, - data, - ); err != nil { - return nil, err - } l1XDMABI, err := bindings.L1CrossDomainMessengerMetaData.GetAbi() if err != nil { return nil, err @@ -287,6 +319,7 @@ func deployL1Contracts(config *DeployConfig, backend *backends.SimulatedBackend) if gasLimit == 0 { gasLimit = defaultL2GasLimit } + constructors = append(constructors, []deployer.Constructor{ { Name: "SystemConfig", @@ -297,6 +330,7 @@ func deployL1Contracts(config *DeployConfig, backend *backends.SimulatedBackend) config.BatchSenderAddress.Hash(), // left-padded 32 bytes value, version is zero anyway gasLimit, config.P2PProposerAddress, + defaultResourceConfig, }, }, { @@ -325,6 +359,7 @@ func deployL1Contracts(config *DeployConfig, backend *backends.SimulatedBackend) Args: []interface{}{ config.PortalGuardian, true, // _paused + predeploys.DevSystemConfigAddr, }, }, { @@ -378,6 +413,7 @@ func l1Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep /* batcherHash= */ deployment.Args[3].(common.Hash), /* gasLimit= */ deployment.Args[4].(uint64), /* unsafeBlockSigner= */ deployment.Args[5].(common.Address), + /* config= */ deployment.Args[6].(bindings.ResourceMeteringResourceConfig), ) case "L2OutputOracle": _, tx, _, err = bindings.DeployL2OutputOracle( @@ -398,6 +434,7 @@ func l1Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep predeploys.DevL2OutputOracleAddr, /* guardian= */ deployment.Args[0].(common.Address), /* paused= */ deployment.Args[1].(bool), + /* config= */ deployment.Args[2].(common.Address), predeploys.DevZKMerkleTrieAddr, ) case "Colosseum": @@ -484,6 +521,15 @@ func l1Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep func upgradeProxy(backend *backends.SimulatedBackend, opts *bind.TransactOpts, proxyAddr common.Address, implAddr common.Address, callData []byte) (*types.Transaction, error) { var tx *types.Transaction + + code, err := backend.CodeAt(context.Background(), implAddr, nil) + if err != nil { + return nil, err + } + if len(code) == 0 { + return nil, fmt.Errorf("no code at %s", implAddr) + } + proxy, err := bindings.NewProxy(proxyAddr, backend) if err != nil { return nil, err diff --git a/utils/chain-ops/genesis/layer_one_test.go b/utils/chain-ops/genesis/layer_one_test.go index 5a1f43c359..43e524f941 100644 --- a/utils/chain-ops/genesis/layer_one_test.go +++ b/utils/chain-ops/genesis/layer_one_test.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" @@ -96,6 +97,30 @@ func TestBuildL1DeveloperGenesis(t *testing.T) { require.NoError(t, err) require.Equal(t, "Wrapped Ether", name) + sysCfg, err := bindings.NewSystemConfig(predeploys.DevSystemConfigAddr, sim) + require.NoError(t, err) + cfg, err := sysCfg.ResourceConfig(&bind.CallOpts{}) + require.NoError(t, err) + require.Equal(t, cfg, defaultResourceConfig) + owner, err := sysCfg.Owner(&bind.CallOpts{}) + require.NoError(t, err) + require.Equal(t, owner, config.FinalSystemOwner) + overhead, err := sysCfg.Overhead(&bind.CallOpts{}) + require.NoError(t, err) + require.Equal(t, overhead.Uint64(), config.GasPriceOracleOverhead) + scalar, err := sysCfg.Scalar(&bind.CallOpts{}) + require.NoError(t, err) + require.Equal(t, scalar.Uint64(), config.GasPriceOracleScalar) + batcherHash, err := sysCfg.BatcherHash(&bind.CallOpts{}) + require.NoError(t, err) + require.Equal(t, common.Hash(batcherHash), config.BatchSenderAddress.Hash()) + gasLimit, err := sysCfg.GasLimit(&bind.CallOpts{}) + require.NoError(t, err) + require.Equal(t, gasLimit, uint64(config.L2GenesisBlockGasLimit)) + unsafeBlockSigner, err := sysCfg.UnsafeBlockSigner(&bind.CallOpts{}) + require.NoError(t, err) + require.Equal(t, unsafeBlockSigner, config.P2PProposerAddress) + // test that we can do deposits, etc. priv, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") require.NoError(t, err) diff --git a/utils/chain-ops/genesis/testdata/test-deploy-config-full.json b/utils/chain-ops/genesis/testdata/test-deploy-config-full.json index 362953e299..37bd563032 100644 --- a/utils/chain-ops/genesis/testdata/test-deploy-config-full.json +++ b/utils/chain-ops/genesis/testdata/test-deploy-config-full.json @@ -17,7 +17,7 @@ "l1BlockTime": 15, "l1GenesisBlockNonce": "0x0", "cliqueSignerAddress": "0x0000000000000000000000000000000000000000", - "l1GenesisBlockGasLimit": "0xe4e1c0", + "l1GenesisBlockGasLimit": "0x1c9c380", "l1GenesisBlockDifficulty": "0x1", "finalSystemOwner": "0x0000000000000000000000000000000000000111", "portalGuardian": "0x0000000000000000000000000000000000000112", @@ -30,7 +30,7 @@ "l1GenesisBlockTimestamp": "0x0", "l1GenesisBlockBaseFeePerGas": "0x3b9aca00", "l2GenesisBlockNonce": "0x0", - "l2GenesisBlockGasLimit": "0xe4e1c0", + "l2GenesisBlockGasLimit": "0x1c9c380", "l2GenesisBlockDifficulty": "0x1", "l2GenesisBlockMixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "l2GenesisBlockNumber": "0x0", diff --git a/utils/service/crypto/signature.go b/utils/service/crypto/signature.go index 87985c2784..c6166ee7fa 100644 --- a/utils/service/crypto/signature.go +++ b/utils/service/crypto/signature.go @@ -1,6 +1,7 @@ package crypto import ( + "bytes" "context" "crypto/ecdsa" "errors" @@ -56,7 +57,7 @@ func SignerFactoryFromConfig(l log.Logger, privateKey, mnemonic, hdPath string, fromAddress = common.HexToAddress(signerConfig.Address) signer = func(chainID *big.Int) SignerFn { return func(ctx context.Context, address common.Address, tx *types.Transaction) (*types.Transaction, error) { - if address.String() != signerConfig.Address { + if !bytes.Equal(address[:], fromAddress[:]) { return nil, fmt.Errorf("attempting to sign for %s, expected %s: ", address, signerConfig.Address) } return signerClient.SignTransaction(ctx, chainID, address, tx) diff --git a/utils/service/metrics/event.go b/utils/service/metrics/event.go index 8589bf654d..7814372718 100644 --- a/utils/service/metrics/event.go +++ b/utils/service/metrics/event.go @@ -52,7 +52,6 @@ func NewEventVec(factory Factory, ns string, name string, displayName string, la Namespace: ns, Name: fmt.Sprintf("last_%s_unix", name), Help: fmt.Sprintf("Timestamp of last %s event", displayName), - }, - labelNames), + }, labelNames), } } diff --git a/utils/service/txmgr/txmgr.go b/utils/service/txmgr/txmgr.go index a73d6b2dcc..f0078b1413 100644 --- a/utils/service/txmgr/txmgr.go +++ b/utils/service/txmgr/txmgr.go @@ -75,7 +75,7 @@ type ETHBackend interface { EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) } -// SimpleTxManager is a implementation of TxManager that performs linear fee +// SimpleTxManager is an implementation of TxManager that performs linear fee // bumping of a tx until it confirms. type SimpleTxManager struct { Config // directly embed the config @@ -212,7 +212,7 @@ func (m *SimpleTxManager) send(ctx context.Context, tx *types.Transaction) (*typ m.publishAndWaitForTx(ctx, tx, sendState, receiptChan) } - // Immediately publish a transaction before starting the resumbission loop + // Immediately publish a transaction before starting the resubmission loop wg.Add(1) go sendTxAsync(tx) diff --git a/yarn.lock b/yarn.lock index 2883c92fb3..01e427a628 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8348,9 +8348,9 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -"forge-std@https://github.com/foundry-rs/forge-std.git#fd86115ed6aba8e234ee0fb86c12fe35eff0b2a0": - version "1.4.0" - resolved "https://github.com/foundry-rs/forge-std.git#fd86115ed6aba8e234ee0fb86c12fe35eff0b2a0" +"forge-std@https://github.com/foundry-rs/forge-std.git#46264e9788017fc74f9f58b7efa0bc6e1df6d410": + version "1.5.2" + resolved "https://github.com/foundry-rs/forge-std.git#46264e9788017fc74f9f58b7efa0bc6e1df6d410" form-data@^3.0.0: version "3.0.1" @@ -13423,13 +13423,6 @@ qs@6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== -qs@^6.10.5: - version "6.10.5" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.5.tgz#974715920a80ff6a262264acd2c7e6c2a53282b4" - integrity sha512-O5RlPh0VFtR78y79rgcgKK4wbAI0C5zGVLztOIdpWX6ep368q5Hv6XRxDvXuZ9q3C6v+e3n8UfZZJw7IIG27eQ== - dependencies: - side-channel "^1.0.4" - qs@^6.7.0: version "6.10.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a"