diff --git a/.circleci/config.yml b/.circleci/config.yml index 238d93ed0da8..9f9a3a373f53 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -448,6 +448,7 @@ jobs: contracts-bedrock-validate-spaces: docker: - image: <> + resource_class: xlarge steps: - checkout - attach_workspace: { at: "." } @@ -469,7 +470,7 @@ jobs: op-bindings-build: docker: - image: <> - resource_class: large + resource_class: xlarge steps: - checkout - run: @@ -480,7 +481,7 @@ jobs: boba-bindings-build: docker: - image: <> - resource_class: large + resource_class: xlarge steps: - checkout - run: @@ -892,7 +893,7 @@ jobs: docker: - image: <> - image: cimg/postgres:14.1 - resource_class: large + resource_class: xlarge steps: - checkout - check-changed: @@ -968,6 +969,7 @@ jobs: devnet-allocs: docker: - image: <> + resource_class: xlarge steps: - checkout - restore_cache: @@ -1554,6 +1556,13 @@ workflows: - op-stack-go-lint - devnet-allocs - l1-geth-version-check + - go-e2e-test: + name: op-e2e-span-batch-tests + module: op-e2e + target: test-span-batch + requires: + - op-stack-go-lint + - devnet-allocs - go-e2e-test: name: op-e2e-ext-erigon-tests module: op-e2e diff --git a/.foundryrc b/.foundryrc index 0a8ddf64ab6e..90fe0bd77b75 100644 --- a/.foundryrc +++ b/.foundryrc @@ -1 +1 @@ -ee5d02c3ef5f55a06b069e4a70a820661a9130c8 +d85718785859dc0b5a095d2302d1a20ec06ab77a diff --git a/Makefile b/Makefile index 77a66e6c29c6..9a4b822fed83 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ golang-docker: # We don't use a buildx builder here, and just load directly into regular docker, for convenience. GIT_COMMIT=$$(git rev-parse HEAD) \ GIT_DATE=$$(git show -s --format='%ct') \ - IMAGE_TAGS=$$GIT_COMMIT,latest \ + IMAGE_TAGS=$$(git rev-parse HEAD),latest \ docker buildx bake \ --progress plain \ --load \ @@ -211,4 +211,3 @@ install-geth: go install -v github.com/ethereum/go-ethereum/cmd/geth@$(shell cat .gethrc); \ echo "Installed geth!"; true) .PHONY: install-geth - diff --git a/bedrock-devnet/devnet/__init__.py b/bedrock-devnet/devnet/__init__.py index 0b9fca513653..40b6d0bc6d10 100644 --- a/bedrock-devnet/devnet/__init__.py +++ b/bedrock-devnet/devnet/__init__.py @@ -208,13 +208,12 @@ def devnet_deploy(paths): # If someone reads this comment and understands why this is being done, please # update this comment to explain. init_devnet_l1_deploy_config(paths, update_timestamp=True) - outfile_l1 = pjoin(paths.devnet_dir, 'genesis-l1.json') run_command([ 'go', 'run', 'cmd/main.go', 'genesis', 'l1', '--deploy-config', paths.devnet_config_path, '--l1-allocs', paths.allocs_path, '--l1-deployments', paths.addresses_json_path, - '--outfile.l1', outfile_l1, + '--outfile.l1', paths.genesis_l1_path, ], cwd=paths.op_node_dir) log.info('Starting L1.') @@ -235,8 +234,8 @@ def devnet_deploy(paths): '--l1-rpc', 'http://localhost:8545', '--deploy-config', paths.devnet_config_path, '--deployment-dir', paths.deployment_dir, - '--outfile.l2', pjoin(paths.devnet_dir, 'genesis-l2.json'), - '--outfile.rollup', pjoin(paths.devnet_dir, 'rollup.json') + '--outfile.l2', paths.genesis_l2_path, + '--outfile.rollup', paths.rollup_config_path ], cwd=paths.op_node_dir) rollup_config = read_json(paths.rollup_config_path) @@ -296,21 +295,23 @@ def debug_dumpBlock(url): def wait_for_rpc_server(url): log.info(f'Waiting for RPC server at {url}') - conn = http.client.HTTPConnection(url) headers = {'Content-type': 'application/json'} body = '{"id":1, "jsonrpc":"2.0", "method": "eth_chainId", "params":[]}' while True: try: + conn = http.client.HTTPConnection(url) conn.request('POST', '/', body, headers) response = conn.getresponse() - conn.close() if response.status < 300: log.info(f'RPC server at {url} ready') return except Exception as e: log.info(f'Waiting for RPC server at {url}') time.sleep(1) + finally: + if conn: + conn.close() CommandPreset = namedtuple('Command', ['name', 'args', 'cwd', 'timeout']) @@ -336,6 +337,11 @@ def devnet_test(paths): cwd=paths.sdk_dir, timeout=8*60) ], max_workers=2) + run_command( + ['npx', 'hardhat', 'deposit-boba', '--network', 'hardhat-local', '--l1-contracts-json-path', paths.addresses_json_path], + cwd=paths.sdk_dir, + timeout=8*60, + ) def run_commands(commands: list[CommandPreset], max_workers=2): with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: @@ -374,13 +380,6 @@ def run_command_preset(command: CommandPreset): proc.kill() return proc.returncode - - run_command( - ['npx', 'hardhat', 'deposit-boba', '--network', 'hardhat-local', '--l1-contracts-json-path', paths.addresses_json_path], - cwd=paths.sdk_dir, - timeout=8*60, - ) - def run_command(args, check=True, shell=False, cwd=None, env=None, timeout=None): env = env if env else {} return subprocess.run( diff --git a/boba-bindings/bindings/alphabetvm_more.go b/boba-bindings/bindings/alphabetvm_more.go index 10c2fb6989e2..5e1ace298023 100644 --- a/boba-bindings/bindings/alphabetvm_more.go +++ b/boba-bindings/bindings/alphabetvm_more.go @@ -9,7 +9,7 @@ import ( "github.com/bobanetwork/v3-anchorage/boba-bindings/solc" ) -const AlphabetVMStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"test/FaultDisputeGame.t.sol:AlphabetVM\",\"label\":\"oracle\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_contract(IPreimageOracle)1001\"}],\"types\":{\"t_contract(IPreimageOracle)1001\":{\"encoding\":\"inplace\",\"label\":\"contract IPreimageOracle\",\"numberOfBytes\":\"20\"}}}" +const AlphabetVMStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"test/mocks/AlphabetVM.sol:AlphabetVM\",\"label\":\"oracle\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_contract(IPreimageOracle)1001\"}],\"types\":{\"t_contract(IPreimageOracle)1001\":{\"encoding\":\"inplace\",\"label\":\"contract IPreimageOracle\",\"numberOfBytes\":\"20\"}}}" var AlphabetVMStorageLayout = new(solc.StorageLayout) diff --git a/boba-bindings/bindings/legacyerc20eth.go b/boba-bindings/bindings/legacyerc20eth.go index 371629b052c4..723e85f5b90c 100644 --- a/boba-bindings/bindings/legacyerc20eth.go +++ b/boba-bindings/bindings/legacyerc20eth.go @@ -30,7 +30,7 @@ var ( const LegacyERC20ETHABI = "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REMOTE_TOKEN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_who\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"remoteToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]" // LegacyERC20ETHBin is the compiled bytecode used for deploying new contracts. -var LegacyERC20ETHBin = "0x6101406040523480156200001257600080fd5b5073420000000000000000000000000000000000001060006040518060400160405280600581526020016422ba3432b960d91b8152506040518060400160405280600381526020016208aa8960eb1b8152506012600160026001858581600390816200007f919062000167565b5060046200008e828262000167565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff166101205262000233565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620000ed57607f821691505b6020821081036200010e57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200016257600081815260208120601f850160051c810160208610156200013d5750805b601f850160051c820191505b818110156200015e5782815560010162000149565b5050505b505050565b81516001600160401b03811115620001835762000183620000c2565b6200019b81620001948454620000d8565b8462000114565b602080601f831160018114620001d35760008415620001ba5750858301515b600019600386901b1c1916600185901b1785556200015e565b600085815260208120601f198616915b828110156200020457888601518255948401946001909101908401620001e3565b5085821015620002235787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516101005161012051610e79620002916000396000610244015260008181610309015261039e0152600081816101a9015261032f015260006107a40152600061077b015260006107520152610e796000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610353578063e78cea9214610307578063ee9a31a21461039957600080fd5b8063ae1f6aaf14610307578063c01e1bd61461032d578063d6c0b2c41461032d57600080fd5b80639dc29fac116100bd5780639dc29fac146102ce578063a457c2d7146102e1578063a9059cbb146102f457600080fd5b806370a082311461029e57806395d89b41146102c657600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004610ab1565b6103c0565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104b1565b60405161019b9190610b2a565b61018f610213366004610ba4565b610543565b6002545b60405190815260200161019b565b61018f610238366004610bce565b6105d3565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004610ba4565b61065e565b61029461028f366004610ba4565b6106e9565b005b6101f861074b565b61021c6102ac366004610c0a565b73ffffffffffffffffffffffffffffffffffffffff163190565b6101f86107ee565b6102946102dc366004610ba4565b6107fd565b61018f6102ef366004610ba4565b61085f565b61018f610302366004610ba4565b6108ea565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c610361366004610c25565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061047957507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104a857507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104c090610c58565b80601f01602080910402602001604051908101604052809291908181526020018280546104ec90610c58565b80156105395780601f1061050e57610100808354040283529160200191610539565b820191906000526020600020905b81548152906001019060200180831161051c57829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4c656761637945524332304554483a20617070726f766520697320646973616260448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526000906084015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4c656761637945524332304554483a207472616e7366657246726f6d2069732060448201527f64697361626c656400000000000000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a20696e637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206d696e742069732064697361626c656460448201526064016105ca565b60606107767f0000000000000000000000000000000000000000000000000000000000000000610974565b61079f7f0000000000000000000000000000000000000000000000000000000000000000610974565b6107c87f0000000000000000000000000000000000000000000000000000000000000000610974565b6040516020016107da93929190610cab565b604051602081830303815290604052905090565b6060600480546104c090610c58565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206275726e2069732064697361626c656460448201526064016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a206465637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4c656761637945524332304554483a207472616e73666572206973206469736160448201527f626c65640000000000000000000000000000000000000000000000000000000060648201526000906084016105ca565b6060816000036109b757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156109e157806109cb81610d50565b91506109da9050600a83610db7565b91506109bb565b60008167ffffffffffffffff8111156109fc576109fc610dcb565b6040519080825280601f01601f191660200182016040528015610a26576020820181803683370190505b5090505b8415610aa957610a3b600183610dfa565b9150610a48600a86610e11565b610a53906030610e25565b60f81b818381518110610a6857610a68610e3d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610aa2600a86610db7565b9450610a2a565b949350505050565b600060208284031215610ac357600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610af357600080fd5b9392505050565b60005b83811015610b15578181015183820152602001610afd565b83811115610b24576000848401525b50505050565b6020815260008251806020840152610b49816040850160208701610afa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b9f57600080fd5b919050565b60008060408385031215610bb757600080fd5b610bc083610b7b565b946020939093013593505050565b600080600060608486031215610be357600080fd5b610bec84610b7b565b9250610bfa60208501610b7b565b9150604084013590509250925092565b600060208284031215610c1c57600080fd5b610af382610b7b565b60008060408385031215610c3857600080fd5b610c4183610b7b565b9150610c4f60208401610b7b565b90509250929050565b600181811c90821680610c6c57607f821691505b602082108103610ca5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008451610cbd818460208901610afa565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610cf9816001850160208a01610afa565b60019201918201528351610d14816002840160208801610afa565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610d8157610d81610d21565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610dc657610dc6610d88565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015610e0c57610e0c610d21565b500390565b600082610e2057610e20610d88565b500690565b60008219821115610e3857610e38610d21565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" +var LegacyERC20ETHBin = "0x60e06040523480156200001157600080fd5b5073420000000000000000000000000000000000001060006040518060400160405280600581526020016422ba3432b960d91b8152506040518060400160405280600381526020016208aa8960eb1b81525060128282816003908162000078919062000152565b50600462000087828262000152565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200021e565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620000d857607f821691505b602082108103620000f957634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200014d57600081815260208120601f850160051c81016020861015620001285750805b601f850160051c820191505b81811015620001495782815560010162000134565b5050505b505050565b81516001600160401b038111156200016e576200016e620000ad565b62000186816200017f8454620000c3565b84620000ff565b602080601f831160018114620001be5760008415620001a55750858301515b600019600386901b1c1916600185901b17855562000149565b600085815260208120601f198616915b82811015620001ef57888601518255948401946001909101908401620001ce565b50858210156200020e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c051610afe6200025c600039600061024401526000818161033d01526103d20152600081816101a901526103630152610afe6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610387578063e78cea921461033b578063ee9a31a2146103cd57600080fd5b8063ae1f6aaf1461033b578063c01e1bd614610361578063d6c0b2c41461036157600080fd5b80639dc29fac116100bd5780639dc29fac14610302578063a457c2d714610315578063a9059cbb1461032857600080fd5b806370a08231146102d257806395d89b41146102fa57600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004610905565b6103f4565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104e5565b60405161019b919061094e565b61018f6102133660046109ea565b610577565b6002545b60405190815260200161019b565b61018f610238366004610a14565b610607565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c3660046109ea565b610692565b61029461028f3660046109ea565b61071d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e0366004610a50565b73ffffffffffffffffffffffffffffffffffffffff163190565b6101f861077f565b6102946103103660046109ea565b61078e565b61018f6103233660046109ea565b6107f0565b61018f6103363660046109ea565b61087b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c610395366004610a6b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104ad57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104dc57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104f490610a9e565b80601f016020809104026020016040519081016040528092919081815260200182805461052090610a9e565b801561056d5780601f106105425761010080835404028352916020019161056d565b820191906000526020600020905b81548152906001019060200180831161055057829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4c656761637945524332304554483a20617070726f766520697320646973616260448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526000906084015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4c656761637945524332304554483a207472616e7366657246726f6d2069732060448201527f64697361626c656400000000000000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a20696e637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206d696e742069732064697361626c656460448201526064016105fe565b6060600480546104f490610a9e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206275726e2069732064697361626c656460448201526064016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a206465637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4c656761637945524332304554483a207472616e73666572206973206469736160448201527f626c65640000000000000000000000000000000000000000000000000000000060648201526000906084016105fe565b60006020828403121561091757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461094757600080fd5b9392505050565b600060208083528351808285015260005b8181101561097b5785810183015185820160400152820161095f565b8181111561098d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146109e557600080fd5b919050565b600080604083850312156109fd57600080fd5b610a06836109c1565b946020939093013593505050565b600080600060608486031215610a2957600080fd5b610a32846109c1565b9250610a40602085016109c1565b9150604084013590509250925092565b600060208284031215610a6257600080fd5b610947826109c1565b60008060408385031215610a7e57600080fd5b610a87836109c1565b9150610a95602084016109c1565b90509250929050565b600181811c90821680610ab257607f821691505b602082108103610aeb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b5091905056fea164736f6c634300080f000a" // DeployLegacyERC20ETH deploys a new Ethereum contract, binding an instance of LegacyERC20ETH to it. func DeployLegacyERC20ETH(auth *bind.TransactOpts, backend bind.ContractBackend) (libcommon.Address, types.Transaction, *LegacyERC20ETH, error) { diff --git a/boba-bindings/bindings/legacyerc20eth_more.go b/boba-bindings/bindings/legacyerc20eth_more.go index 72d284845612..620522f122e3 100644 --- a/boba-bindings/bindings/legacyerc20eth_more.go +++ b/boba-bindings/bindings/legacyerc20eth_more.go @@ -13,7 +13,7 @@ const LegacyERC20ETHStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contrac var LegacyERC20ETHStorageLayout = new(solc.StorageLayout) -var LegacyERC20ETHDeployedBin = "0x608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610353578063e78cea9214610307578063ee9a31a21461039957600080fd5b8063ae1f6aaf14610307578063c01e1bd61461032d578063d6c0b2c41461032d57600080fd5b80639dc29fac116100bd5780639dc29fac146102ce578063a457c2d7146102e1578063a9059cbb146102f457600080fd5b806370a082311461029e57806395d89b41146102c657600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004610ab1565b6103c0565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104b1565b60405161019b9190610b2a565b61018f610213366004610ba4565b610543565b6002545b60405190815260200161019b565b61018f610238366004610bce565b6105d3565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004610ba4565b61065e565b61029461028f366004610ba4565b6106e9565b005b6101f861074b565b61021c6102ac366004610c0a565b73ffffffffffffffffffffffffffffffffffffffff163190565b6101f86107ee565b6102946102dc366004610ba4565b6107fd565b61018f6102ef366004610ba4565b61085f565b61018f610302366004610ba4565b6108ea565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c610361366004610c25565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061047957507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104a857507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104c090610c58565b80601f01602080910402602001604051908101604052809291908181526020018280546104ec90610c58565b80156105395780601f1061050e57610100808354040283529160200191610539565b820191906000526020600020905b81548152906001019060200180831161051c57829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4c656761637945524332304554483a20617070726f766520697320646973616260448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526000906084015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4c656761637945524332304554483a207472616e7366657246726f6d2069732060448201527f64697361626c656400000000000000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a20696e637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206d696e742069732064697361626c656460448201526064016105ca565b60606107767f0000000000000000000000000000000000000000000000000000000000000000610974565b61079f7f0000000000000000000000000000000000000000000000000000000000000000610974565b6107c87f0000000000000000000000000000000000000000000000000000000000000000610974565b6040516020016107da93929190610cab565b604051602081830303815290604052905090565b6060600480546104c090610c58565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206275726e2069732064697361626c656460448201526064016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a206465637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4c656761637945524332304554483a207472616e73666572206973206469736160448201527f626c65640000000000000000000000000000000000000000000000000000000060648201526000906084016105ca565b6060816000036109b757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156109e157806109cb81610d50565b91506109da9050600a83610db7565b91506109bb565b60008167ffffffffffffffff8111156109fc576109fc610dcb565b6040519080825280601f01601f191660200182016040528015610a26576020820181803683370190505b5090505b8415610aa957610a3b600183610dfa565b9150610a48600a86610e11565b610a53906030610e25565b60f81b818381518110610a6857610a68610e3d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610aa2600a86610db7565b9450610a2a565b949350505050565b600060208284031215610ac357600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610af357600080fd5b9392505050565b60005b83811015610b15578181015183820152602001610afd565b83811115610b24576000848401525b50505050565b6020815260008251806020840152610b49816040850160208701610afa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b9f57600080fd5b919050565b60008060408385031215610bb757600080fd5b610bc083610b7b565b946020939093013593505050565b600080600060608486031215610be357600080fd5b610bec84610b7b565b9250610bfa60208501610b7b565b9150604084013590509250925092565b600060208284031215610c1c57600080fd5b610af382610b7b565b60008060408385031215610c3857600080fd5b610c4183610b7b565b9150610c4f60208401610b7b565b90509250929050565b600181811c90821680610c6c57607f821691505b602082108103610ca5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008451610cbd818460208901610afa565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610cf9816001850160208a01610afa565b60019201918201528351610d14816002840160208801610afa565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610d8157610d81610d21565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610dc657610dc6610d88565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015610e0c57610e0c610d21565b500390565b600082610e2057610e20610d88565b500690565b60008219821115610e3857610e38610d21565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" +var LegacyERC20ETHDeployedBin = "0x608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610387578063e78cea921461033b578063ee9a31a2146103cd57600080fd5b8063ae1f6aaf1461033b578063c01e1bd614610361578063d6c0b2c41461036157600080fd5b80639dc29fac116100bd5780639dc29fac14610302578063a457c2d714610315578063a9059cbb1461032857600080fd5b806370a08231146102d257806395d89b41146102fa57600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004610905565b6103f4565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104e5565b60405161019b919061094e565b61018f6102133660046109ea565b610577565b6002545b60405190815260200161019b565b61018f610238366004610a14565b610607565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c3660046109ea565b610692565b61029461028f3660046109ea565b61071d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e0366004610a50565b73ffffffffffffffffffffffffffffffffffffffff163190565b6101f861077f565b6102946103103660046109ea565b61078e565b61018f6103233660046109ea565b6107f0565b61018f6103363660046109ea565b61087b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c610395366004610a6b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104ad57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104dc57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104f490610a9e565b80601f016020809104026020016040519081016040528092919081815260200182805461052090610a9e565b801561056d5780601f106105425761010080835404028352916020019161056d565b820191906000526020600020905b81548152906001019060200180831161055057829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4c656761637945524332304554483a20617070726f766520697320646973616260448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526000906084015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4c656761637945524332304554483a207472616e7366657246726f6d2069732060448201527f64697361626c656400000000000000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a20696e637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206d696e742069732064697361626c656460448201526064016105fe565b6060600480546104f490610a9e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206275726e2069732064697361626c656460448201526064016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a206465637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4c656761637945524332304554483a207472616e73666572206973206469736160448201527f626c65640000000000000000000000000000000000000000000000000000000060648201526000906084016105fe565b60006020828403121561091757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461094757600080fd5b9392505050565b600060208083528351808285015260005b8181101561097b5785810183015185820160400152820161095f565b8181111561098d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146109e557600080fd5b919050565b600080604083850312156109fd57600080fd5b610a06836109c1565b946020939093013593505050565b600080600060608486031215610a2957600080fd5b610a32846109c1565b9250610a40602085016109c1565b9150604084013590509250925092565b600060208284031215610a6257600080fd5b610947826109c1565b60008060408385031215610a7e57600080fd5b610a87836109c1565b9150610a95602084016109c1565b90509250929050565b600181811c90821680610ab257607f821691505b602082108103610aeb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b5091905056fea164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(LegacyERC20ETHStorageLayoutJSON), LegacyERC20ETHStorageLayout); err != nil { diff --git a/boba-bindings/bindings/mips_more.go b/boba-bindings/bindings/mips_more.go index 83647b4ca047..e30283cd3820 100644 --- a/boba-bindings/bindings/mips_more.go +++ b/boba-bindings/bindings/mips_more.go @@ -15,7 +15,7 @@ var MIPSStorageLayout = new(solc.StorageLayout) var MIPSDeployedBin = "0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063155633fe146100465780637dc0d1d01461006b578063836e7b32146100af575b600080fd5b610051634000000081565b60405163ffffffff90911681526020015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610062565b6100c26100bd366004611d2e565b6100d0565b604051908152602001610062565b60006100da611c5b565b608081146100e757600080fd5b604051610600146100f757600080fd5b6084871461010457600080fd5b6101a4851461011257600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b60208110156101bd57823560e01c8252600490920191602090910190600101610199565b505050806101200151156101db576101d361061b565b915050610612565b6101408101805160010167ffffffffffffffff16905260608101516000906102039082610737565b9050603f601a82901c16600281148061022257508063ffffffff166003145b156102775760006002836303ffffff1663ffffffff16901b846080015163f00000001617905061026c8263ffffffff1660021461026057601f610263565b60005b60ff16826107f3565b945050505050610612565b6101608301516000908190601f601086901c81169190601587901c16602081106102a3576102a3611da2565b602002015192508063ffffffff851615806102c457508463ffffffff16601c145b156102fb578661016001518263ffffffff16602081106102e6576102e6611da2565b6020020151925050601f600b86901c166103b7565b60208563ffffffff16101561035d578463ffffffff16600c148061032557508463ffffffff16600d145b8061033657508463ffffffff16600e145b15610347578561ffff1692506103b7565b6103568661ffff1660106108e4565b92506103b7565b60288563ffffffff1610158061037957508463ffffffff166022145b8061038a57508463ffffffff166026145b156103b7578661016001518263ffffffff16602081106103ac576103ac611da2565b602002015192508190505b60048563ffffffff16101580156103d4575060088563ffffffff16105b806103e557508463ffffffff166001145b15610404576103f685878487610957565b975050505050505050610612565b63ffffffff6000602087831610610469576104248861ffff1660106108e4565b9095019463fffffffc861661043a816001610737565b915060288863ffffffff161015801561045a57508763ffffffff16603014155b1561046757809250600093505b505b600061047789888885610b67565b63ffffffff9081169150603f8a1690891615801561049c575060088163ffffffff1610155b80156104ae5750601c8163ffffffff16105b1561058b578063ffffffff16600814806104ce57508063ffffffff166009145b15610505576104f38163ffffffff166008146104ea57856104ed565b60005b896107f3565b9b505050505050505050505050610612565b8063ffffffff16600a03610525576104f3858963ffffffff8a16156112f7565b8063ffffffff16600b03610546576104f3858963ffffffff8a1615156112f7565b8063ffffffff16600c0361055d576104f38d6113dd565b60108163ffffffff161015801561057a5750601c8163ffffffff16105b1561058b576104f381898988611914565b8863ffffffff1660381480156105a6575063ffffffff861615155b156105db5760018b61016001518763ffffffff16602081106105ca576105ca611da2565b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff146105f8576105f884600184611b0e565b610604858360016112f7565b9b5050505050505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b60208110156106ba57601c8601518452602090950194600490930192600101610696565b506000835283830384a06000945080600181146106da5760039550610702565b8280156106f257600181146106fb5760029650610700565b60009650610700565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008061074383611bb2565b9050600384161561075357600080fd5b6020810190358460051c8160005b601b8110156107b95760208501943583821c6001168015610789576001811461079e576107af565b600084815260208390526040902093506107af565b600082815260208590526040902093505b5050600101610761565b5060805191508181146107d457630badf00d60005260206000fd5b5050601f94909416601c0360031b9390931c63ffffffff169392505050565b60006107fd611c5b565b60809050806060015160040163ffffffff16816080015163ffffffff1614610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b60608101805160808301805163ffffffff9081169093528583169052908516156108dc57806008018261016001518663ffffffff16602081106108cb576108cb611da2565b63ffffffff90921660209290920201525b61061261061b565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610941576000610943565b815b90861663ffffffff16179250505092915050565b6000610961611c5b565b608090506000816060015160040163ffffffff16826080015163ffffffff16146109e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f74000000000000000000000000604482015260640161087d565b8663ffffffff1660041480610a0257508663ffffffff166005145b15610a7e5760008261016001518663ffffffff1660208110610a2657610a26611da2565b602002015190508063ffffffff168563ffffffff16148015610a4e57508763ffffffff166004145b80610a7657508063ffffffff168563ffffffff1614158015610a7657508763ffffffff166005145b915050610afb565b8663ffffffff16600603610a9b5760008460030b13159050610afb565b8663ffffffff16600703610ab75760008460030b139050610afb565b8663ffffffff16600103610afb57601f601087901c166000819003610ae05760008560030b1291505b8063ffffffff16600103610af95760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b41576002610b268861ffff1660106108e4565b63ffffffff90811690911b8201600401166080840152610b53565b60808301805160040163ffffffff1690525b610b5b61061b565b98975050505050505050565b6000603f601a86901c16801580610b96575060088163ffffffff1610158015610b965750600f8163ffffffff16105b15610fec57603f86168160088114610bdd5760098114610be657600a8114610bef57600b8114610bf857600c8114610c0157600d8114610c0a57600e8114610c1357610c18565b60209150610c18565b60219150610c18565b602a9150610c18565b602b9150610c18565b60249150610c18565b60259150610c18565b602691505b508063ffffffff16600003610c3f5750505063ffffffff8216601f600686901c161b6112ef565b8063ffffffff16600203610c655750505063ffffffff8216601f600686901c161c6112ef565b8063ffffffff16600303610c9b57601f600688901c16610c9163ffffffff8716821c60208390036108e4565b93505050506112ef565b8063ffffffff16600403610cbd5750505063ffffffff8216601f84161b6112ef565b8063ffffffff16600603610cdf5750505063ffffffff8216601f84161c6112ef565b8063ffffffff16600703610d1257610d098663ffffffff168663ffffffff16901c876020036108e4565b925050506112ef565b8063ffffffff16600803610d2a5785925050506112ef565b8063ffffffff16600903610d425785925050506112ef565b8063ffffffff16600a03610d5a5785925050506112ef565b8063ffffffff16600b03610d725785925050506112ef565b8063ffffffff16600c03610d8a5785925050506112ef565b8063ffffffff16600f03610da25785925050506112ef565b8063ffffffff16601003610dba5785925050506112ef565b8063ffffffff16601103610dd25785925050506112ef565b8063ffffffff16601203610dea5785925050506112ef565b8063ffffffff16601303610e025785925050506112ef565b8063ffffffff16601803610e1a5785925050506112ef565b8063ffffffff16601903610e325785925050506112ef565b8063ffffffff16601a03610e4a5785925050506112ef565b8063ffffffff16601b03610e625785925050506112ef565b8063ffffffff16602003610e7b575050508282016112ef565b8063ffffffff16602103610e94575050508282016112ef565b8063ffffffff16602203610ead575050508183036112ef565b8063ffffffff16602303610ec6575050508183036112ef565b8063ffffffff16602403610edf575050508282166112ef565b8063ffffffff16602503610ef8575050508282176112ef565b8063ffffffff16602603610f11575050508282186112ef565b8063ffffffff16602703610f2b57505050828217196112ef565b8063ffffffff16602a03610f5c578460030b8660030b12610f4d576000610f50565b60015b60ff16925050506112ef565b8063ffffffff16602b03610f84578463ffffffff168663ffffffff1610610f4d576000610f50565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015260640161087d565b50610f84565b8063ffffffff16601c0361107057603f86166002819003611012575050508282026112ef565b8063ffffffff166020148061102d57508063ffffffff166021145b15610fe6578063ffffffff16602003611044579419945b60005b6380000000871615611066576401fffffffe600197881b169601611047565b92506112ef915050565b8063ffffffff16600f0361109257505065ffffffff0000601083901b166112ef565b8063ffffffff166020036110ce576110c68560031660080260180363ffffffff168463ffffffff16901c60ff1660086108e4565b9150506112ef565b8063ffffffff16602103611103576110c68560021660080260100363ffffffff168463ffffffff16901c61ffff1660106108e4565b8063ffffffff1660220361113257505063ffffffff60086003851602811681811b198416918316901b176112ef565b8063ffffffff1660230361114957829150506112ef565b8063ffffffff1660240361117b578460031660080260180363ffffffff168363ffffffff16901c60ff169150506112ef565b8063ffffffff166025036111ae578460021660080260100363ffffffff168363ffffffff16901c61ffff169150506112ef565b8063ffffffff166026036111e057505063ffffffff60086003851602601803811681811c198416918316901c176112ef565b8063ffffffff1660280361121657505060ff63ffffffff60086003861602601803811682811b9091188316918416901b176112ef565b8063ffffffff1660290361124d57505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b176112ef565b8063ffffffff16602a0361127c57505063ffffffff60086003851602811681811c198316918416901c176112ef565b8063ffffffff16602b0361129357839150506112ef565b8063ffffffff16602e036112c557505063ffffffff60086003851602601803811681811b198316918416901b176112ef565b8063ffffffff166030036112dc57829150506112ef565b8063ffffffff16603803610f8457839150505b949350505050565b6000611301611c5b565b506080602063ffffffff861610611374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015260640161087d565b63ffffffff8516158015906113865750825b156113ba57838161016001518663ffffffff16602081106113a9576113a9611da2565b63ffffffff90921660209290920201525b60808101805163ffffffff8082166060850152600490910116905261061261061b565b60006113e7611c5b565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa036114615781610fff81161561143057610fff811661100003015b8363ffffffff166000036114575760e08801805163ffffffff83820116909152955061145b565b8395505b506118d3565b8563ffffffff16610fcd0361147c57634000000094506118d3565b8563ffffffff166110180361149457600194506118d3565b8563ffffffff16611096036114ca57600161012088015260ff83166101008801526114bd61061b565b9998505050505050505050565b8563ffffffff16610fa3036117365763ffffffff8316156118d3577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8416016116f05760006115258363fffffffc166001610737565b60208901519091508060001a60010361159457604080516000838152336020528d83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790505b6040808a015190517fe03110e10000000000000000000000000000000000000000000000000000000081526004810183905263ffffffff9091166024820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e03110e1906044016040805180830381865afa158015611635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116599190611dd1565b91509150600386168060040382811015611671578092505b508186101561167e578591505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b039150811981169050838119871617955050506116d58663fffffffc16600186611b0e565b60408b018051820163ffffffff169052975061173192505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff841601611725578094506118d3565b63ffffffff9450600993505b6118d3565b8563ffffffff16610fa4036118275763ffffffff831660011480611760575063ffffffff83166002145b80611771575063ffffffff83166004145b1561177e578094506118d3565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8416016117255760006117be8363fffffffc166001610737565b602089015190915060038416600403838110156117d9578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b176020880152600060408801529350836118d3565b8563ffffffff16610fd7036118d3578163ffffffff166003036118c75763ffffffff8316158061185d575063ffffffff83166005145b8061186e575063ffffffff83166003145b1561187c57600094506118d3565b63ffffffff831660011480611897575063ffffffff83166002145b806118a8575063ffffffff83166006145b806118b9575063ffffffff83166004145b1561172557600194506118d3565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b015260040190911690526114bd61061b565b600061191e611c5b565b506080600063ffffffff871660100361193c575060c0810151611aa5565b8663ffffffff1660110361195b5763ffffffff861660c0830152611aa5565b8663ffffffff16601203611974575060a0810151611aa5565b8663ffffffff166013036119935763ffffffff861660a0830152611aa5565b8663ffffffff166018036119c75763ffffffff600387810b9087900b02602081901c821660c08501521660a0830152611aa5565b8663ffffffff166019036119f85763ffffffff86811681871602602081901c821660c08501521660a0830152611aa5565b8663ffffffff16601a03611a4e578460030b8660030b81611a1b57611a1b611df5565b0763ffffffff1660c0830152600385810b9087900b81611a3d57611a3d611df5565b0563ffffffff1660a0830152611aa5565b8663ffffffff16601b03611aa5578463ffffffff168663ffffffff1681611a7757611a77611df5565b0663ffffffff90811660c084015285811690871681611a9857611a98611df5565b0463ffffffff1660a08301525b63ffffffff841615611ae057808261016001518563ffffffff1660208110611acf57611acf611da2565b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611b0361061b565b979650505050505050565b6000611b1983611bb2565b90506003841615611b2957600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611ba75760208401933582821c6001168015611b775760018114611b8c57611b9d565b60008581526020839052604090209450611b9d565b600082815260208690526040902094505b5050600101611b4f565b505060805250505050565b60ff8116610380026101a4810190369061052401811015611c55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f6174610000000000000000000000000000000000000000000000000000000000606482015260840161087d565b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611cc1611cc6565b905290565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112611cf757600080fd5b50813567ffffffffffffffff811115611d0f57600080fd5b602083019150836020828501011115611d2757600080fd5b9250929050565b600080600080600060608688031215611d4657600080fd5b853567ffffffffffffffff80821115611d5e57600080fd5b611d6a89838a01611ce5565b90975095506020880135915080821115611d8357600080fd5b50611d9088828901611ce5565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060408385031215611de457600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a" -var MIPSDeployedSourceMap = "1131:40054:144:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1710:45;;1745:10;1710:45;;;;;188:10:310;176:23;;;158:42;;146:2;131:18;1710:45:144;;;;;;;;2448:99;;;412:42:310;2534:6:144;400:55:310;382:74;;370:2;355:18;2448:99:144;211:251:310;26025:6379:144;;;;;;:::i;:::-;;:::i;:::-;;;1755:25:310;;;1743:2;1728:18;26025:6379:144;1609:177:310;26025:6379:144;26128:7;26171:18;;:::i;:::-;26318:4;26311:5;26308:15;26298:134;;26412:1;26409;26402:12;26298:134;26468:4;26462:11;26475:10;26459:27;26449:136;;26565:1;26562;26555:12;26449:136;26634:3;26615:17;26612:26;26602:151;;26733:1;26730;26723:12;26602:151;26798:3;26783:13;26780:22;26770:146;;26896:1;26893;26886:12;26770:146;27176:24;;27521:4;27222:20;27579:2;27280:21;;27176:24;27338:18;27222:20;27280:21;;;27176:24;27153:21;27149:52;;;27338:18;27222:20;;;27280:21;;;27176:24;27149:52;;27222:20;;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;;27338:18;27222:20;27280:21;;;27176:24;27153:21;27149:52;;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;28197:10;27338:18;28187:21;;;27280;;;;28295:1;28280:77;28305:2;28302:1;28299:9;28280:77;;;27176:24;;27153:21;27149:52;27222:20;;28353:1;27280:21;;;;27164:2;27338:18;;;;28323:1;28316:9;28280:77;;;28284:14;;;28435:5;:12;;;28431:71;;;28474:13;:11;:13::i;:::-;28467:20;;;;;28431:71;28516:10;;;:15;;28530:1;28516:15;;;;;28601:8;;;;-1:-1:-1;;28593:20:144;;-1:-1:-1;28593:7:144;:20::i;:::-;28579:34;-1:-1:-1;28643:10:144;28651:2;28643:10;;;;28720:1;28710:11;;;:26;;;28725:6;:11;;28735:1;28725:11;28710:26;28706:310;;;28866:13;28935:1;28913:4;28920:10;28913:17;28912:24;;;;28883:5;:12;;;28898:10;28883:25;28882:54;28866:70;;28961:40;28972:6;:11;;28982:1;28972:11;:20;;28990:2;28972:20;;;28986:1;28972:20;28961:40;;28994:6;28961:10;:40::i;:::-;28954:47;;;;;;;;28706:310;29265:15;;;;29060:9;;;;29197:4;29191:2;29183:10;;;29182:19;;;29265:15;29290:2;29282:10;;;29281:19;29265:36;;;;;;;:::i;:::-;;;;;;-1:-1:-1;29330:5:144;29354:11;;;;;:29;;;29369:6;:14;;29379:4;29369:14;29354:29;29350:832;;;29446:5;:15;;;29462:5;29446:22;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;29509:4:144;29503:2;29495:10;;;29494:19;29350:832;;;29547:4;29538:6;:13;;;29534:648;;;29668:6;:13;;29678:3;29668:13;:30;;;;29685:6;:13;;29695:3;29685:13;29668:30;:47;;;;29702:6;:13;;29712:3;29702:13;29668:47;29664:253;;;29778:4;29785:6;29778:13;29773:18;;29534:648;;29664:253;29877:21;29880:4;29887:6;29880:13;29895:2;29877;:21::i;:::-;29872:26;;29534:648;;;29951:4;29941:6;:14;;;;:32;;;;29959:6;:14;;29969:4;29959:14;29941:32;:50;;;;29977:6;:14;;29987:4;29977:14;29941:50;29937:245;;;30061:5;:15;;;30077:5;30061:22;;;;;;;;;:::i;:::-;;;;;30056:27;;30162:5;30154:13;;29937:245;30211:1;30201:6;:11;;;;:25;;;;;30225:1;30216:6;:10;;;30201:25;30200:42;;;;30231:6;:11;;30241:1;30231:11;30200:42;30196:125;;;30269:37;30282:6;30290:4;30296:5;30303:2;30269:12;:37::i;:::-;30262:44;;;;;;;;;;;30196:125;30354:13;30335:16;30506:4;30496:14;;;;30492:446;;30575:21;30578:4;30585:6;30578:13;30593:2;30575;:21::i;:::-;30569:27;;;;30633:10;30628:15;;30667:16;30628:15;30681:1;30667:7;:16::i;:::-;30661:22;;30715:4;30705:6;:14;;;;:32;;;;;30723:6;:14;;30733:4;30723:14;;30705:32;30701:223;;;30802:4;30790:16;;30904:1;30896:9;;30701:223;30512:426;30492:446;30971:10;30984:26;30992:4;30998:2;31002;31006:3;30984:7;:26::i;:::-;31013:10;30984:39;;;;-1:-1:-1;31109:4:144;31102:11;;;31141;;;:24;;;;;31164:1;31156:4;:9;;;;31141:24;:39;;;;;31176:4;31169;:11;;;31141:39;31137:860;;;31204:4;:9;;31212:1;31204:9;:22;;;;31217:4;:9;;31225:1;31217:9;31204:22;31200:144;;;31288:37;31299:4;:9;;31307:1;31299:9;:21;;31315:5;31299:21;;;31311:1;31299:21;31322:2;31288:10;:37::i;:::-;31281:44;;;;;;;;;;;;;;;31200:144;31366:4;:11;;31374:3;31366:11;31362:121;;31436:28;31445:5;31452:2;31456:7;;;;31436:8;:28::i;31362:121::-;31504:4;:11;;31512:3;31504:11;31500:121;;31574:28;31583:5;31590:2;31594:7;;;;;31574:8;:28::i;31500:121::-;31691:4;:11;;31699:3;31691:11;31687:93;;31733:28;31747:13;31733;:28::i;31687:93::-;31883:4;31875;:12;;;;:27;;;;;31898:4;31891;:11;;;31875:27;31871:112;;;31933:31;31944:4;31950:2;31954;31958:5;31933:10;:31::i;31871:112::-;32057:6;:14;;32067:4;32057:14;:28;;;;-1:-1:-1;32075:10:144;;;;;32057:28;32053:93;;;32130:1;32105:5;:15;;;32121:5;32105:22;;;;;;;;;:::i;:::-;:26;;;;:22;;;;;;:26;32053:93;32192:9;:26;;32205:13;32192:26;32188:92;;32238:27;32247:9;32258:1;32261:3;32238:8;:27::i;:::-;32361:26;32370:5;32377:3;32382:4;32361:8;:26::i;:::-;32354:33;;;;;;;;;;;;;26025:6379;;;;;;;;:::o;3087:2334::-;3634:4;3628:11;;3550:4;3353:31;3342:43;;3413:13;3353:31;3752:2;3452:13;;3342:43;3359:24;3353:31;3452:13;;;3342:43;;;;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3413:13;4180:11;3359:24;3353:31;3452:13;;;3342:43;3413:13;4275:11;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3128:12;;4415:13;;3628:11;;3452:13;;;;4180:11;3128:12;4495:84;4520:2;4517:1;4514:9;4495:84;;;3369:13;3359:24;;3353:31;3342:43;;3373:2;3413:13;;;;4575:1;3452:13;;;;4538:1;4531:9;4495:84;;;4499:14;4642:1;4638:2;4631:13;4737:5;4733:2;4729:14;4722:5;4717:27;4811:1;4797:15;;4832:6;4856:1;4851:273;;;;5191:1;5181:11;;4825:369;;4851:273;4883:8;4941:22;;;;5020:1;5015:22;;;;5107:1;5097:11;;4876:234;;4941:22;4960:1;4950:11;;4941:22;;5015;5034:1;5024:11;;4876:234;;4825:369;-1:-1:-1;;;5317:14:144;;;5300:32;;5360:19;5356:30;5392:3;5388:16;;;;5353:52;;3087:2334;-1:-1:-1;3087:2334:144:o;21746:1831::-;21819:11;21930:14;21947:24;21959:11;21947;:24::i;:::-;21930:41;;22079:1;22072:5;22068:13;22065:33;;;22094:1;22091;22084:12;22065:33;22227:2;22215:15;;;22168:20;22657:5;22654:1;22650:13;22692:4;22728:1;22713:343;22738:2;22735:1;22732:9;22713:343;;;22861:2;22849:15;;;22798:20;22896:12;;;22910:1;22892:20;22933:42;;;;23001:1;22996:42;;;;22885:153;;22933:42;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;22942:31;;22933:42;;22996;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;23005:31;;22885:153;-1:-1:-1;;22756:1:144;22749:9;22713:343;;;22717:14;23166:4;23160:11;23145:26;;23252:7;23246:4;23243:17;23233:124;;23294:10;23291:1;23284:21;23336:2;23333:1;23326:13;23233:124;-1:-1:-1;;23484:2:144;23473:14;;;;23461:10;23457:31;23454:1;23450:39;23518:16;;;;23536:10;23514:33;;21746:1831;-1:-1:-1;;;21746:1831:144:o;18856:823::-;18925:12;19012:18;;:::i;:::-;19080:4;19071:13;;19132:5;:8;;;19143:1;19132:12;19116:28;;:5;:12;;;:28;;;19112:95;;19164:28;;;;;2182:2:310;19164:28:144;;;2164:21:310;2221:2;2201:18;;;2194:30;2260:20;2240:18;;;2233:48;2298:18;;19164:28:144;;;;;;;;19112:95;19296:8;;;;;19329:12;;;;;19318:23;;;;;;;19355:20;;;;;19296:8;19487:13;;;19483:90;;19548:6;19557:1;19548:10;19520:5;:15;;;19536:8;19520:25;;;;;;;;;:::i;:::-;:38;;;;:25;;;;;;:38;19483:90;19649:13;:11;:13::i;2645:339::-;2706:11;2770:18;;;;2779:8;;;;2770:18;;;;;;2769:25;;;;;2786:1;2833:2;:9;;;2827:16;;;;;2826:22;;2825:32;;;;;;;2887:9;;2886:15;2769:25;2944:21;;2964:1;2944:21;;;2955:6;2944:21;2929:11;;;;;:37;;-1:-1:-1;;;2645:339:144;;;;:::o;13732:2026::-;13829:12;13915:18;;:::i;:::-;13983:4;13974:13;;14015:17;14075:5;:8;;;14086:1;14075:12;14059:28;;:5;:12;;;:28;;;14055:97;;14107:30;;;;;2529:2:310;14107:30:144;;;2511:21:310;2568:2;2548:18;;;2541:30;2607:22;2587:18;;;2580:50;2647:18;;14107:30:144;2327:344:310;14055:97:144;14222:7;:12;;14233:1;14222:12;:28;;;;14238:7;:12;;14249:1;14238:12;14222:28;14218:947;;;14270:9;14282:5;:15;;;14298:6;14282:23;;;;;;;;;:::i;:::-;;;;;14270:35;;14346:2;14339:9;;:3;:9;;;:25;;;;;14352:7;:12;;14363:1;14352:12;14339:25;14338:58;;;;14377:2;14370:9;;:3;:9;;;;:25;;;;;14383:7;:12;;14394:1;14383:12;14370:25;14323:73;;14252:159;14218:947;;;14508:7;:12;;14519:1;14508:12;14504:661;;14569:1;14561:3;14555:15;;;;14540:30;;14504:661;;;14673:7;:12;;14684:1;14673:12;14669:496;;14733:1;14726:3;14720:14;;;14705:29;;14669:496;;;14854:7;:12;;14865:1;14854:12;14850:315;;14942:4;14936:2;14927:11;;;14926:20;14912:10;14969:8;;;14965:84;;15029:1;15022:3;15016:14;;;15001:29;;14965:84;15070:3;:8;;15077:1;15070:8;15066:85;;15131:1;15123:3;15117:15;;;;15102:30;;15066:85;14868:297;14850:315;15241:8;;;;;15319:12;;;;15308:23;;;;;15475:178;;;;15566:1;15540:22;15543:5;15551:6;15543:14;15559:2;15540;:22::i;:::-;:27;;;;;;;15526:42;;15535:1;15526:42;15511:57;:12;;;:57;15475:178;;;15622:12;;;;;15637:1;15622:16;15607:31;;;;15475:178;15728:13;:11;:13::i;:::-;15721:20;13732:2026;-1:-1:-1;;;;;;;;13732:2026:144:o;32450:8733::-;32537:10;32599;32607:2;32599:10;;;;32638:11;;;:44;;;32664:1;32654:6;:11;;;;:27;;;;;32678:3;32669:6;:12;;;32654:27;32634:8490;;;32723:4;32716:11;;32847:6;32907:3;32902:25;;;;32982:3;32977:25;;;;33056:3;33051:25;;;;33131:3;33126:25;;;;33205:3;33200:25;;;;33278:3;33273:25;;;;33352:3;33347:25;;;;32840:532;;32902:25;32921:4;32913:12;;32902:25;;32977;32996:4;32988:12;;32977:25;;33051;33070:4;33062:12;;33051:25;;33126;33145:4;33137:12;;33126:25;;33200;33219:4;33211:12;;33200:25;;33273;33292:4;33284:12;;33273:25;;33347;33366:4;33358:12;;32840:532;;33435:4;:12;;33443:4;33435:12;33431:4023;;-1:-1:-1;;;33486:9:144;33478:26;;33499:4;33494:1;33486:9;;;33485:18;33478:26;33471:33;;33431:4023;33572:4;:12;;33580:4;33572:12;33568:3886;;-1:-1:-1;;;33623:9:144;33615:26;;33636:4;33631:1;33623:9;;;33622:18;33615:26;33608:33;;33568:3886;33709:4;:12;;33717:4;33709:12;33705:3749;;33774:4;33769:1;33761:9;;;33760:18;33807:27;33761:9;33810:11;;;;33823:2;:10;;;33807:2;:27::i;:::-;33800:34;;;;;;;33705:3749;33903:4;:12;;33911:4;33903:12;33899:3555;;-1:-1:-1;;;33946:17:144;;;33958:4;33953:9;;33946:17;33939:24;;33899:3555;34032:4;:11;;34040:3;34032:11;34028:3426;;-1:-1:-1;;;34074:17:144;;;34086:4;34081:9;;34074:17;34067:24;;34028:3426;34160:4;:12;;34168:4;34160:12;34156:3298;;34203:21;34212:2;34206:8;;:2;:8;;;;34221:2;34216;:7;34203:2;:21::i;:::-;34196:28;;;;;;34156:3298;34473:4;:12;;34481:4;34473:12;34469:2985;;34516:2;34509:9;;;;;;34469:2985;34587:4;:12;;34595:4;34587:12;34583:2871;;34630:2;34623:9;;;;;;34583:2871;34701:4;:12;;34709:4;34701:12;34697:2757;;34744:2;34737:9;;;;;;34697:2757;34815:4;:12;;34823:4;34815:12;34811:2643;;34858:2;34851:9;;;;;;34811:2643;34932:4;:12;;34940:4;34932:12;34928:2526;;34975:2;34968:9;;;;;;34928:2526;35092:4;:12;;35100:4;35092:12;35088:2366;;35135:2;35128:9;;;;;;35088:2366;35206:4;:12;;35214:4;35206:12;35202:2252;;35249:2;35242:9;;;;;;35202:2252;35320:4;:12;;35328:4;35320:12;35316:2138;;35363:2;35356:9;;;;;;35316:2138;35434:4;:12;;35442:4;35434:12;35430:2024;;35477:2;35470:9;;;;;;35430:2024;35548:4;:12;;35556:4;35548:12;35544:1910;;35591:2;35584:9;;;;;;35544:1910;35662:4;:12;;35670:4;35662:12;35658:1796;;35705:2;35698:9;;;;;;35658:1796;35777:4;:12;;35785:4;35777:12;35773:1681;;35820:2;35813:9;;;;;;35773:1681;35890:4;:12;;35898:4;35890:12;35886:1568;;35933:2;35926:9;;;;;;35886:1568;36004:4;:12;;36012:4;36004:12;36000:1454;;36047:2;36040:9;;;;;;36000:1454;36196:4;:12;;36204:4;36196:12;36192:1262;;-1:-1:-1;;;36240:7:144;;;36232:16;;36192:1262;36317:4;:12;;36325:4;36317:12;36313:1141;;-1:-1:-1;;;36361:7:144;;;36353:16;;36313:1141;36437:4;:12;;36445:4;36437:12;36433:1021;;-1:-1:-1;;;36481:7:144;;;36473:16;;36433:1021;36558:4;:12;;36566:4;36558:12;36554:900;;-1:-1:-1;;;36602:7:144;;;36594:16;;36554:900;36678:4;:12;;36686:4;36678:12;36674:780;;-1:-1:-1;;;36722:7:144;;;36714:16;;36674:780;36797:4;:12;;36805:4;36797:12;36793:661;;-1:-1:-1;;;36841:7:144;;;36833:16;;36793:661;36917:4;:12;;36925:4;36917:12;36913:541;;-1:-1:-1;;;36961:7:144;;;36953:16;;36913:541;37037:4;:12;;37045:4;37037:12;37033:421;;-1:-1:-1;;;37082:7:144;;;37080:10;37073:17;;37033:421;37159:4;:12;;37167:4;37159:12;37155:299;;37220:2;37202:21;;37208:2;37202:21;;;:29;;37230:1;37202:29;;;37226:1;37202:29;37195:36;;;;;;;;37155:299;37301:4;:12;;37309:4;37301:12;37297:157;;37349:2;37344:7;;:2;:7;;;:15;;37358:1;37344:15;;37297:157;37406:29;;;;;2878:2:310;37406:29:144;;;2860:21:310;2917:2;2897:18;;;2890:30;2956:21;2936:18;;;2929:49;2995:18;;37406:29:144;2676:343:310;37297:157:144;32684:4784;32634:8490;;;37524:6;:14;;37534:4;37524:14;37520:3590;;37583:4;37576:11;;37658:3;37650:11;;;37646:549;;-1:-1:-1;;;37703:21:144;;;37689:36;;37646:549;37810:4;:12;;37818:4;37810:12;:28;;;;37826:4;:12;;37834:4;37826:12;37810:28;37806:389;;;37870:4;:12;;37878:4;37870:12;37866:83;;37919:3;;;37866:83;37974:8;38012:127;38024:10;38019:15;;:20;38012:127;;38104:8;38071:3;38104:8;;;;;38071:3;38012:127;;;38171:1;-1:-1:-1;38164:8:144;;-1:-1:-1;;38164:8:144;37520:3590;38262:6;:14;;38272:4;38262:14;38258:2852;;-1:-1:-1;;38307:8:144;38313:2;38307:8;;;;38300:15;;38258:2852;38382:6;:14;;38392:4;38382:14;38378:2732;;38427:42;38445:2;38450:1;38445:6;38455:1;38444:12;38439:2;:17;38431:26;;:3;:26;;;;38461:4;38430:35;38467:1;38427:2;:42::i;:::-;38420:49;;;;;38378:2732;38536:6;:14;;38546:4;38536:14;38532:2578;;38581:45;38599:2;38604:1;38599:6;38609:1;38598:12;38593:2;:17;38585:26;;:3;:26;;;;38615:6;38584:37;38623:2;38581;:45::i;38532:2578::-;38694:6;:14;;38704:4;38694:14;38690:2420;;-1:-1:-1;;38745:21:144;38764:1;38759;38754:6;;38753:12;38745:21;;38802:36;;;38873:5;38868:10;;38745:21;;;;;38867:18;38860:25;;38690:2420;38952:6;:14;;38962:4;38952:14;38948:2162;;38997:3;38990:10;;;;;38948:2162;39068:6;:14;;39078:4;39068:14;39064:2046;;39128:2;39133:1;39128:6;39138:1;39127:12;39122:2;:17;39114:26;;:3;:26;;;;39144:4;39113:35;39106:42;;;;;39064:2046;39217:6;:14;;39227:4;39217:14;39213:1897;;39277:2;39282:1;39277:6;39287:1;39276:12;39271:2;:17;39263:26;;:3;:26;;;;39293:6;39262:37;39255:44;;;;;39213:1897;39368:6;:14;;39378:4;39368:14;39364:1746;;-1:-1:-1;;39419:26:144;39443:1;39438;39433:6;;39432:12;39427:2;:17;39419:26;;39481:41;;;39557:5;39552:10;;39419:26;;;;;39551:18;39544:25;;39364:1746;39637:6;:14;;39647:4;39637:14;39633:1477;;-1:-1:-1;;39694:4:144;39688:34;39720:1;39715;39710:6;;39709:12;39704:2;:17;39688:34;;39778:27;;;39758:48;;;39836:10;;39689:9;;;39688:34;;39835:18;39828:25;;39633:1477;39921:6;:14;;39931:4;39921:14;39917:1193;;-1:-1:-1;;39978:6:144;39972:36;40006:1;40001;39996:6;;39995:12;39990:2;:17;39972:36;;40064:29;;;40044:50;;;40124:10;;39973:11;;;39972:36;;40123:18;40116:25;;39917:1193;40210:6;:14;;40220:4;40210:14;40206:904;;-1:-1:-1;;40261:20:144;40279:1;40274;40269:6;;40268:12;40261:20;;40317:36;;;40389:5;40383:11;;40261:20;;;;;40382:19;40375:26;;40206:904;40469:6;:14;;40479:4;40469:14;40465:645;;40514:2;40507:9;;;;;40465:645;40585:6;:14;;40595:4;40585:14;40581:529;;-1:-1:-1;;40636:25:144;40659:1;40654;40649:6;;40648:12;40643:2;:17;40636:25;;40697:41;;;40774:5;40768:11;;40636:25;;;;;40767:19;40760:26;;40581:529;40853:6;:14;;40863:4;40853:14;40849:261;;40898:3;40891:10;;;;;40849:261;40968:6;:14;;40978:4;40968:14;40964:146;;41013:2;41006:9;;;32450:8733;;;;;;;:::o;19960:782::-;20046:12;20133:18;;:::i;:::-;-1:-1:-1;20201:4:144;20308:2;20296:14;;;;20288:41;;;;;;;3226:2:310;20288:41:144;;;3208:21:310;3265:2;3245:18;;;3238:30;3304:16;3284:18;;;3277:44;3338:18;;20288:41:144;3024:338:310;20288:41:144;20425:14;;;;;;;:30;;;20443:12;20425:30;20421:102;;;20504:4;20475:5;:15;;;20491:9;20475:26;;;;;;;;;:::i;:::-;:33;;;;:26;;;;;;:33;20421:102;20578:12;;;;;20567:23;;;;:8;;;:23;20634:1;20619:16;;;20604:31;;;20712:13;:11;:13::i;5582:7764::-;5646:12;5732:18;;:::i;:::-;-1:-1:-1;5910:15:144;;:18;;;;5800:4;6070:18;;;;6114;;;;6158;;;;;5800:4;;5890:17;;;;6070:18;6114;6248;;;6262:4;6248:18;6244:6792;;6298:2;6327:4;6322:9;;:14;6318:144;;6438:4;6433:9;;6425:4;:18;6419:24;6318:144;6483:2;:7;;6489:1;6483:7;6479:161;;6519:10;;;;;6551:16;;;;;;;;6519:10;-1:-1:-1;6479:161:144;;;6619:2;6614:7;;6479:161;6268:386;6244:6792;;;6756:10;:18;;6770:4;6756:18;6752:6284;;1745:10;6794:14;;6752:6284;;;6892:10;:18;;6906:4;6892:18;6888:6148;;6935:1;6930:6;;6888:6148;;;7060:10;:18;;7074:4;7060:18;7056:5980;;7113:4;7098:12;;;:19;7135:26;;;:14;;;:26;7186:13;:11;:13::i;:::-;7179:20;5582:7764;-1:-1:-1;;;;;;;;;5582:7764:144:o;7056:5980::-;7325:10;:18;;7339:4;7325:18;7321:5715;;7476:14;;;7472:2723;7321:5715;7472:2723;7646:22;;;;;7642:2553;;7771:10;7784:27;7792:2;7797:10;7792:15;7809:1;7784:7;:27::i;:::-;7895:17;;;;7771:40;;-1:-1:-1;7895:17:144;7873:19;8045:14;8064:1;8039:26;8035:146;;1676:4:145;1670:11;;1533:21;1787:15;;;1828:8;1822:4;1815:22;1850:27;;;1996:4;1983:18;;2098:17;;2003:19;1979:44;2025:11;1976:61;8093:65:144;;8035:146;8267:20;;;;;8234:54;;;;;;;;3540:25:310;;;8234:54:144;3601:23:310;;;3581:18;;;3574:51;8203:11:144;;;;8234:19;:6;:19;;;;3513:18:310;;8234:54:144;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8202:86;;;;8515:1;8511:2;8507:10;8612:9;8609:1;8605:17;8694:6;8687:5;8684:17;8681:40;;;8714:5;8704:15;;8681:40;;8797:6;8793:2;8790:14;8787:34;;;8817:2;8807:12;;8787:34;8923:3;8918:1;8910:6;8906:14;8901:3;8897:24;8893:34;8886:41;;9023:3;9019:1;9007:9;8998:6;8995:1;8991:14;8987:30;8983:38;8979:48;8972:55;;9178:1;9174;9170;9158:9;9155:1;9151:17;9147:25;9143:33;9139:41;9305:1;9301;9297;9288:6;9276:9;9273:1;9269:17;9265:30;9261:38;9257:46;9253:54;9235:72;;9436:10;9432:15;9426:4;9422:26;9414:34;;9552:3;9544:4;9540:9;9535:3;9531:19;9528:28;9521:35;;;;9698:33;9707:2;9712:10;9707:15;9724:1;9727:3;9698:8;:33::i;:::-;9753:20;;;:38;;;;;;;;;-1:-1:-1;7642:2553:144;;-1:-1:-1;;;7642:2553:144;;9910:18;;;;;9906:289;;10080:2;10075:7;;7321:5715;;9906:289;10134:10;10129:15;;2053:3;10166:10;;9906:289;7321:5715;;;10324:10;:18;;10338:4;10324:18;10320:2716;;10478:15;;;1824:1;10478:15;;:34;;-1:-1:-1;10497:15:144;;;1859:1;10497:15;10478:34;:57;;;-1:-1:-1;10516:19:144;;;1936:1;10516:19;10478:57;10474:1593;;;10564:2;10559:7;;10320:2716;;10474:1593;10690:23;;;;;10686:1381;;10737:10;10750:27;10758:2;10763:10;10758:15;10775:1;10750:7;:27::i;:::-;10853:17;;;;10737:40;;-1:-1:-1;11096:1:144;11088:10;;11190:1;11186:17;11265:13;;;11262:32;;;11287:5;11281:11;;11262:32;11573:14;;;11379:1;11569:22;;;11565:32;;;;11462:26;11486:1;11371:10;;;11466:18;;;11462:26;11561:43;11367:20;;11669:12;11797:17;;;:23;11865:1;11842:20;;;:24;11375:2;-1:-1:-1;11375:2:144;7321:5715;;10320:2716;12269:10;:18;;12283:4;12269:18;12265:771;;12379:2;:7;;12385:1;12379:7;12375:647;;12472:14;;;;;:40;;-1:-1:-1;12490:22:144;;;1978:1;12490:22;12472:40;:62;;;-1:-1:-1;12516:18:144;;;1897:1;12516:18;12472:62;12468:404;;;12567:1;12562:6;;12375:647;;12468:404;12613:15;;;1824:1;12613:15;;:34;;-1:-1:-1;12632:15:144;;;1859:1;12632:15;12613:34;:61;;;-1:-1:-1;12651:23:144;;;2021:1;12651:23;12613:61;:84;;;-1:-1:-1;12678:19:144;;;1936:1;12678:19;12613:84;12609:263;;;12730:1;12725:6;;7321:5715;;12375:647;12923:10;12918:15;;2087:4;12955:11;;12375:647;13111:15;;;;;:23;;;;:18;;;;:23;;;;13148:15;;:23;;;:18;;;;:23;-1:-1:-1;13237:12:144;;;;13226:23;;;:8;;;:23;13293:1;13278:16;13263:31;;;;;13316:13;:11;:13::i;16084:2480::-;16178:12;16264:18;;:::i;:::-;-1:-1:-1;16332:4:144;16364:10;16472:13;;;16481:4;16472:13;16468:1705;;-1:-1:-1;16511:8:144;;;;16468:1705;;;16630:5;:13;;16639:4;16630:13;16626:1547;;16663:14;;;:8;;;:14;16626:1547;;;16793:5;:13;;16802:4;16793:13;16789:1384;;-1:-1:-1;16832:8:144;;;;16789:1384;;;16951:5;:13;;16960:4;16951:13;16947:1226;;16984:14;;;:8;;;:14;16947:1226;;;17125:5;:13;;17134:4;17125:13;17121:1052;;17252:9;17198:17;17178;;;17198;;;;17178:37;17259:2;17252:9;;;;;17234:8;;;:28;17280:22;:8;;;:22;17121:1052;;;17439:5;:13;;17448:4;17439:13;17435:738;;17506:11;17492;;;17506;;;17492:25;17561:2;17554:9;;;;;17536:8;;;:28;17582:22;:8;;;:22;17435:738;;;17763:5;:13;;17772:4;17763:13;17759:414;;17833:3;17814:23;;17820:3;17814:23;;;;;;;:::i;:::-;;17796:42;;:8;;;:42;17874:23;;;;;;;;;;;;;:::i;:::-;;17856:42;;:8;;;:42;17759:414;;;18067:5;:13;;18076:4;18067:13;18063:110;;18117:3;18111:9;;:3;:9;;;;;;;:::i;:::-;;18100:20;;;;:8;;;:20;18149:9;;;;;;;;;;;:::i;:::-;;18138:20;;:8;;;:20;18063:110;18266:14;;;;18262:85;;18329:3;18300:5;:15;;;18316:9;18300:26;;;;;;;;;:::i;:::-;:32;;;;:26;;;;;;:32;18262:85;18401:12;;;;;18390:23;;;;:8;;;:23;18457:1;18442:16;;;18427:31;;;18534:13;:11;:13::i;:::-;18527:20;16084:2480;-1:-1:-1;;;;;;;16084:2480:144:o;23913:1654::-;24089:14;24106:24;24118:11;24106;:24::i;:::-;24089:41;;24238:1;24231:5;24227:13;24224:33;;;24253:1;24250;24243:12;24224:33;24392:2;24586:15;;;24411:2;24400:14;;24388:10;24384:31;24381:1;24377:39;24542:16;;;24327:20;;24527:10;24516:22;;;24512:27;24502:38;24499:60;25028:5;25025:1;25021:13;25099:1;25084:343;25109:2;25106:1;25103:9;25084:343;;;25232:2;25220:15;;;25169:20;25267:12;;;25281:1;25263:20;25304:42;;;;25372:1;25367:42;;;;25256:153;;25304:42;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;25313:31;;25304:42;;25367;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;25376:31;;25256:153;-1:-1:-1;;25127:1:144;25120:9;25084:343;;;-1:-1:-1;;25526:4:144;25519:18;-1:-1:-1;;;;23913:1654:144:o;20946:586::-;21268:20;;;21292:7;21268:32;21261:3;:40;;;21374:14;;21429:17;;21423:24;;;21415:72;;;;;;;4277:2:310;21415:72:144;;;4259:21:310;4316:2;4296:18;;;4289:30;4355:34;4335:18;;;4328:62;4426:5;4406:18;;;4399:33;4449:19;;21415:72:144;4075:399:310;21415:72:144;21501:14;20946:586;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;467:347:310:-;518:8;528:6;582:3;575:4;567:6;563:17;559:27;549:55;;600:1;597;590:12;549:55;-1:-1:-1;623:20:310;;666:18;655:30;;652:50;;;698:1;695;688:12;652:50;735:4;727:6;723:17;711:29;;787:3;780:4;771:6;763;759:19;755:30;752:39;749:59;;;804:1;801;794:12;749:59;467:347;;;;;:::o;819:785::-;918:6;926;934;942;950;1003:2;991:9;982:7;978:23;974:32;971:52;;;1019:1;1016;1009:12;971:52;1059:9;1046:23;1088:18;1129:2;1121:6;1118:14;1115:34;;;1145:1;1142;1135:12;1115:34;1184:58;1234:7;1225:6;1214:9;1210:22;1184:58;:::i;:::-;1261:8;;-1:-1:-1;1158:84:310;-1:-1:-1;1349:2:310;1334:18;;1321:32;;-1:-1:-1;1365:16:310;;;1362:36;;;1394:1;1391;1384:12;1362:36;;1433:60;1485:7;1474:8;1463:9;1459:24;1433:60;:::i;:::-;819:785;;;;-1:-1:-1;1512:8:310;1594:2;1579:18;1566:32;;819:785;-1:-1:-1;;;;819:785:310:o;1791:184::-;1843:77;1840:1;1833:88;1940:4;1937:1;1930:15;1964:4;1961:1;1954:15;3636:245;3715:6;3723;3776:2;3764:9;3755:7;3751:23;3747:32;3744:52;;;3792:1;3789;3782:12;3744:52;-1:-1:-1;;3815:16:310;;3871:2;3856:18;;;3850:25;3815:16;;3850:25;;-1:-1:-1;3636:245:310:o;3886:184::-;3938:77;3935:1;3928:88;4035:4;4032:1;4025:15;4059:4;4056:1;4049:15" +var MIPSDeployedSourceMap = "1131:40054:144:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1710:45;;1745:10;1710:45;;;;;188:10:319;176:23;;;158:42;;146:2;131:18;1710:45:144;;;;;;;;2448:99;;;412:42:319;2534:6:144;400:55:319;382:74;;370:2;355:18;2448:99:144;211:251:319;26025:6379:144;;;;;;:::i;:::-;;:::i;:::-;;;1755:25:319;;;1743:2;1728:18;26025:6379:144;1609:177:319;26025:6379:144;26128:7;26171:18;;:::i;:::-;26318:4;26311:5;26308:15;26298:134;;26412:1;26409;26402:12;26298:134;26468:4;26462:11;26475:10;26459:27;26449:136;;26565:1;26562;26555:12;26449:136;26634:3;26615:17;26612:26;26602:151;;26733:1;26730;26723:12;26602:151;26798:3;26783:13;26780:22;26770:146;;26896:1;26893;26886:12;26770:146;27176:24;;27521:4;27222:20;27579:2;27280:21;;27176:24;27338:18;27222:20;27280:21;;;27176:24;27153:21;27149:52;;;27338:18;27222:20;;;27280:21;;;27176:24;27149:52;;27222:20;;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;;27338:18;27222:20;27280:21;;;27176:24;27153:21;27149:52;;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;28197:10;27338:18;28187:21;;;27280;;;;28295:1;28280:77;28305:2;28302:1;28299:9;28280:77;;;27176:24;;27153:21;27149:52;27222:20;;28353:1;27280:21;;;;27164:2;27338:18;;;;28323:1;28316:9;28280:77;;;28284:14;;;28435:5;:12;;;28431:71;;;28474:13;:11;:13::i;:::-;28467:20;;;;;28431:71;28516:10;;;:15;;28530:1;28516:15;;;;;28601:8;;;;-1:-1:-1;;28593:20:144;;-1:-1:-1;28593:7:144;:20::i;:::-;28579:34;-1:-1:-1;28643:10:144;28651:2;28643:10;;;;28720:1;28710:11;;;:26;;;28725:6;:11;;28735:1;28725:11;28710:26;28706:310;;;28866:13;28935:1;28913:4;28920:10;28913:17;28912:24;;;;28883:5;:12;;;28898:10;28883:25;28882:54;28866:70;;28961:40;28972:6;:11;;28982:1;28972:11;:20;;28990:2;28972:20;;;28986:1;28972:20;28961:40;;28994:6;28961:10;:40::i;:::-;28954:47;;;;;;;;28706:310;29265:15;;;;29060:9;;;;29197:4;29191:2;29183:10;;;29182:19;;;29265:15;29290:2;29282:10;;;29281:19;29265:36;;;;;;;:::i;:::-;;;;;;-1:-1:-1;29330:5:144;29354:11;;;;;:29;;;29369:6;:14;;29379:4;29369:14;29354:29;29350:832;;;29446:5;:15;;;29462:5;29446:22;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;29509:4:144;29503:2;29495:10;;;29494:19;29350:832;;;29547:4;29538:6;:13;;;29534:648;;;29668:6;:13;;29678:3;29668:13;:30;;;;29685:6;:13;;29695:3;29685:13;29668:30;:47;;;;29702:6;:13;;29712:3;29702:13;29668:47;29664:253;;;29778:4;29785:6;29778:13;29773:18;;29534:648;;29664:253;29877:21;29880:4;29887:6;29880:13;29895:2;29877;:21::i;:::-;29872:26;;29534:648;;;29951:4;29941:6;:14;;;;:32;;;;29959:6;:14;;29969:4;29959:14;29941:32;:50;;;;29977:6;:14;;29987:4;29977:14;29941:50;29937:245;;;30061:5;:15;;;30077:5;30061:22;;;;;;;;;:::i;:::-;;;;;30056:27;;30162:5;30154:13;;29937:245;30211:1;30201:6;:11;;;;:25;;;;;30225:1;30216:6;:10;;;30201:25;30200:42;;;;30231:6;:11;;30241:1;30231:11;30200:42;30196:125;;;30269:37;30282:6;30290:4;30296:5;30303:2;30269:12;:37::i;:::-;30262:44;;;;;;;;;;;30196:125;30354:13;30335:16;30506:4;30496:14;;;;30492:446;;30575:21;30578:4;30585:6;30578:13;30593:2;30575;:21::i;:::-;30569:27;;;;30633:10;30628:15;;30667:16;30628:15;30681:1;30667:7;:16::i;:::-;30661:22;;30715:4;30705:6;:14;;;;:32;;;;;30723:6;:14;;30733:4;30723:14;;30705:32;30701:223;;;30802:4;30790:16;;30904:1;30896:9;;30701:223;30512:426;30492:446;30971:10;30984:26;30992:4;30998:2;31002;31006:3;30984:7;:26::i;:::-;31013:10;30984:39;;;;-1:-1:-1;31109:4:144;31102:11;;;31141;;;:24;;;;;31164:1;31156:4;:9;;;;31141:24;:39;;;;;31176:4;31169;:11;;;31141:39;31137:860;;;31204:4;:9;;31212:1;31204:9;:22;;;;31217:4;:9;;31225:1;31217:9;31204:22;31200:144;;;31288:37;31299:4;:9;;31307:1;31299:9;:21;;31315:5;31299:21;;;31311:1;31299:21;31322:2;31288:10;:37::i;:::-;31281:44;;;;;;;;;;;;;;;31200:144;31366:4;:11;;31374:3;31366:11;31362:121;;31436:28;31445:5;31452:2;31456:7;;;;31436:8;:28::i;31362:121::-;31504:4;:11;;31512:3;31504:11;31500:121;;31574:28;31583:5;31590:2;31594:7;;;;;31574:8;:28::i;31500:121::-;31691:4;:11;;31699:3;31691:11;31687:93;;31733:28;31747:13;31733;:28::i;31687:93::-;31883:4;31875;:12;;;;:27;;;;;31898:4;31891;:11;;;31875:27;31871:112;;;31933:31;31944:4;31950:2;31954;31958:5;31933:10;:31::i;31871:112::-;32057:6;:14;;32067:4;32057:14;:28;;;;-1:-1:-1;32075:10:144;;;;;32057:28;32053:93;;;32130:1;32105:5;:15;;;32121:5;32105:22;;;;;;;;;:::i;:::-;:26;;;;:22;;;;;;:26;32053:93;32192:9;:26;;32205:13;32192:26;32188:92;;32238:27;32247:9;32258:1;32261:3;32238:8;:27::i;:::-;32361:26;32370:5;32377:3;32382:4;32361:8;:26::i;:::-;32354:33;;;;;;;;;;;;;26025:6379;;;;;;;;:::o;3087:2334::-;3634:4;3628:11;;3550:4;3353:31;3342:43;;3413:13;3353:31;3752:2;3452:13;;3342:43;3359:24;3353:31;3452:13;;;3342:43;;;;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3413:13;4180:11;3359:24;3353:31;3452:13;;;3342:43;3413:13;4275:11;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3128:12;;4415:13;;3628:11;;3452:13;;;;4180:11;3128:12;4495:84;4520:2;4517:1;4514:9;4495:84;;;3369:13;3359:24;;3353:31;3342:43;;3373:2;3413:13;;;;4575:1;3452:13;;;;4538:1;4531:9;4495:84;;;4499:14;4642:1;4638:2;4631:13;4737:5;4733:2;4729:14;4722:5;4717:27;4811:1;4797:15;;4832:6;4856:1;4851:273;;;;5191:1;5181:11;;4825:369;;4851:273;4883:8;4941:22;;;;5020:1;5015:22;;;;5107:1;5097:11;;4876:234;;4941:22;4960:1;4950:11;;4941:22;;5015;5034:1;5024:11;;4876:234;;4825:369;-1:-1:-1;;;5317:14:144;;;5300:32;;5360:19;5356:30;5392:3;5388:16;;;;5353:52;;3087:2334;-1:-1:-1;3087:2334:144:o;21746:1831::-;21819:11;21930:14;21947:24;21959:11;21947;:24::i;:::-;21930:41;;22079:1;22072:5;22068:13;22065:33;;;22094:1;22091;22084:12;22065:33;22227:2;22215:15;;;22168:20;22657:5;22654:1;22650:13;22692:4;22728:1;22713:343;22738:2;22735:1;22732:9;22713:343;;;22861:2;22849:15;;;22798:20;22896:12;;;22910:1;22892:20;22933:42;;;;23001:1;22996:42;;;;22885:153;;22933:42;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;22942:31;;22933:42;;22996;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;23005:31;;22885:153;-1:-1:-1;;22756:1:144;22749:9;22713:343;;;22717:14;23166:4;23160:11;23145:26;;23252:7;23246:4;23243:17;23233:124;;23294:10;23291:1;23284:21;23336:2;23333:1;23326:13;23233:124;-1:-1:-1;;23484:2:144;23473:14;;;;23461:10;23457:31;23454:1;23450:39;23518:16;;;;23536:10;23514:33;;21746:1831;-1:-1:-1;;;21746:1831:144:o;18856:823::-;18925:12;19012:18;;:::i;:::-;19080:4;19071:13;;19132:5;:8;;;19143:1;19132:12;19116:28;;:5;:12;;;:28;;;19112:95;;19164:28;;;;;2182:2:319;19164:28:144;;;2164:21:319;2221:2;2201:18;;;2194:30;2260:20;2240:18;;;2233:48;2298:18;;19164:28:144;;;;;;;;19112:95;19296:8;;;;;19329:12;;;;;19318:23;;;;;;;19355:20;;;;;19296:8;19487:13;;;19483:90;;19548:6;19557:1;19548:10;19520:5;:15;;;19536:8;19520:25;;;;;;;;;:::i;:::-;:38;;;;:25;;;;;;:38;19483:90;19649:13;:11;:13::i;2645:339::-;2706:11;2770:18;;;;2779:8;;;;2770:18;;;;;;2769:25;;;;;2786:1;2833:2;:9;;;2827:16;;;;;2826:22;;2825:32;;;;;;;2887:9;;2886:15;2769:25;2944:21;;2964:1;2944:21;;;2955:6;2944:21;2929:11;;;;;:37;;-1:-1:-1;;;2645:339:144;;;;:::o;13732:2026::-;13829:12;13915:18;;:::i;:::-;13983:4;13974:13;;14015:17;14075:5;:8;;;14086:1;14075:12;14059:28;;:5;:12;;;:28;;;14055:97;;14107:30;;;;;2529:2:319;14107:30:144;;;2511:21:319;2568:2;2548:18;;;2541:30;2607:22;2587:18;;;2580:50;2647:18;;14107:30:144;2327:344:319;14055:97:144;14222:7;:12;;14233:1;14222:12;:28;;;;14238:7;:12;;14249:1;14238:12;14222:28;14218:947;;;14270:9;14282:5;:15;;;14298:6;14282:23;;;;;;;;;:::i;:::-;;;;;14270:35;;14346:2;14339:9;;:3;:9;;;:25;;;;;14352:7;:12;;14363:1;14352:12;14339:25;14338:58;;;;14377:2;14370:9;;:3;:9;;;;:25;;;;;14383:7;:12;;14394:1;14383:12;14370:25;14323:73;;14252:159;14218:947;;;14508:7;:12;;14519:1;14508:12;14504:661;;14569:1;14561:3;14555:15;;;;14540:30;;14504:661;;;14673:7;:12;;14684:1;14673:12;14669:496;;14733:1;14726:3;14720:14;;;14705:29;;14669:496;;;14854:7;:12;;14865:1;14854:12;14850:315;;14942:4;14936:2;14927:11;;;14926:20;14912:10;14969:8;;;14965:84;;15029:1;15022:3;15016:14;;;15001:29;;14965:84;15070:3;:8;;15077:1;15070:8;15066:85;;15131:1;15123:3;15117:15;;;;15102:30;;15066:85;14868:297;14850:315;15241:8;;;;;15319:12;;;;15308:23;;;;;15475:178;;;;15566:1;15540:22;15543:5;15551:6;15543:14;15559:2;15540;:22::i;:::-;:27;;;;;;;15526:42;;15535:1;15526:42;15511:57;:12;;;:57;15475:178;;;15622:12;;;;;15637:1;15622:16;15607:31;;;;15475:178;15728:13;:11;:13::i;:::-;15721:20;13732:2026;-1:-1:-1;;;;;;;;13732:2026:144:o;32450:8733::-;32537:10;32599;32607:2;32599:10;;;;32638:11;;;:44;;;32664:1;32654:6;:11;;;;:27;;;;;32678:3;32669:6;:12;;;32654:27;32634:8490;;;32723:4;32716:11;;32847:6;32907:3;32902:25;;;;32982:3;32977:25;;;;33056:3;33051:25;;;;33131:3;33126:25;;;;33205:3;33200:25;;;;33278:3;33273:25;;;;33352:3;33347:25;;;;32840:532;;32902:25;32921:4;32913:12;;32902:25;;32977;32996:4;32988:12;;32977:25;;33051;33070:4;33062:12;;33051:25;;33126;33145:4;33137:12;;33126:25;;33200;33219:4;33211:12;;33200:25;;33273;33292:4;33284:12;;33273:25;;33347;33366:4;33358:12;;32840:532;;33435:4;:12;;33443:4;33435:12;33431:4023;;-1:-1:-1;;;33486:9:144;33478:26;;33499:4;33494:1;33486:9;;;33485:18;33478:26;33471:33;;33431:4023;33572:4;:12;;33580:4;33572:12;33568:3886;;-1:-1:-1;;;33623:9:144;33615:26;;33636:4;33631:1;33623:9;;;33622:18;33615:26;33608:33;;33568:3886;33709:4;:12;;33717:4;33709:12;33705:3749;;33774:4;33769:1;33761:9;;;33760:18;33807:27;33761:9;33810:11;;;;33823:2;:10;;;33807:2;:27::i;:::-;33800:34;;;;;;;33705:3749;33903:4;:12;;33911:4;33903:12;33899:3555;;-1:-1:-1;;;33946:17:144;;;33958:4;33953:9;;33946:17;33939:24;;33899:3555;34032:4;:11;;34040:3;34032:11;34028:3426;;-1:-1:-1;;;34074:17:144;;;34086:4;34081:9;;34074:17;34067:24;;34028:3426;34160:4;:12;;34168:4;34160:12;34156:3298;;34203:21;34212:2;34206:8;;:2;:8;;;;34221:2;34216;:7;34203:2;:21::i;:::-;34196:28;;;;;;34156:3298;34473:4;:12;;34481:4;34473:12;34469:2985;;34516:2;34509:9;;;;;;34469:2985;34587:4;:12;;34595:4;34587:12;34583:2871;;34630:2;34623:9;;;;;;34583:2871;34701:4;:12;;34709:4;34701:12;34697:2757;;34744:2;34737:9;;;;;;34697:2757;34815:4;:12;;34823:4;34815:12;34811:2643;;34858:2;34851:9;;;;;;34811:2643;34932:4;:12;;34940:4;34932:12;34928:2526;;34975:2;34968:9;;;;;;34928:2526;35092:4;:12;;35100:4;35092:12;35088:2366;;35135:2;35128:9;;;;;;35088:2366;35206:4;:12;;35214:4;35206:12;35202:2252;;35249:2;35242:9;;;;;;35202:2252;35320:4;:12;;35328:4;35320:12;35316:2138;;35363:2;35356:9;;;;;;35316:2138;35434:4;:12;;35442:4;35434:12;35430:2024;;35477:2;35470:9;;;;;;35430:2024;35548:4;:12;;35556:4;35548:12;35544:1910;;35591:2;35584:9;;;;;;35544:1910;35662:4;:12;;35670:4;35662:12;35658:1796;;35705:2;35698:9;;;;;;35658:1796;35777:4;:12;;35785:4;35777:12;35773:1681;;35820:2;35813:9;;;;;;35773:1681;35890:4;:12;;35898:4;35890:12;35886:1568;;35933:2;35926:9;;;;;;35886:1568;36004:4;:12;;36012:4;36004:12;36000:1454;;36047:2;36040:9;;;;;;36000:1454;36196:4;:12;;36204:4;36196:12;36192:1262;;-1:-1:-1;;;36240:7:144;;;36232:16;;36192:1262;36317:4;:12;;36325:4;36317:12;36313:1141;;-1:-1:-1;;;36361:7:144;;;36353:16;;36313:1141;36437:4;:12;;36445:4;36437:12;36433:1021;;-1:-1:-1;;;36481:7:144;;;36473:16;;36433:1021;36558:4;:12;;36566:4;36558:12;36554:900;;-1:-1:-1;;;36602:7:144;;;36594:16;;36554:900;36678:4;:12;;36686:4;36678:12;36674:780;;-1:-1:-1;;;36722:7:144;;;36714:16;;36674:780;36797:4;:12;;36805:4;36797:12;36793:661;;-1:-1:-1;;;36841:7:144;;;36833:16;;36793:661;36917:4;:12;;36925:4;36917:12;36913:541;;-1:-1:-1;;;36961:7:144;;;36953:16;;36913:541;37037:4;:12;;37045:4;37037:12;37033:421;;-1:-1:-1;;;37082:7:144;;;37080:10;37073:17;;37033:421;37159:4;:12;;37167:4;37159:12;37155:299;;37220:2;37202:21;;37208:2;37202:21;;;:29;;37230:1;37202:29;;;37226:1;37202:29;37195:36;;;;;;;;37155:299;37301:4;:12;;37309:4;37301:12;37297:157;;37349:2;37344:7;;:2;:7;;;:15;;37358:1;37344:15;;37297:157;37406:29;;;;;2878:2:319;37406:29:144;;;2860:21:319;2917:2;2897:18;;;2890:30;2956:21;2936:18;;;2929:49;2995:18;;37406:29:144;2676:343:319;37297:157:144;32684:4784;32634:8490;;;37524:6;:14;;37534:4;37524:14;37520:3590;;37583:4;37576:11;;37658:3;37650:11;;;37646:549;;-1:-1:-1;;;37703:21:144;;;37689:36;;37646:549;37810:4;:12;;37818:4;37810:12;:28;;;;37826:4;:12;;37834:4;37826:12;37810:28;37806:389;;;37870:4;:12;;37878:4;37870:12;37866:83;;37919:3;;;37866:83;37974:8;38012:127;38024:10;38019:15;;:20;38012:127;;38104:8;38071:3;38104:8;;;;;38071:3;38012:127;;;38171:1;-1:-1:-1;38164:8:144;;-1:-1:-1;;38164:8:144;37520:3590;38262:6;:14;;38272:4;38262:14;38258:2852;;-1:-1:-1;;38307:8:144;38313:2;38307:8;;;;38300:15;;38258:2852;38382:6;:14;;38392:4;38382:14;38378:2732;;38427:42;38445:2;38450:1;38445:6;38455:1;38444:12;38439:2;:17;38431:26;;:3;:26;;;;38461:4;38430:35;38467:1;38427:2;:42::i;:::-;38420:49;;;;;38378:2732;38536:6;:14;;38546:4;38536:14;38532:2578;;38581:45;38599:2;38604:1;38599:6;38609:1;38598:12;38593:2;:17;38585:26;;:3;:26;;;;38615:6;38584:37;38623:2;38581;:45::i;38532:2578::-;38694:6;:14;;38704:4;38694:14;38690:2420;;-1:-1:-1;;38745:21:144;38764:1;38759;38754:6;;38753:12;38745:21;;38802:36;;;38873:5;38868:10;;38745:21;;;;;38867:18;38860:25;;38690:2420;38952:6;:14;;38962:4;38952:14;38948:2162;;38997:3;38990:10;;;;;38948:2162;39068:6;:14;;39078:4;39068:14;39064:2046;;39128:2;39133:1;39128:6;39138:1;39127:12;39122:2;:17;39114:26;;:3;:26;;;;39144:4;39113:35;39106:42;;;;;39064:2046;39217:6;:14;;39227:4;39217:14;39213:1897;;39277:2;39282:1;39277:6;39287:1;39276:12;39271:2;:17;39263:26;;:3;:26;;;;39293:6;39262:37;39255:44;;;;;39213:1897;39368:6;:14;;39378:4;39368:14;39364:1746;;-1:-1:-1;;39419:26:144;39443:1;39438;39433:6;;39432:12;39427:2;:17;39419:26;;39481:41;;;39557:5;39552:10;;39419:26;;;;;39551:18;39544:25;;39364:1746;39637:6;:14;;39647:4;39637:14;39633:1477;;-1:-1:-1;;39694:4:144;39688:34;39720:1;39715;39710:6;;39709:12;39704:2;:17;39688:34;;39778:27;;;39758:48;;;39836:10;;39689:9;;;39688:34;;39835:18;39828:25;;39633:1477;39921:6;:14;;39931:4;39921:14;39917:1193;;-1:-1:-1;;39978:6:144;39972:36;40006:1;40001;39996:6;;39995:12;39990:2;:17;39972:36;;40064:29;;;40044:50;;;40124:10;;39973:11;;;39972:36;;40123:18;40116:25;;39917:1193;40210:6;:14;;40220:4;40210:14;40206:904;;-1:-1:-1;;40261:20:144;40279:1;40274;40269:6;;40268:12;40261:20;;40317:36;;;40389:5;40383:11;;40261:20;;;;;40382:19;40375:26;;40206:904;40469:6;:14;;40479:4;40469:14;40465:645;;40514:2;40507:9;;;;;40465:645;40585:6;:14;;40595:4;40585:14;40581:529;;-1:-1:-1;;40636:25:144;40659:1;40654;40649:6;;40648:12;40643:2;:17;40636:25;;40697:41;;;40774:5;40768:11;;40636:25;;;;;40767:19;40760:26;;40581:529;40853:6;:14;;40863:4;40853:14;40849:261;;40898:3;40891:10;;;;;40849:261;40968:6;:14;;40978:4;40968:14;40964:146;;41013:2;41006:9;;;32450:8733;;;;;;;:::o;19960:782::-;20046:12;20133:18;;:::i;:::-;-1:-1:-1;20201:4:144;20308:2;20296:14;;;;20288:41;;;;;;;3226:2:319;20288:41:144;;;3208:21:319;3265:2;3245:18;;;3238:30;3304:16;3284:18;;;3277:44;3338:18;;20288:41:144;3024:338:319;20288:41:144;20425:14;;;;;;;:30;;;20443:12;20425:30;20421:102;;;20504:4;20475:5;:15;;;20491:9;20475:26;;;;;;;;;:::i;:::-;:33;;;;:26;;;;;;:33;20421:102;20578:12;;;;;20567:23;;;;:8;;;:23;20634:1;20619:16;;;20604:31;;;20712:13;:11;:13::i;5582:7764::-;5646:12;5732:18;;:::i;:::-;-1:-1:-1;5910:15:144;;:18;;;;5800:4;6070:18;;;;6114;;;;6158;;;;;5800:4;;5890:17;;;;6070:18;6114;6248;;;6262:4;6248:18;6244:6792;;6298:2;6327:4;6322:9;;:14;6318:144;;6438:4;6433:9;;6425:4;:18;6419:24;6318:144;6483:2;:7;;6489:1;6483:7;6479:161;;6519:10;;;;;6551:16;;;;;;;;6519:10;-1:-1:-1;6479:161:144;;;6619:2;6614:7;;6479:161;6268:386;6244:6792;;;6756:10;:18;;6770:4;6756:18;6752:6284;;1745:10;6794:14;;6752:6284;;;6892:10;:18;;6906:4;6892:18;6888:6148;;6935:1;6930:6;;6888:6148;;;7060:10;:18;;7074:4;7060:18;7056:5980;;7113:4;7098:12;;;:19;7135:26;;;:14;;;:26;7186:13;:11;:13::i;:::-;7179:20;5582:7764;-1:-1:-1;;;;;;;;;5582:7764:144:o;7056:5980::-;7325:10;:18;;7339:4;7325:18;7321:5715;;7476:14;;;7472:2723;7321:5715;7472:2723;7646:22;;;;;7642:2553;;7771:10;7784:27;7792:2;7797:10;7792:15;7809:1;7784:7;:27::i;:::-;7895:17;;;;7771:40;;-1:-1:-1;7895:17:144;7873:19;8045:14;8064:1;8039:26;8035:146;;1676:4:145;1670:11;;1533:21;1787:15;;;1828:8;1822:4;1815:22;1850:27;;;1996:4;1983:18;;2098:17;;2003:19;1979:44;2025:11;1976:61;8093:65:144;;8035:146;8267:20;;;;;8234:54;;;;;;;;3540:25:319;;;8234:54:144;3601:23:319;;;3581:18;;;3574:51;8203:11:144;;;;8234:19;:6;:19;;;;3513:18:319;;8234:54:144;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8202:86;;;;8515:1;8511:2;8507:10;8612:9;8609:1;8605:17;8694:6;8687:5;8684:17;8681:40;;;8714:5;8704:15;;8681:40;;8797:6;8793:2;8790:14;8787:34;;;8817:2;8807:12;;8787:34;8923:3;8918:1;8910:6;8906:14;8901:3;8897:24;8893:34;8886:41;;9023:3;9019:1;9007:9;8998:6;8995:1;8991:14;8987:30;8983:38;8979:48;8972:55;;9178:1;9174;9170;9158:9;9155:1;9151:17;9147:25;9143:33;9139:41;9305:1;9301;9297;9288:6;9276:9;9273:1;9269:17;9265:30;9261:38;9257:46;9253:54;9235:72;;9436:10;9432:15;9426:4;9422:26;9414:34;;9552:3;9544:4;9540:9;9535:3;9531:19;9528:28;9521:35;;;;9698:33;9707:2;9712:10;9707:15;9724:1;9727:3;9698:8;:33::i;:::-;9753:20;;;:38;;;;;;;;;-1:-1:-1;7642:2553:144;;-1:-1:-1;;;7642:2553:144;;9910:18;;;;;9906:289;;10080:2;10075:7;;7321:5715;;9906:289;10134:10;10129:15;;2053:3;10166:10;;9906:289;7321:5715;;;10324:10;:18;;10338:4;10324:18;10320:2716;;10478:15;;;1824:1;10478:15;;:34;;-1:-1:-1;10497:15:144;;;1859:1;10497:15;10478:34;:57;;;-1:-1:-1;10516:19:144;;;1936:1;10516:19;10478:57;10474:1593;;;10564:2;10559:7;;10320:2716;;10474:1593;10690:23;;;;;10686:1381;;10737:10;10750:27;10758:2;10763:10;10758:15;10775:1;10750:7;:27::i;:::-;10853:17;;;;10737:40;;-1:-1:-1;11096:1:144;11088:10;;11190:1;11186:17;11265:13;;;11262:32;;;11287:5;11281:11;;11262:32;11573:14;;;11379:1;11569:22;;;11565:32;;;;11462:26;11486:1;11371:10;;;11466:18;;;11462:26;11561:43;11367:20;;11669:12;11797:17;;;:23;11865:1;11842:20;;;:24;11375:2;-1:-1:-1;11375:2:144;7321:5715;;10320:2716;12269:10;:18;;12283:4;12269:18;12265:771;;12379:2;:7;;12385:1;12379:7;12375:647;;12472:14;;;;;:40;;-1:-1:-1;12490:22:144;;;1978:1;12490:22;12472:40;:62;;;-1:-1:-1;12516:18:144;;;1897:1;12516:18;12472:62;12468:404;;;12567:1;12562:6;;12375:647;;12468:404;12613:15;;;1824:1;12613:15;;:34;;-1:-1:-1;12632:15:144;;;1859:1;12632:15;12613:34;:61;;;-1:-1:-1;12651:23:144;;;2021:1;12651:23;12613:61;:84;;;-1:-1:-1;12678:19:144;;;1936:1;12678:19;12613:84;12609:263;;;12730:1;12725:6;;7321:5715;;12375:647;12923:10;12918:15;;2087:4;12955:11;;12375:647;13111:15;;;;;:23;;;;:18;;;;:23;;;;13148:15;;:23;;;:18;;;;:23;-1:-1:-1;13237:12:144;;;;13226:23;;;:8;;;:23;13293:1;13278:16;13263:31;;;;;13316:13;:11;:13::i;16084:2480::-;16178:12;16264:18;;:::i;:::-;-1:-1:-1;16332:4:144;16364:10;16472:13;;;16481:4;16472:13;16468:1705;;-1:-1:-1;16511:8:144;;;;16468:1705;;;16630:5;:13;;16639:4;16630:13;16626:1547;;16663:14;;;:8;;;:14;16626:1547;;;16793:5;:13;;16802:4;16793:13;16789:1384;;-1:-1:-1;16832:8:144;;;;16789:1384;;;16951:5;:13;;16960:4;16951:13;16947:1226;;16984:14;;;:8;;;:14;16947:1226;;;17125:5;:13;;17134:4;17125:13;17121:1052;;17252:9;17198:17;17178;;;17198;;;;17178:37;17259:2;17252:9;;;;;17234:8;;;:28;17280:22;:8;;;:22;17121:1052;;;17439:5;:13;;17448:4;17439:13;17435:738;;17506:11;17492;;;17506;;;17492:25;17561:2;17554:9;;;;;17536:8;;;:28;17582:22;:8;;;:22;17435:738;;;17763:5;:13;;17772:4;17763:13;17759:414;;17833:3;17814:23;;17820:3;17814:23;;;;;;;:::i;:::-;;17796:42;;:8;;;:42;17874:23;;;;;;;;;;;;;:::i;:::-;;17856:42;;:8;;;:42;17759:414;;;18067:5;:13;;18076:4;18067:13;18063:110;;18117:3;18111:9;;:3;:9;;;;;;;:::i;:::-;;18100:20;;;;:8;;;:20;18149:9;;;;;;;;;;;:::i;:::-;;18138:20;;:8;;;:20;18063:110;18266:14;;;;18262:85;;18329:3;18300:5;:15;;;18316:9;18300:26;;;;;;;;;:::i;:::-;:32;;;;:26;;;;;;:32;18262:85;18401:12;;;;;18390:23;;;;:8;;;:23;18457:1;18442:16;;;18427:31;;;18534:13;:11;:13::i;:::-;18527:20;16084:2480;-1:-1:-1;;;;;;;16084:2480:144:o;23913:1654::-;24089:14;24106:24;24118:11;24106;:24::i;:::-;24089:41;;24238:1;24231:5;24227:13;24224:33;;;24253:1;24250;24243:12;24224:33;24392:2;24586:15;;;24411:2;24400:14;;24388:10;24384:31;24381:1;24377:39;24542:16;;;24327:20;;24527:10;24516:22;;;24512:27;24502:38;24499:60;25028:5;25025:1;25021:13;25099:1;25084:343;25109:2;25106:1;25103:9;25084:343;;;25232:2;25220:15;;;25169:20;25267:12;;;25281:1;25263:20;25304:42;;;;25372:1;25367:42;;;;25256:153;;25304:42;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;25313:31;;25304:42;;25367;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;25376:31;;25256:153;-1:-1:-1;;25127:1:144;25120:9;25084:343;;;-1:-1:-1;;25526:4:144;25519:18;-1:-1:-1;;;;23913:1654:144:o;20946:586::-;21268:20;;;21292:7;21268:32;21261:3;:40;;;21374:14;;21429:17;;21423:24;;;21415:72;;;;;;;4277:2:319;21415:72:144;;;4259:21:319;4316:2;4296:18;;;4289:30;4355:34;4335:18;;;4328:62;4426:5;4406:18;;;4399:33;4449:19;;21415:72:144;4075:399:319;21415:72:144;21501:14;20946:586;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;467:347:319:-;518:8;528:6;582:3;575:4;567:6;563:17;559:27;549:55;;600:1;597;590:12;549:55;-1:-1:-1;623:20:319;;666:18;655:30;;652:50;;;698:1;695;688:12;652:50;735:4;727:6;723:17;711:29;;787:3;780:4;771:6;763;759:19;755:30;752:39;749:59;;;804:1;801;794:12;749:59;467:347;;;;;:::o;819:785::-;918:6;926;934;942;950;1003:2;991:9;982:7;978:23;974:32;971:52;;;1019:1;1016;1009:12;971:52;1059:9;1046:23;1088:18;1129:2;1121:6;1118:14;1115:34;;;1145:1;1142;1135:12;1115:34;1184:58;1234:7;1225:6;1214:9;1210:22;1184:58;:::i;:::-;1261:8;;-1:-1:-1;1158:84:319;-1:-1:-1;1349:2:319;1334:18;;1321:32;;-1:-1:-1;1365:16:319;;;1362:36;;;1394:1;1391;1384:12;1362:36;;1433:60;1485:7;1474:8;1463:9;1459:24;1433:60;:::i;:::-;819:785;;;;-1:-1:-1;1512:8:319;1594:2;1579:18;1566:32;;819:785;-1:-1:-1;;;;819:785:319:o;1791:184::-;1843:77;1840:1;1833:88;1940:4;1937:1;1930:15;1964:4;1961:1;1954:15;3636:245;3715:6;3723;3776:2;3764:9;3755:7;3751:23;3747:32;3744:52;;;3792:1;3789;3782:12;3744:52;-1:-1:-1;;3815:16:319;;3871:2;3856:18;;;3850:25;3815:16;;3850:25;;-1:-1:-1;3636:245:319:o;3886:184::-;3938:77;3935:1;3928:88;4035:4;4032:1;4025:15;4059:4;4056:1;4049:15" func init() { if err := json.Unmarshal([]byte(MIPSStorageLayoutJSON), MIPSStorageLayout); err != nil { diff --git a/boba-bindings/bindings/optimismmintableerc20.go b/boba-bindings/bindings/optimismmintableerc20.go index 46a42003928c..b54b8a325b98 100644 --- a/boba-bindings/bindings/optimismmintableerc20.go +++ b/boba-bindings/bindings/optimismmintableerc20.go @@ -32,7 +32,7 @@ var ( const OptimismMintableERC20ABI = "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REMOTE_TOKEN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"remoteToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]" // OptimismMintableERC20Bin is the compiled bytecode used for deploying new contracts. -var OptimismMintableERC20Bin = "0x6101406040523480156200001257600080fd5b5060405162001ad738038062001ad7833981016040819052620000359162000177565b6001600281858560036200004a8382620002b2565b506004620000598282620002b2565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff16610120526200037e565b80516001600160a01b0381168114620000a557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000d257600080fd5b81516001600160401b0380821115620000ef57620000ef620000aa565b604051601f8301601f19908116603f011681019082821181831017156200011a576200011a620000aa565b816040528381526020925086838588010111156200013757600080fd5b600091505b838210156200015b57858201830151818301840152908201906200013c565b838211156200016d5760008385830101525b9695505050505050565b600080600080600060a086880312156200019057600080fd5b6200019b866200008d565b9450620001ab602087016200008d565b60408701519094506001600160401b0380821115620001c957600080fd5b620001d789838a01620000c0565b94506060880151915080821115620001ee57600080fd5b50620001fd88828901620000c0565b925050608086015160ff811681146200021557600080fd5b809150509295509295909350565b600181811c908216806200023857607f821691505b6020821081036200025957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002ad57600081815260208120601f850160051c81016020861015620002885750805b601f850160051c820191505b81811015620002a95782815560010162000294565b5050505b505050565b81516001600160401b03811115620002ce57620002ce620000aa565b620002e681620002df845462000223565b846200025f565b602080601f8311600181146200031e5760008415620003055750858301515b600019600386901b1c1916600185901b178555620002a9565b600085815260208120601f198616915b828110156200034f578886015182559484019460019091019084016200032e565b50858210156200036e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516116ed620003ea6000396000610244015260008181610317015281816103ac015281816105f101526107cb0152600081816101a9015261033d0152600061075a015260006107310152600061070801526116ed6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" +var OptimismMintableERC20Bin = "0x60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000a" // DeployOptimismMintableERC20 deploys a new Ethereum contract, binding an instance of OptimismMintableERC20 to it. func DeployOptimismMintableERC20(auth *bind.TransactOpts, backend bind.ContractBackend, _bridge libcommon.Address, _remoteToken libcommon.Address, _name string, _symbol string, _decimals uint8) (libcommon.Address, types.Transaction, *OptimismMintableERC20, error) { diff --git a/boba-bindings/bindings/optimismmintableerc20_more.go b/boba-bindings/bindings/optimismmintableerc20_more.go index 98f40184f1b7..5e2af66436c2 100644 --- a/boba-bindings/bindings/optimismmintableerc20_more.go +++ b/boba-bindings/bindings/optimismmintableerc20_more.go @@ -13,7 +13,7 @@ const OptimismMintableERC20StorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\" var OptimismMintableERC20StorageLayout = new(solc.StorageLayout) -var OptimismMintableERC20DeployedBin = "0x608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" +var OptimismMintableERC20DeployedBin = "0x608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(OptimismMintableERC20StorageLayoutJSON), OptimismMintableERC20StorageLayout); err != nil { diff --git a/boba-bindings/bindings/optimismmintableerc20factory.go b/boba-bindings/bindings/optimismmintableerc20factory.go index 6fb930586436..60d12ceedc43 100644 --- a/boba-bindings/bindings/optimismmintableerc20factory.go +++ b/boba-bindings/bindings/optimismmintableerc20factory.go @@ -32,7 +32,7 @@ var ( const OptimismMintableERC20FactoryABI = "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\"}],\"name\":\"OptimismMintableERC20Created\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"StandardL2TokenCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createOptimismMintableERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"name\":\"createOptimismMintableERC20WithDecimals\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createStandardL2Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]" // OptimismMintableERC20FactoryBin is the compiled bytecode used for deploying new contracts. -var OptimismMintableERC20FactoryBin = "0x608060405234801561001057600080fd5b5061001b6000610020565b610118565b600054600390610100900460ff16158015610042575060005460ff8083169116105b6100a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805461010060ff841661ffff19909216821717610100600160b01b03191661ff0019620100006001600160a01b0387160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6123ce806101276000396000f3fe60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e362e3100000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b611ad780620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe6101406040523480156200001257600080fd5b5060405162001ad738038062001ad7833981016040819052620000359162000177565b6001600281858560036200004a8382620002b2565b506004620000598282620002b2565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff16610120526200037e565b80516001600160a01b0381168114620000a557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000d257600080fd5b81516001600160401b0380821115620000ef57620000ef620000aa565b604051601f8301601f19908116603f011681019082821181831017156200011a576200011a620000aa565b816040528381526020925086838588010111156200013757600080fd5b600091505b838210156200015b57858201830151818301840152908201906200013c565b838211156200016d5760008385830101525b9695505050505050565b600080600080600060a086880312156200019057600080fd5b6200019b866200008d565b9450620001ab602087016200008d565b60408701519094506001600160401b0380821115620001c957600080fd5b620001d789838a01620000c0565b94506060880151915080821115620001ee57600080fd5b50620001fd88828901620000c0565b925050608086015160ff811681146200021557600080fd5b809150509295509295909350565b600181811c908216806200023857607f821691505b6020821081036200025957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002ad57600081815260208120601f850160051c81016020861015620002885750805b601f850160051c820191505b81811015620002a95782815560010162000294565b5050505b505050565b81516001600160401b03811115620002ce57620002ce620000aa565b620002e681620002df845462000223565b846200025f565b602080601f8311600181146200031e5760008415620003055750858301515b600019600386901b1c1916600185901b178555620002a9565b600085815260208120601f198616915b828110156200034f578886015182559484019460019091019084016200032e565b50858210156200036e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516116ed620003ea6000396000610244015260008181610317015281816103ac015281816105f101526107cb0152600081816101a9015261033d0152600061075a015260006107310152600061070801526116ed6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a" +var OptimismMintableERC20FactoryBin = "0x608060405234801561001057600080fd5b5061001b6000610020565b610118565b600054600390610100900460ff16158015610042575060005460ff8083169116105b6100a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805461010060ff841661ffff19909216821717610100600160b01b03191661ff0019620100006001600160a01b0387160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b612081806101276000396000f3fe60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e372e3000000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b61178a80620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a" // DeployOptimismMintableERC20Factory deploys a new Ethereum contract, binding an instance of OptimismMintableERC20Factory to it. func DeployOptimismMintableERC20Factory(auth *bind.TransactOpts, backend bind.ContractBackend) (libcommon.Address, types.Transaction, *OptimismMintableERC20Factory, error) { diff --git a/boba-bindings/bindings/optimismmintableerc20factory_more.go b/boba-bindings/bindings/optimismmintableerc20factory_more.go index 7725ed5520f6..28a4ce9fd4ea 100644 --- a/boba-bindings/bindings/optimismmintableerc20factory_more.go +++ b/boba-bindings/bindings/optimismmintableerc20factory_more.go @@ -13,7 +13,7 @@ const OptimismMintableERC20FactoryStorageLayoutJSON = "{\"storage\":[{\"astId\": var OptimismMintableERC20FactoryStorageLayout = new(solc.StorageLayout) -var OptimismMintableERC20FactoryDeployedBin = "0x60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e362e3100000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b611ad780620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe6101406040523480156200001257600080fd5b5060405162001ad738038062001ad7833981016040819052620000359162000177565b6001600281858560036200004a8382620002b2565b506004620000598282620002b2565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff16610120526200037e565b80516001600160a01b0381168114620000a557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000d257600080fd5b81516001600160401b0380821115620000ef57620000ef620000aa565b604051601f8301601f19908116603f011681019082821181831017156200011a576200011a620000aa565b816040528381526020925086838588010111156200013757600080fd5b600091505b838210156200015b57858201830151818301840152908201906200013c565b838211156200016d5760008385830101525b9695505050505050565b600080600080600060a086880312156200019057600080fd5b6200019b866200008d565b9450620001ab602087016200008d565b60408701519094506001600160401b0380821115620001c957600080fd5b620001d789838a01620000c0565b94506060880151915080821115620001ee57600080fd5b50620001fd88828901620000c0565b925050608086015160ff811681146200021557600080fd5b809150509295509295909350565b600181811c908216806200023857607f821691505b6020821081036200025957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002ad57600081815260208120601f850160051c81016020861015620002885750805b601f850160051c820191505b81811015620002a95782815560010162000294565b5050505b505050565b81516001600160401b03811115620002ce57620002ce620000aa565b620002e681620002df845462000223565b846200025f565b602080601f8311600181146200031e5760008415620003055750858301515b600019600386901b1c1916600185901b178555620002a9565b600085815260208120601f198616915b828110156200034f578886015182559484019460019091019084016200032e565b50858210156200036e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516116ed620003ea6000396000610244015260008181610317015281816103ac015281816105f101526107cb0152600081816101a9015261033d0152600061075a015260006107310152600061070801526116ed6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a" +var OptimismMintableERC20FactoryDeployedBin = "0x60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e372e3000000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b61178a80620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(OptimismMintableERC20FactoryStorageLayoutJSON), OptimismMintableERC20FactoryStorageLayout); err != nil { diff --git a/boba-bindings/bindings/preimageoracle_more.go b/boba-bindings/bindings/preimageoracle_more.go index 1d776d75ff90..6a56fe60b63f 100644 --- a/boba-bindings/bindings/preimageoracle_more.go +++ b/boba-bindings/bindings/preimageoracle_more.go @@ -15,7 +15,7 @@ var PreimageOracleStorageLayout = new(solc.StorageLayout) var PreimageOracleDeployedBin = "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063e03110e111610050578063e03110e114610106578063e15926111461012e578063fef2b4ed1461014357600080fd5b806361238bde146100775780638542cf50146100b5578063c0c220c9146100f3575b600080fd5b6100a26100853660046104df565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6100e36100c33660046104df565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016100ac565b6100a2610101366004610501565b610163565b6101196101143660046104df565b610238565b604080519283526020830191909152016100ac565b61014161013c36600461053c565b610329565b005b6100a26101513660046105b8565b60006020819052908152604090205481565b600061016f8686610432565b905061017c836008610600565b8211806101895750602083115b156101c0576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b6000828152600260209081526040808320848452909152812054819060ff166102c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546102dd816008610600565b6102e8856020610600565b1061030657836102f9826008610600565b6103039190610618565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018611156103485763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316176104d8818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b600080604083850312156104f257600080fd5b50508035926020909101359150565b600080600080600060a0868803121561051957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060006040848603121561055157600080fd5b83359250602084013567ffffffffffffffff8082111561057057600080fd5b818601915086601f83011261058457600080fd5b81358181111561059357600080fd5b8760208285010111156105a557600080fd5b6020830194508093505050509250925092565b6000602082840312156105ca57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610613576106136105d1565b500190565b60008282101561062a5761062a6105d1565b50039056fea164736f6c634300080f000a" -var PreimageOracleDeployedSourceMap = "306:3911:146:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;537:68;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;413:25:310;;;401:2;386:18;537:68:146;;;;;;;;680:66;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;614:14:310;;607:22;589:41;;577:2;562:18;680:66:146;449:187:310;1367:1211:146;;;;;;:::i;:::-;;:::i;789:536::-;;;;;;:::i;:::-;;:::i;:::-;;;;1274:25:310;;;1330:2;1315:18;;1308:34;;;;1247:18;789:536:146;1100:248:310;2620:1595:146;;;;;;:::i;:::-;;:::i;:::-;;419:50;;;;;;:::i;:::-;;;;;;;;;;;;;;;1367:1211;1560:12;1665:51;1694:6;1702:13;1665:28;:51::i;:::-;1658:58;-1:-1:-1;1810:9:146;:5;1818:1;1810:9;:::i;:::-;1796:11;:23;:37;;;;1831:2;1823:5;:10;1796:37;1792:90;;;1856:15;;;;;;;;;;;;;;1792:90;1951:12;2051:4;2044:18;;;2152:3;2148:15;;;2135:29;;2184:4;2177:19;;;;2286:18;;2376:20;;;:14;:20;;;;;;:33;;;;;;;;:40;;;;2412:4;2376:40;;;;;;2426:19;;;;;;;;:32;;;;;;;;;:39;2542:21;;;;;;;;;:29;2391:4;1367:1211;-1:-1:-1;;1367:1211:146:o;789:536::-;865:12;914:20;;;:14;:20;;;;;;;;:29;;;;;;;;;865:12;;914:29;;906:62;;;;;;;2908:2:310;906:62:146;;;2890:21:310;2947:2;2927:18;;;2920:30;2986:22;2966:18;;;2959:50;3026:18;;906:62:146;;;;;;;;-1:-1:-1;1099:14:146;1116:21;;;1087:2;1116:21;;;;;;;;1167:10;1116:21;1176:1;1167:10;:::i;:::-;1151:12;:7;1161:2;1151:12;:::i;:::-;:26;1147:87;;1216:7;1203:10;:6;1212:1;1203:10;:::i;:::-;:20;;;;:::i;:::-;1193:30;;1147:87;-1:-1:-1;1290:19:146;;;;:13;:19;;;;;;;;:28;;;;;;;;;;;;789:536;;-1:-1:-1;789:536:146:o;2620:1595::-;2916:4;2903:18;2721:12;;3045:1;3035:12;;3019:29;;3016:210;;;3120:10;3117:1;3110:21;3210:1;3204:4;3197:15;3016:210;3469:3;3465:14;;;3369:4;3453:27;3500:11;3474:4;3619:16;3500:11;3601:41;3832:29;;;3836:11;3832:29;3826:36;3884:20;;;;4031:19;4024:27;4053:11;4021:44;4084:19;;;;4062:1;4084:19;;;;;;;;:32;;;;;;;;:39;;;;4119:4;4084:39;;;;;;4133:18;;;;;;;;:31;;;;;;;;;:38;;;;4181:20;;;;;;;;;;;:27;;;;-1:-1:-1;;;;2620:1595:146:o;552:449:145:-;835:11;860:19;848:32;;832:49;965:29;832:49;980:13;1676:4;1670:11;;1533:21;1787:15;;;1828:8;1822:4;1815:22;1850:27;;;1996:4;1983:18;;;2098:17;;2003:19;1979:44;2025:11;1976:61;;1455:676;965:29;958:36;552:449;-1:-1:-1;;;552:449:145:o;14:248:310:-;82:6;90;143:2;131:9;122:7;118:23;114:32;111:52;;;159:1;156;149:12;111:52;-1:-1:-1;;182:23:310;;;252:2;237:18;;;224:32;;-1:-1:-1;14:248:310:o;641:454::-;736:6;744;752;760;768;821:3;809:9;800:7;796:23;792:33;789:53;;;838:1;835;828:12;789:53;-1:-1:-1;;861:23:310;;;931:2;916:18;;903:32;;-1:-1:-1;982:2:310;967:18;;954:32;;1033:2;1018:18;;1005:32;;-1:-1:-1;1084:3:310;1069:19;1056:33;;-1:-1:-1;641:454:310;-1:-1:-1;641:454:310:o;1353:659::-;1432:6;1440;1448;1501:2;1489:9;1480:7;1476:23;1472:32;1469:52;;;1517:1;1514;1507:12;1469:52;1553:9;1540:23;1530:33;;1614:2;1603:9;1599:18;1586:32;1637:18;1678:2;1670:6;1667:14;1664:34;;;1694:1;1691;1684:12;1664:34;1732:6;1721:9;1717:22;1707:32;;1777:7;1770:4;1766:2;1762:13;1758:27;1748:55;;1799:1;1796;1789:12;1748:55;1839:2;1826:16;1865:2;1857:6;1854:14;1851:34;;;1881:1;1878;1871:12;1851:34;1926:7;1921:2;1912:6;1908:2;1904:15;1900:24;1897:37;1894:57;;;1947:1;1944;1937:12;1894:57;1978:2;1974;1970:11;1960:21;;2000:6;1990:16;;;;;1353:659;;;;;:::o;2017:180::-;2076:6;2129:2;2117:9;2108:7;2104:23;2100:32;2097:52;;;2145:1;2142;2135:12;2097:52;-1:-1:-1;2168:23:310;;2017:180;-1:-1:-1;2017:180:310:o;2384:184::-;2436:77;2433:1;2426:88;2533:4;2530:1;2523:15;2557:4;2554:1;2547:15;2573:128;2613:3;2644:1;2640:6;2637:1;2634:13;2631:39;;;2650:18;;:::i;:::-;-1:-1:-1;2686:9:310;;2573:128::o;3055:125::-;3095:4;3123:1;3120;3117:8;3114:34;;;3128:18;;:::i;:::-;-1:-1:-1;3165:9:310;;3055:125::o" +var PreimageOracleDeployedSourceMap = "306:3911:146:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;537:68;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;413:25:319;;;401:2;386:18;537:68:146;;;;;;;;680:66;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;614:14:319;;607:22;589:41;;577:2;562:18;680:66:146;449:187:319;1367:1211:146;;;;;;:::i;:::-;;:::i;789:536::-;;;;;;:::i;:::-;;:::i;:::-;;;;1274:25:319;;;1330:2;1315:18;;1308:34;;;;1247:18;789:536:146;1100:248:319;2620:1595:146;;;;;;:::i;:::-;;:::i;:::-;;419:50;;;;;;:::i;:::-;;;;;;;;;;;;;;;1367:1211;1560:12;1665:51;1694:6;1702:13;1665:28;:51::i;:::-;1658:58;-1:-1:-1;1810:9:146;:5;1818:1;1810:9;:::i;:::-;1796:11;:23;:37;;;;1831:2;1823:5;:10;1796:37;1792:90;;;1856:15;;;;;;;;;;;;;;1792:90;1951:12;2051:4;2044:18;;;2152:3;2148:15;;;2135:29;;2184:4;2177:19;;;;2286:18;;2376:20;;;:14;:20;;;;;;:33;;;;;;;;:40;;;;2412:4;2376:40;;;;;;2426:19;;;;;;;;:32;;;;;;;;;:39;2542:21;;;;;;;;;:29;2391:4;1367:1211;-1:-1:-1;;1367:1211:146:o;789:536::-;865:12;914:20;;;:14;:20;;;;;;;;:29;;;;;;;;;865:12;;914:29;;906:62;;;;;;;2908:2:319;906:62:146;;;2890:21:319;2947:2;2927:18;;;2920:30;2986:22;2966:18;;;2959:50;3026:18;;906:62:146;;;;;;;;-1:-1:-1;1099:14:146;1116:21;;;1087:2;1116:21;;;;;;;;1167:10;1116:21;1176:1;1167:10;:::i;:::-;1151:12;:7;1161:2;1151:12;:::i;:::-;:26;1147:87;;1216:7;1203:10;:6;1212:1;1203:10;:::i;:::-;:20;;;;:::i;:::-;1193:30;;1147:87;-1:-1:-1;1290:19:146;;;;:13;:19;;;;;;;;:28;;;;;;;;;;;;789:536;;-1:-1:-1;789:536:146:o;2620:1595::-;2916:4;2903:18;2721:12;;3045:1;3035:12;;3019:29;;3016:210;;;3120:10;3117:1;3110:21;3210:1;3204:4;3197:15;3016:210;3469:3;3465:14;;;3369:4;3453:27;3500:11;3474:4;3619:16;3500:11;3601:41;3832:29;;;3836:11;3832:29;3826:36;3884:20;;;;4031:19;4024:27;4053:11;4021:44;4084:19;;;;4062:1;4084:19;;;;;;;;:32;;;;;;;;:39;;;;4119:4;4084:39;;;;;;4133:18;;;;;;;;:31;;;;;;;;;:38;;;;4181:20;;;;;;;;;;;:27;;;;-1:-1:-1;;;;2620:1595:146:o;552:449:145:-;835:11;860:19;848:32;;832:49;965:29;832:49;980:13;1676:4;1670:11;;1533:21;1787:15;;;1828:8;1822:4;1815:22;1850:27;;;1996:4;1983:18;;;2098:17;;2003:19;1979:44;2025:11;1976:61;;1455:676;965:29;958:36;552:449;-1:-1:-1;;;552:449:145:o;14:248:319:-;82:6;90;143:2;131:9;122:7;118:23;114:32;111:52;;;159:1;156;149:12;111:52;-1:-1:-1;;182:23:319;;;252:2;237:18;;;224:32;;-1:-1:-1;14:248:319:o;641:454::-;736:6;744;752;760;768;821:3;809:9;800:7;796:23;792:33;789:53;;;838:1;835;828:12;789:53;-1:-1:-1;;861:23:319;;;931:2;916:18;;903:32;;-1:-1:-1;982:2:319;967:18;;954:32;;1033:2;1018:18;;1005:32;;-1:-1:-1;1084:3:319;1069:19;1056:33;;-1:-1:-1;641:454:319;-1:-1:-1;641:454:319:o;1353:659::-;1432:6;1440;1448;1501:2;1489:9;1480:7;1476:23;1472:32;1469:52;;;1517:1;1514;1507:12;1469:52;1553:9;1540:23;1530:33;;1614:2;1603:9;1599:18;1586:32;1637:18;1678:2;1670:6;1667:14;1664:34;;;1694:1;1691;1684:12;1664:34;1732:6;1721:9;1717:22;1707:32;;1777:7;1770:4;1766:2;1762:13;1758:27;1748:55;;1799:1;1796;1789:12;1748:55;1839:2;1826:16;1865:2;1857:6;1854:14;1851:34;;;1881:1;1878;1871:12;1851:34;1926:7;1921:2;1912:6;1908:2;1904:15;1900:24;1897:37;1894:57;;;1947:1;1944;1937:12;1894:57;1978:2;1974;1970:11;1960:21;;2000:6;1990:16;;;;;1353:659;;;;;:::o;2017:180::-;2076:6;2129:2;2117:9;2108:7;2104:23;2100:32;2097:52;;;2145:1;2142;2135:12;2097:52;-1:-1:-1;2168:23:319;;2017:180;-1:-1:-1;2017:180:319:o;2384:184::-;2436:77;2433:1;2426:88;2533:4;2530:1;2523:15;2557:4;2554:1;2547:15;2573:128;2613:3;2644:1;2640:6;2637:1;2634:13;2631:39;;;2650:18;;:::i;:::-;-1:-1:-1;2686:9:319;;2573:128::o;3055:125::-;3095:4;3123:1;3120;3117:8;3114:34;;;3128:18;;:::i;:::-;-1:-1:-1;3165:9:319;;3055:125::o" func init() { if err := json.Unmarshal([]byte(PreimageOracleStorageLayoutJSON), PreimageOracleStorageLayout); err != nil { diff --git a/codecov.yml b/codecov.yml index f64112c9cf1c..11f6adec1635 100644 --- a/codecov.yml +++ b/codecov.yml @@ -3,7 +3,7 @@ codecov: comment: layout: "diff, flags, files" behavior: default - require_changes: false + require_changes: true flags: - contracts-bedrock-tests @@ -12,6 +12,7 @@ ignore: - "op-bindings/bindings/*.go" - "**/*.t.sol" - "packages/contracts-bedrock/test/**/*.sol" + - "packages/contracts-bedrock/scripts/**/*.sol" - "packages/contracts-bedrock/contracts/vendor/WETH9.sol" - 'packages/contracts-bedrock/contracts/EAS/**/*.sol' coverage: diff --git a/go.mod b/go.mod index a384fc4c0295..c9a2db28d756 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 - github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20231026175037-2cff0d130e74 + github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20231030223232-e16eae11e492 github.com/ethereum/go-ethereum v1.13.1 github.com/fsnotify/fsnotify v1.7.0 github.com/go-chi/chi/v5 v5.0.10 @@ -23,10 +23,10 @@ require ( github.com/ipfs/go-datastore v0.6.0 github.com/ipfs/go-ds-leveldb v0.5.0 github.com/jackc/pgtype v1.14.0 - github.com/jackc/pgx/v5 v5.4.3 - github.com/libp2p/go-libp2p v0.31.0 + github.com/jackc/pgx/v5 v5.5.0 + github.com/libp2p/go-libp2p v0.32.0 github.com/libp2p/go-libp2p-mplex v0.9.0 - github.com/libp2p/go-libp2p-pubsub v0.9.3 + github.com/libp2p/go-libp2p-pubsub v0.10.0 github.com/libp2p/go-libp2p-testing v0.12.0 github.com/mattn/go-isatty v0.0.20 github.com/multiformats/go-base32 v0.1.0 @@ -40,11 +40,11 @@ require ( github.com/stretchr/testify v1.8.4 github.com/urfave/cli/v2 v2.25.7 golang.org/x/crypto v0.14.0 - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 - golang.org/x/sync v0.4.0 + golang.org/x/exp v0.0.0-20231006140011-7918f672742d + golang.org/x/sync v0.5.0 golang.org/x/term v0.13.0 - golang.org/x/time v0.3.0 - golang.org/x/tools v0.13.0 + golang.org/x/time v0.4.0 + golang.org/x/tools v0.14.0 gorm.io/driver/postgres v1.5.4 gorm.io/gorm v1.25.5 ) @@ -102,10 +102,9 @@ require ( github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect - github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect + github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -122,6 +121,7 @@ require ( github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/goprocess v0.1.4 // indirect @@ -129,7 +129,7 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.2 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/pretty v0.3.1 // indirect @@ -149,7 +149,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.55 // indirect + github.com/miekg/dns v1.1.56 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/minio/sha256-simd v1.0.1 // indirect @@ -162,7 +162,7 @@ require ( github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multicodec v0.9.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect - github.com/multiformats/go-multistream v0.4.1 // indirect + github.com/multiformats/go-multistream v0.5.0 // indirect github.com/multiformats/go-varint v0.0.7 // indirect github.com/naoina/go-stringutil v0.1.0 // indirect github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 // indirect @@ -176,9 +176,9 @@ require ( github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.11.1 // indirect github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-20 v0.3.3 // indirect - github.com/quic-go/quic-go v0.38.1 // indirect - github.com/quic-go/webtransport-go v0.5.3 // indirect + github.com/quic-go/qtls-go1-20 v0.3.4 // indirect + github.com/quic-go/quic-go v0.39.3 // indirect + github.com/quic-go/webtransport-go v0.6.0 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/rivo/uniseg v0.4.3 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect @@ -197,11 +197,12 @@ require ( github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect go.uber.org/automaxprocs v1.5.2 // indirect - go.uber.org/dig v1.17.0 // indirect - go.uber.org/fx v1.20.0 // indirect + go.uber.org/dig v1.17.1 // indirect + go.uber.org/fx v1.20.1 // indirect + go.uber.org/mock v0.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.25.0 // indirect - golang.org/x/mod v0.12.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/mod v0.13.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect @@ -213,7 +214,7 @@ require ( rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/ethereum/go-ethereum v1.13.1 => github.com/ethereum-optimism/op-geth v1.101303.0-rc.2.0.20231026180835-94fbbd04522e +replace github.com/ethereum/go-ethereum v1.13.1 => github.com/ethereum-optimism/op-geth v1.101304.0-rc.2.0.20231030225546-cd491fa3b588 //replace github.com/ethereum-optimism/superchain-registry/superchain => ../superchain-registry/superchain //replace github.com/ethereum/go-ethereum v1.13.1 => ../go-ethereum diff --git a/go.sum b/go.sum index ad68213b6625..6b7bd8a55654 100644 --- a/go.sum +++ b/go.sum @@ -224,10 +224,10 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs= -github.com/ethereum-optimism/op-geth v1.101303.0-rc.2.0.20231026180835-94fbbd04522e h1:5ucLyIBCwo07ejZOKFY+6QbCqbLgITHWVqkmLoO6604= -github.com/ethereum-optimism/op-geth v1.101303.0-rc.2.0.20231026180835-94fbbd04522e/go.mod h1:m6GrpSyAe1zdFLJlSctgYKSXUdHwj/yfq2WSOc5vs2A= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20231026175037-2cff0d130e74 h1:02gXBD+Cas7xj9rpkke5wD1+vpfYxyF/+31M5tosP9A= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20231026175037-2cff0d130e74/go.mod h1:/70H/KqrtKcvWvNGVj6S3rAcLC+kUPr3t2aDmYIS+Xk= +github.com/ethereum-optimism/op-geth v1.101304.0-rc.2.0.20231030225546-cd491fa3b588 h1:jrvFoV3aSGJcTT8Pyo8R2Sp7CZ0v3hqrdhfSmyZbJVw= +github.com/ethereum-optimism/op-geth v1.101304.0-rc.2.0.20231030225546-cd491fa3b588/go.mod h1:12W+vBetjYbDj5D2+V8hizke5yWuLrUDf7UmVkXTnCQ= +github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20231030223232-e16eae11e492 h1:FyzLzMLKMc9zcDYcSxbrLDglIRrGQJE9juFzIO35RmE= +github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20231030223232-e16eae11e492/go.mod h1:/70H/KqrtKcvWvNGVj6S3rAcLC+kUPr3t2aDmYIS+Xk= github.com/ethereum/c-kzg-4844 v0.3.1 h1:sR65+68+WdnMKxseNWxSJuAv2tsUrihTpVBTfM/U5Zg= github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.10.3/go.mod h1:99onQmSd1GRGOziyGldI41YQb7EESX3Q4H41IfJgIQQ= @@ -320,8 +320,6 @@ github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200j github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -370,8 +368,8 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= -github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo= -github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0= +github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -494,11 +492,13 @@ github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9 github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c h1:Dznn52SgVIVst9UyOT9brctYUgxs+CvVfPaC3jKrA50= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= -github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/pgx/v5 v5.5.0 h1:NxstgwndsTRy7eq9/kqYc/BZh5w2hHJV86wjvO+1xPw= +github.com/jackc/pgx/v5 v5.5.0/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= @@ -540,8 +540,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -582,14 +582,14 @@ github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38y github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.31.0 h1:LFShhP8F6xthWiBBq3euxbKjZsoRajVEyBS9snfHxYg= -github.com/libp2p/go-libp2p v0.31.0/go.mod h1:W/FEK1c/t04PbRH3fA9i5oucu5YcgrG0JVoBWT1B7Eg= +github.com/libp2p/go-libp2p v0.32.0 h1:86I4B7nBUPIyTgw3+5Ibq6K7DdKRCuZw8URCfPc1hQM= +github.com/libp2p/go-libp2p v0.32.0/go.mod h1:hXXC3kXPlBZ1eu8Q2hptGrMB4mZ3048JUoS4EKaHW5c= github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= github.com/libp2p/go-libp2p-mplex v0.9.0 h1:R58pDRAmuBXkYugbSSXR9wrTX3+1pFM1xP2bLuodIq8= github.com/libp2p/go-libp2p-mplex v0.9.0/go.mod h1:ro1i4kuwiFT+uMPbIDIFkcLs1KRbNp0QwnUXM+P64Og= -github.com/libp2p/go-libp2p-pubsub v0.9.3 h1:ihcz9oIBMaCK9kcx+yHWm3mLAFBMAUsM4ux42aikDxo= -github.com/libp2p/go-libp2p-pubsub v0.9.3/go.mod h1:RYA7aM9jIic5VV47WXu4GkcRxRhrdElWf8xtyli+Dzc= +github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA= +github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= @@ -645,8 +645,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= -github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= +github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= @@ -690,8 +690,8 @@ github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI1 github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= -github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo= -github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q= +github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE= +github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA= github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= @@ -781,12 +781,12 @@ github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 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-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM= -github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= -github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE= -github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4= -github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU= -github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= +github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg= +github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= +github.com/quic-go/quic-go v0.39.3 h1:o3YB6t2SR+HU/pgwF29kJ6g4jJIJEwEZ8CKia1h1TKg= +github.com/quic-go/quic-go v0.39.3/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q= +github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY= +github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= @@ -928,13 +928,15 @@ go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= -go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI= -go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU= -go.uber.org/fx v1.20.0 h1:ZMC/pnRvhsthOZh9MZjMq5U8Or3mA9zBSPaLnzs3ihQ= -go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0= +go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= +go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= +go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk= +go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= +go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -946,8 +948,8 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -983,8 +985,8 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0 golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1007,8 +1009,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1066,8 +1068,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1152,8 +1154,8 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= +golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1192,11 +1194,10 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/indexer/api-ts/generated.ts b/indexer/api-ts/generated.ts index 9b19bb6da987..957d72fddc07 100644 --- a/indexer/api-ts/generated.ts +++ b/indexer/api-ts/generated.ts @@ -34,12 +34,12 @@ export interface WithdrawalItem { from: string; to: string; transactionHash: string; - messageHash: string; + crossDomainMessageHash: string; timestamp: number /* uint64 */; l2BlockHash: string; amount: string; - proofTransactionHash: string; - claimTransactionHash: string; + l1ProvenTxHash: string; + l1FinalizedTxHash: string; l1TokenAddress: string; l2TokenAddress: string; } diff --git a/indexer/api/api.go b/indexer/api/api.go index 37a572515e26..e844839d55bf 100644 --- a/indexer/api/api.go +++ b/indexer/api/api.go @@ -6,33 +6,25 @@ import ( "fmt" "net" "net/http" - "runtime/debug" "strconv" - "sync" + "sync/atomic" + "time" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" + "github.com/prometheus/client_golang/prometheus" + + "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/indexer/api/routes" "github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/ethereum-optimism/optimism/op-service/metrics" - "github.com/ethereum/go-ethereum/log" - "github.com/go-chi/chi/v5" - "github.com/go-chi/chi/v5/middleware" - "github.com/prometheus/client_golang/prometheus" ) const ethereumAddressRegex = `^0x[a-fA-F0-9]{40}$` -// Api ... Indexer API struct -// TODO : Structured error responses -type API struct { - log log.Logger - router *chi.Mux - serverConfig config.ServerConfig - metricsConfig config.ServerConfig - metricsRegistry *prometheus.Registry -} - const ( MetricsNamespace = "op_indexer_api" addressParam = "{address:%s}" @@ -45,6 +37,23 @@ const ( WithdrawalsPath = "/api/v0/withdrawals/" ) +// Api ... Indexer API struct +// TODO : Structured error responses +type APIService struct { + log log.Logger + router *chi.Mux + + bv database.BridgeTransfersView + dbClose func() error + + metricsRegistry *prometheus.Registry + + apiServer *httputil.HTTPServer + metricsServer *httputil.HTTPServer + + stopped atomic.Bool +} + // chiMetricsMiddleware ... Injects a metrics recorder into request processing middleware func chiMetricsMiddleware(rec metrics.HTTPRecorder) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { @@ -53,112 +62,117 @@ func chiMetricsMiddleware(rec metrics.HTTPRecorder) func(http.Handler) http.Hand } // NewApi ... Construct a new api instance -func NewApi(logger log.Logger, bv database.BridgeTransfersView, serverConfig config.ServerConfig, metricsConfig config.ServerConfig) *API { - // (1) Initialize dependencies - apiRouter := chi.NewRouter() - h := routes.NewRoutes(logger, bv, apiRouter) - - mr := metrics.NewRegistry() - promRecorder := metrics.NewPromHTTPRecorder(mr, MetricsNamespace) - - // (2) Inject routing middleware - apiRouter.Use(chiMetricsMiddleware(promRecorder)) - apiRouter.Use(middleware.Recoverer) - apiRouter.Use(middleware.Heartbeat(HealthPath)) +func NewApi(ctx context.Context, log log.Logger, cfg *Config) (*APIService, error) { + out := &APIService{log: log, metricsRegistry: metrics.NewRegistry()} + if err := out.initFromConfig(ctx, cfg); err != nil { + return nil, errors.Join(err, out.Stop(ctx)) // close any resources we may have opened already + } + return out, nil +} - // (3) Set GET routes - apiRouter.Get(fmt.Sprintf(DepositsPath+addressParam, ethereumAddressRegex), h.L1DepositsHandler) - apiRouter.Get(fmt.Sprintf(WithdrawalsPath+addressParam, ethereumAddressRegex), h.L2WithdrawalsHandler) +func (a *APIService) initFromConfig(ctx context.Context, cfg *Config) error { + if err := a.initDB(ctx, cfg.DB); err != nil { + return fmt.Errorf("failed to init DB: %w", err) + } + if err := a.startMetricsServer(cfg.MetricsServer); err != nil { + return fmt.Errorf("failed to start metrics server: %w", err) + } + a.initRouter(cfg.HTTPServer) + if err := a.startServer(cfg.HTTPServer); err != nil { + return fmt.Errorf("failed to start API server: %w", err) + } + return nil +} - return &API{log: logger, router: apiRouter, metricsRegistry: mr, serverConfig: serverConfig, metricsConfig: metricsConfig} +func (a *APIService) Start(ctx context.Context) error { + // Completed all setup-up jobs at init-time already, + // and the API service does not have any other special starting routines or background-jobs to start. + return nil } -// Run ... Runs the API server routines -func (a *API) Run(ctx context.Context) error { - var wg sync.WaitGroup - errCh := make(chan error, 2) - - // (1) Construct an inner function that will start a goroutine - // and handle any panics that occur on a shared error channel - processCtx, processCancel := context.WithCancel(ctx) - runProcess := func(start func(ctx context.Context) error) { - wg.Add(1) - go func() { - defer func() { - if err := recover(); err != nil { - a.log.Error("halting api on panic", "err", err) - debug.PrintStack() - errCh <- fmt.Errorf("panic: %v", err) - } - - processCancel() - wg.Done() - }() - - errCh <- start(processCtx) - }() +func (a *APIService) Stop(ctx context.Context) error { + var result error + if a.apiServer != nil { + if err := a.apiServer.Stop(ctx); err != nil { + result = errors.Join(result, fmt.Errorf("failed to stop API server: %w", err)) + } + } + if a.metricsServer != nil { + if err := a.metricsServer.Stop(ctx); err != nil { + result = errors.Join(result, fmt.Errorf("failed to stop metrics server: %w", err)) + } } + if a.dbClose != nil { + if err := a.dbClose(); err != nil { + result = errors.Join(result, fmt.Errorf("failed to close DB: %w", err)) + } + } + a.stopped.Store(true) + a.log.Info("API service shutdown complete") + return result +} - // (2) Start the API and metrics servers - runProcess(a.startServer) - runProcess(a.startMetricsServer) +func (a *APIService) Stopped() bool { + return a.stopped.Load() +} - // (3) Wait for all processes to complete - wg.Wait() +// Addr ... returns the address that the HTTP server is listening on (excl. http:// prefix, just the host and port) +func (a *APIService) Addr() string { + if a.apiServer == nil { + return "" + } + return a.apiServer.Addr().String() +} - err := <-errCh +func (a *APIService) initDB(ctx context.Context, connector DBConnector) error { + db, err := connector.OpenDB(ctx, a.log) if err != nil { - a.log.Error("api stopped", "err", err) - } else { - a.log.Info("api stopped") + return fmt.Errorf("failed to connect to databse: %w", err) } - - return err + a.dbClose = db.Closer + a.bv = db.BridgeTransfers + return nil } -// Port ... Returns the the port that server is listening on -func (a *API) Port() int { - return a.serverConfig.Port +func (a *APIService) initRouter(apiConfig config.ServerConfig) { + apiRouter := chi.NewRouter() + h := routes.NewRoutes(a.log, a.bv, apiRouter) + + promRecorder := metrics.NewPromHTTPRecorder(a.metricsRegistry, MetricsNamespace) + + // (2) Inject routing middleware + apiRouter.Use(chiMetricsMiddleware(promRecorder)) + apiRouter.Use(middleware.Timeout(time.Duration(apiConfig.WriteTimeout) * time.Second)) + apiRouter.Use(middleware.Recoverer) + apiRouter.Use(middleware.Heartbeat(HealthPath)) + + // (3) Set GET routes + apiRouter.Get(fmt.Sprintf(DepositsPath+addressParam, ethereumAddressRegex), h.L1DepositsHandler) + apiRouter.Get(fmt.Sprintf(WithdrawalsPath+addressParam, ethereumAddressRegex), h.L2WithdrawalsHandler) + a.router = apiRouter } // startServer ... Starts the API server -func (a *API) startServer(ctx context.Context) error { - a.log.Debug("api server listening...", "port", a.serverConfig.Port) - addr := net.JoinHostPort(a.serverConfig.Host, strconv.Itoa(a.serverConfig.Port)) +func (a *APIService) startServer(serverConfig config.ServerConfig) error { + a.log.Debug("API server listening...", "port", serverConfig.Port) + addr := net.JoinHostPort(serverConfig.Host, strconv.Itoa(serverConfig.Port)) srv, err := httputil.StartHTTPServer(addr, a.router) if err != nil { return fmt.Errorf("failed to start API server: %w", err) } - - host, portStr, err := net.SplitHostPort(srv.Addr().String()) - if err != nil { - return errors.Join(err, srv.Close()) - } - port, err := strconv.Atoi(portStr) - if err != nil { - return errors.Join(err, srv.Close()) - } - - // Update the port in the config in case the OS chose a different port - // than the one we requested (e.g. using port 0 to fetch a random open port) - a.serverConfig.Host = host - a.serverConfig.Port = port - - <-ctx.Done() - if err := srv.Stop(context.Background()); err != nil { - return fmt.Errorf("failed to shutdown api server: %w", err) - } + a.log.Info("API server started", "addr", srv.Addr().String()) + a.apiServer = srv return nil } // startMetricsServer ... Starts the metrics server -func (a *API) startMetricsServer(ctx context.Context) error { - a.log.Debug("starting metrics server...", "port", a.metricsConfig.Port) - srv, err := metrics.StartServer(a.metricsRegistry, a.metricsConfig.Host, a.metricsConfig.Port) +func (a *APIService) startMetricsServer(metricsConfig config.ServerConfig) error { + a.log.Debug("starting metrics server...", "port", metricsConfig.Port) + srv, err := metrics.StartServer(a.metricsRegistry, metricsConfig.Host, metricsConfig.Port) if err != nil { return fmt.Errorf("failed to start metrics server: %w", err) } - <-ctx.Done() - defer a.log.Info("metrics server stopped") - return srv.Stop(context.Background()) + a.log.Info("Metrics server started", "addr", srv.Addr().String()) + a.metricsServer = srv + return nil } diff --git a/indexer/api/api_test.go b/indexer/api/api_test.go index 554fce28ce51..ba01d858b4de 100644 --- a/indexer/api/api_test.go +++ b/indexer/api/api_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "fmt" "net/http" @@ -24,11 +25,12 @@ var mockAddress = "0x4204204204204204204204204204204204204204" var apiConfig = config.ServerConfig{ Host: "localhost", - Port: 8080, + Port: 0, // random port, to allow parallel tests } + var metricsConfig = config.ServerConfig{ Host: "localhost", - Port: 7300, + Port: 0, // random port, to allow parallel tests } var ( @@ -95,8 +97,14 @@ func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalsByAddress(address common. } func TestHealthz(t *testing.T) { logger := testlog.Logger(t, log.LvlInfo) - api := NewApi(logger, &MockBridgeTransfersView{}, apiConfig, metricsConfig) - request, err := http.NewRequest("GET", "/healthz", nil) + cfg := &Config{ + DB: &TestDBConnector{BridgeTransfers: &MockBridgeTransfersView{}}, + HTTPServer: apiConfig, + MetricsServer: metricsConfig, + } + api, err := NewApi(context.Background(), logger, cfg) + require.NoError(t, err) + request, err := http.NewRequest("GET", "http://"+api.Addr()+"/healthz", nil) assert.Nil(t, err) responseRecorder := httptest.NewRecorder() @@ -107,8 +115,14 @@ func TestHealthz(t *testing.T) { func TestL1BridgeDepositsHandler(t *testing.T) { logger := testlog.Logger(t, log.LvlInfo) - api := NewApi(logger, &MockBridgeTransfersView{}, apiConfig, metricsConfig) - request, err := http.NewRequest("GET", fmt.Sprintf("/api/v0/deposits/%s", mockAddress), nil) + cfg := &Config{ + DB: &TestDBConnector{BridgeTransfers: &MockBridgeTransfersView{}}, + HTTPServer: apiConfig, + MetricsServer: metricsConfig, + } + api, err := NewApi(context.Background(), logger, cfg) + require.NoError(t, err) + request, err := http.NewRequest("GET", fmt.Sprintf("http://"+api.Addr()+"/api/v0/deposits/%s", mockAddress), nil) assert.Nil(t, err) responseRecorder := httptest.NewRecorder() @@ -130,8 +144,14 @@ func TestL1BridgeDepositsHandler(t *testing.T) { func TestL2BridgeWithdrawalsByAddressHandler(t *testing.T) { logger := testlog.Logger(t, log.LvlInfo) - api := NewApi(logger, &MockBridgeTransfersView{}, apiConfig, metricsConfig) - request, err := http.NewRequest("GET", fmt.Sprintf("/api/v0/withdrawals/%s", mockAddress), nil) + cfg := &Config{ + DB: &TestDBConnector{BridgeTransfers: &MockBridgeTransfersView{}}, + HTTPServer: apiConfig, + MetricsServer: metricsConfig, + } + api, err := NewApi(context.Background(), logger, cfg) + require.NoError(t, err) + request, err := http.NewRequest("GET", fmt.Sprintf("http://"+api.Addr()+"/api/v0/withdrawals/%s", mockAddress), nil) assert.Nil(t, err) responseRecorder := httptest.NewRecorder() @@ -149,8 +169,8 @@ func TestL2BridgeWithdrawalsByAddressHandler(t *testing.T) { assert.Equal(t, resp.Items[0].To, withdrawal.Tx.ToAddress.String()) assert.Equal(t, resp.Items[0].TransactionHash, common.HexToHash("0x789").String()) assert.Equal(t, resp.Items[0].Amount, withdrawal.Tx.Amount.String()) - assert.Equal(t, resp.Items[0].ProofTransactionHash, common.HexToHash("0x123").String()) - assert.Equal(t, resp.Items[0].ClaimTransactionHash, common.HexToHash("0x123").String()) + assert.Equal(t, resp.Items[0].L1ProvenTxHash, common.HexToHash("0x123").String()) + assert.Equal(t, resp.Items[0].L1FinalizedTxHash, common.HexToHash("0x123").String()) assert.Equal(t, resp.Items[0].L1TokenAddress, withdrawal.TokenPair.RemoteTokenAddress.String()) assert.Equal(t, resp.Items[0].L2TokenAddress, withdrawal.TokenPair.LocalTokenAddress.String()) assert.Equal(t, resp.Items[0].Timestamp, withdrawal.Tx.Timestamp) diff --git a/indexer/api/config.go b/indexer/api/config.go new file mode 100644 index 000000000000..fccf8f86c20d --- /dev/null +++ b/indexer/api/config.go @@ -0,0 +1,60 @@ +package api + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/indexer/config" + "github.com/ethereum-optimism/optimism/indexer/database" +) + +// DB represents the abstract DB access the API has. +type DB struct { + BridgeTransfers database.BridgeTransfersView + Closer func() error +} + +// DBConfigConnector implements a fully config based DBConnector +type DBConfigConnector struct { + config.DBConfig +} + +func (cfg *DBConfigConnector) OpenDB(ctx context.Context, log log.Logger) (*DB, error) { + db, err := database.NewDB(ctx, log, cfg.DBConfig) + if err != nil { + return nil, fmt.Errorf("failed to connect to databse: %w", err) + } + return &DB{ + BridgeTransfers: db.BridgeTransfers, + Closer: db.Close, + }, nil +} + +type TestDBConnector struct { + BridgeTransfers database.BridgeTransfersView +} + +func (tdb *TestDBConnector) OpenDB(ctx context.Context, log log.Logger) (*DB, error) { + return &DB{ + BridgeTransfers: tdb.BridgeTransfers, + Closer: func() error { + log.Info("API service closed test DB view") + return nil + }, + }, nil +} + +// DBConnector is an interface: the config may provide different ways to access the DB. +// This is implemented in tests to provide custom DB views, or share the DB with other services. +type DBConnector interface { + OpenDB(ctx context.Context, log log.Logger) (*DB, error) +} + +// Config for the API service +type Config struct { + DB DBConnector + HTTPServer config.ServerConfig + MetricsServer config.ServerConfig +} diff --git a/indexer/api/models/models.go b/indexer/api/models/models.go index 6ccdeae2f057..1bf86ee26192 100644 --- a/indexer/api/models/models.go +++ b/indexer/api/models/models.go @@ -1,5 +1,10 @@ package models +import ( + "github.com/ethereum-optimism/optimism/indexer/database" + "github.com/ethereum/go-ethereum/common" +) + // DepositItem ... Deposit item model for API responses type DepositItem struct { Guid string `json:"guid"` @@ -23,18 +28,18 @@ type DepositResponse struct { // WithdrawalItem ... Data model for API JSON response type WithdrawalItem struct { - Guid string `json:"guid"` - From string `json:"from"` - To string `json:"to"` - TransactionHash string `json:"transactionHash"` - MessageHash string `json:"messageHash"` - Timestamp uint64 `json:"timestamp"` - L2BlockHash string `json:"l2BlockHash"` - Amount string `json:"amount"` - ProofTransactionHash string `json:"proofTransactionHash"` - ClaimTransactionHash string `json:"claimTransactionHash"` - L1TokenAddress string `json:"l1TokenAddress"` - L2TokenAddress string `json:"l2TokenAddress"` + Guid string `json:"guid"` + From string `json:"from"` + To string `json:"to"` + TransactionHash string `json:"transactionHash"` + CrossDomainMessageHash string `json:"crossDomainMessageHash"` + Timestamp uint64 `json:"timestamp"` + L2BlockHash string `json:"l2BlockHash"` + Amount string `json:"amount"` + L1ProvenTxHash string `json:"l1ProvenTxHash"` + L1FinalizedTxHash string `json:"l1FinalizedTxHash"` + L1TokenAddress string `json:"l1TokenAddress"` + L2TokenAddress string `json:"l2TokenAddress"` } // WithdrawalResponse ... Data model for API JSON response @@ -43,3 +48,38 @@ type WithdrawalResponse struct { HasNextPage bool `json:"hasNextPage"` Items []WithdrawalItem `json:"items"` } + +// FIXME make a pure function that returns a struct instead of newWithdrawalResponse +// newWithdrawalResponse ... Converts a database.L2BridgeWithdrawalsResponse to an api.WithdrawalResponse +func CreateWithdrawalResponse(withdrawals *database.L2BridgeWithdrawalsResponse) WithdrawalResponse { + items := make([]WithdrawalItem, len(withdrawals.Withdrawals)) + for i, withdrawal := range withdrawals.Withdrawals { + + cdh := withdrawal.L2BridgeWithdrawal.CrossDomainMessageHash + if cdh == nil { // Zero value indicates that the withdrawal didn't have a cross domain message + cdh = &common.Hash{0} + } + + item := WithdrawalItem{ + Guid: withdrawal.L2BridgeWithdrawal.TransactionWithdrawalHash.String(), + L2BlockHash: withdrawal.L2BlockHash.String(), + Timestamp: withdrawal.L2BridgeWithdrawal.Tx.Timestamp, + From: withdrawal.L2BridgeWithdrawal.Tx.FromAddress.String(), + To: withdrawal.L2BridgeWithdrawal.Tx.ToAddress.String(), + TransactionHash: withdrawal.L2TransactionHash.String(), + Amount: withdrawal.L2BridgeWithdrawal.Tx.Amount.String(), + CrossDomainMessageHash: cdh.String(), + L1ProvenTxHash: withdrawal.ProvenL1TransactionHash.String(), + L1FinalizedTxHash: withdrawal.FinalizedL1TransactionHash.String(), + L1TokenAddress: withdrawal.L2BridgeWithdrawal.TokenPair.RemoteTokenAddress.String(), + L2TokenAddress: withdrawal.L2BridgeWithdrawal.TokenPair.LocalTokenAddress.String(), + } + items[i] = item + } + + return WithdrawalResponse{ + Cursor: withdrawals.Cursor, + HasNextPage: withdrawals.HasNextPage, + Items: items, + } +} diff --git a/indexer/api/models/models_test.go b/indexer/api/models/models_test.go new file mode 100644 index 000000000000..c2fe8a842c97 --- /dev/null +++ b/indexer/api/models/models_test.go @@ -0,0 +1,64 @@ +package models_test + +import ( + "fmt" + "reflect" + "testing" + + "github.com/ethereum-optimism/optimism/indexer/api/models" + "github.com/ethereum-optimism/optimism/indexer/database" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestCreateWithdrawal(t *testing.T) { + // (1) Create a dummy database response object + + cdh := common.HexToHash("0x2") + dbWithdrawals := &database.L2BridgeWithdrawalsResponse{ + Withdrawals: []database.L2BridgeWithdrawalWithTransactionHashes{ + { + L2BridgeWithdrawal: database.L2BridgeWithdrawal{ + TransactionWithdrawalHash: common.HexToHash("0x1"), + BridgeTransfer: database.BridgeTransfer{ + CrossDomainMessageHash: &cdh, + Tx: database.Transaction{ + FromAddress: common.HexToAddress("0x3"), + ToAddress: common.HexToAddress("0x4"), + Timestamp: 5, + }, + TokenPair: database.TokenPair{ + LocalTokenAddress: common.HexToAddress("0x6"), + RemoteTokenAddress: common.HexToAddress("0x7"), + }, + }, + }, + }, + }, + } + + // (2) Create and validate response object + + response := models.CreateWithdrawalResponse(dbWithdrawals) + require.NotEmpty(t, response.Items) + require.Len(t, response.Items, 1) + + // (3) Use reflection to check that all fields in WithdrawalItem are populated correctly + + item := response.Items[0] + structType := reflect.TypeOf(item) + + structVal := reflect.ValueOf(item) + fieldNum := structVal.NumField() + + for i := 0; i < fieldNum; i++ { + field := structVal.Field(i) + fieldName := structType.Field(i).Name + + isSet := field.IsValid() && !field.IsZero() + + require.True(t, isSet, fmt.Sprintf("%s in not set", fieldName)) + + } + +} diff --git a/indexer/api/routes/withdrawals.go b/indexer/api/routes/withdrawals.go index 7c3ed399c00e..c408f2ab350d 100644 --- a/indexer/api/routes/withdrawals.go +++ b/indexer/api/routes/withdrawals.go @@ -4,38 +4,9 @@ import ( "net/http" "github.com/ethereum-optimism/optimism/indexer/api/models" - "github.com/ethereum-optimism/optimism/indexer/database" "github.com/go-chi/chi/v5" ) -// FIXME make a pure function that returns a struct instead of newWithdrawalResponse -// newWithdrawalResponse ... Converts a database.L2BridgeWithdrawalsResponse to an api.WithdrawalResponse -func newWithdrawalResponse(withdrawals *database.L2BridgeWithdrawalsResponse) models.WithdrawalResponse { - items := make([]models.WithdrawalItem, len(withdrawals.Withdrawals)) - for i, withdrawal := range withdrawals.Withdrawals { - item := models.WithdrawalItem{ - Guid: withdrawal.L2BridgeWithdrawal.TransactionWithdrawalHash.String(), - L2BlockHash: withdrawal.L2BlockHash.String(), - Timestamp: withdrawal.L2BridgeWithdrawal.Tx.Timestamp, - From: withdrawal.L2BridgeWithdrawal.Tx.FromAddress.String(), - To: withdrawal.L2BridgeWithdrawal.Tx.ToAddress.String(), - TransactionHash: withdrawal.L2TransactionHash.String(), - Amount: withdrawal.L2BridgeWithdrawal.Tx.Amount.String(), - ProofTransactionHash: withdrawal.ProvenL1TransactionHash.String(), - ClaimTransactionHash: withdrawal.FinalizedL1TransactionHash.String(), - L1TokenAddress: withdrawal.L2BridgeWithdrawal.TokenPair.RemoteTokenAddress.String(), - L2TokenAddress: withdrawal.L2BridgeWithdrawal.TokenPair.LocalTokenAddress.String(), - } - items[i] = item - } - - return models.WithdrawalResponse{ - Cursor: withdrawals.Cursor, - HasNextPage: withdrawals.HasNextPage, - Items: items, - } -} - // L2WithdrawalsHandler ... Handles /api/v0/withdrawals/{address} GET requests func (h Routes) L2WithdrawalsHandler(w http.ResponseWriter, r *http.Request) { addressValue := chi.URLParam(r, "address") @@ -69,7 +40,7 @@ func (h Routes) L2WithdrawalsHandler(w http.ResponseWriter, r *http.Request) { h.logger.Error("Unable to read withdrawals from DB", "err", err.Error()) return } - response := newWithdrawalResponse(withdrawals) + response := models.CreateWithdrawalResponse(withdrawals) err = jsonResponse(w, response, http.StatusOK) if err != nil { diff --git a/indexer/cmd/indexer/cli.go b/indexer/cmd/indexer/cli.go index ebf3b2a48db9..153cae9da4fc 100644 --- a/indexer/cmd/indexer/cli.go +++ b/indexer/cmd/indexer/cli.go @@ -1,14 +1,19 @@ package main import ( + "context" + + "github.com/urfave/cli/v2" + + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum-optimism/optimism/indexer" "github.com/ethereum-optimism/optimism/indexer/api" "github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/database" + "github.com/ethereum-optimism/optimism/op-service/cliapp" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum/go-ethereum/params" - - "github.com/urfave/cli/v2" + "github.com/ethereum-optimism/optimism/op-service/opio" ) var ( @@ -27,7 +32,7 @@ var ( } ) -func runIndexer(ctx *cli.Context) error { +func runIndexer(ctx *cli.Context, shutdown context.CancelCauseFunc) (cliapp.Lifecycle, error) { log := oplog.NewLogger(oplog.AppOut(ctx), oplog.ReadCLIConfig(ctx)).New("role", "indexer") oplog.SetGlobalLogHandler(log.GetHandler()) log.Info("running indexer...") @@ -35,26 +40,13 @@ func runIndexer(ctx *cli.Context) error { cfg, err := config.LoadConfig(log, ctx.String(ConfigFlag.Name)) if err != nil { log.Error("failed to load config", "err", err) - return err + return nil, err } - db, err := database.NewDB(log, cfg.DB) - if err != nil { - log.Error("failed to connect to database", "err", err) - return err - } - defer db.Close() - - indexer, err := indexer.NewIndexer(log, db, cfg.Chain, cfg.RPCs, cfg.HTTPServer, cfg.MetricsServer) - if err != nil { - log.Error("failed to create indexer", "err", err) - return err - } - - return indexer.Run(ctx.Context) + return indexer.NewIndexer(ctx.Context, log, &cfg, shutdown) } -func runApi(ctx *cli.Context) error { +func runApi(ctx *cli.Context, _ context.CancelCauseFunc) (cliapp.Lifecycle, error) { log := oplog.NewLogger(oplog.AppOut(ctx), oplog.ReadCLIConfig(ctx)).New("role", "api") oplog.SetGlobalLogHandler(log.GetHandler()) log.Info("running api...") @@ -62,21 +54,22 @@ func runApi(ctx *cli.Context) error { cfg, err := config.LoadConfig(log, ctx.String(ConfigFlag.Name)) if err != nil { log.Error("failed to load config", "err", err) - return err + return nil, err } - db, err := database.NewDB(log, cfg.DB) - if err != nil { - log.Error("failed to connect to database", "err", err) - return err + apiCfg := &api.Config{ + DB: &api.DBConfigConnector{DBConfig: cfg.DB}, + HTTPServer: cfg.HTTPServer, + MetricsServer: cfg.MetricsServer, } - defer db.Close() - api := api.NewApi(log, db.BridgeTransfers, cfg.HTTPServer, cfg.MetricsServer) - return api.Run(ctx.Context) + return api.NewApi(ctx.Context, log, apiCfg) } func runMigrations(ctx *cli.Context) error { + // We don't maintain a complicated lifecycle here, just interrupt to shut down. + ctx.Context = opio.CancelOnInterrupt(ctx.Context) + log := oplog.NewLogger(oplog.AppOut(ctx), oplog.ReadCLIConfig(ctx)).New("role", "migrations") oplog.SetGlobalLogHandler(log.GetHandler()) log.Info("running migrations...") @@ -87,7 +80,7 @@ func runMigrations(ctx *cli.Context) error { return err } - db, err := database.NewDB(log, cfg.DB) + db, err := database.NewDB(ctx.Context, log, cfg.DB) if err != nil { log.Error("failed to connect to database", "err", err) return err @@ -112,13 +105,13 @@ func newCli(GitCommit string, GitDate string) *cli.App { Name: "api", Flags: flags, Description: "Runs the api service", - Action: runApi, + Action: cliapp.LifecycleCmd(runApi), }, { Name: "index", Flags: flags, Description: "Runs the indexing service", - Action: runIndexer, + Action: cliapp.LifecycleCmd(runIndexer), }, { Name: "migrate", diff --git a/indexer/cmd/indexer/main.go b/indexer/cmd/indexer/main.go index 9026ea7c796c..341f10c4366b 100644 --- a/indexer/cmd/indexer/main.go +++ b/indexer/cmd/indexer/main.go @@ -4,9 +4,10 @@ import ( "context" "os" + "github.com/ethereum/go-ethereum/log" + oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/opio" - "github.com/ethereum/go-ethereum/log" ) var ( @@ -15,16 +16,10 @@ var ( ) func main() { - // This is the most root context, used to propagate - // cancellations to all spawned application-level goroutines - ctx, cancel := context.WithCancel(context.Background()) - go func() { - opio.BlockOnInterrupts() - cancel() - }() - oplog.SetupDefaults() app := newCli(GitCommit, GitDate) + // sub-commands set up their individual interrupt lifecycles, which can block on the given interrupt as needed. + ctx := opio.WithInterruptBlocker(context.Background()) if err := app.RunContext(ctx, os.Args); err != nil { log.Error("application failed", "err", err) os.Exit(1) diff --git a/indexer/config/config.go b/indexer/config/config.go index c8ecb286a6c3..831a26158e7f 100644 --- a/indexer/config/config.go +++ b/indexer/config/config.go @@ -134,10 +134,11 @@ type DBConfig struct { Password string `toml:"password"` } -// Configures the a server +// Configures the server type ServerConfig struct { - Host string `toml:"host"` - Port int `toml:"port"` + Host string `toml:"host"` + Port int `toml:"port"` + WriteTimeout int `toml:"timeout"` } // LoadConfig loads the `indexer.toml` config file from a given path diff --git a/indexer/database/db.go b/indexer/database/db.go index def83841f869..fdb8db253a04 100644 --- a/indexer/database/db.go +++ b/indexer/database/db.go @@ -30,7 +30,9 @@ type DB struct { BridgeTransactions BridgeTransactionsDB } -func NewDB(log log.Logger, dbConfig config.DBConfig) (*DB, error) { +// NewDB connects to the configured DB, and provides client-bindings to it. +// The initial connection may fail, or the dial may be cancelled with the provided context. +func NewDB(ctx context.Context, log log.Logger, dbConfig config.DBConfig) (*DB, error) { log = log.New("module", "db") dsn := fmt.Sprintf("host=%s dbname=%s sslmode=disable", dbConfig.Host, dbConfig.Name) diff --git a/indexer/e2e_tests/setup.go b/indexer/e2e_tests/setup.go index ebd69112c8aa..15126bd1fff8 100644 --- a/indexer/e2e_tests/setup.go +++ b/indexer/e2e_tests/setup.go @@ -34,7 +34,7 @@ type E2ETestSuite struct { // API Client *client.Client - API *api.API + API *api.APIService // Indexer DB *database.DB @@ -73,7 +73,7 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { t.Cleanup(func() { opSys.Close() }) // Indexer Configuration and Start - indexerCfg := config.Config{ + indexerCfg := &config.Config{ DB: config.DBConfig{ Host: "127.0.0.1", Port: 5432, @@ -106,51 +106,40 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { // the system is running, mark this test for Parallel execution t.Parallel() - // provide a DB for the unit test. disable logging - silentLog := testlog.Logger(t, log.LvlInfo) - silentLog.SetHandler(log.DiscardHandler()) - db, err := database.NewDB(silentLog, indexerCfg.DB) - require.NoError(t, err) - t.Cleanup(func() { db.Close() }) - indexerLog := testlog.Logger(t, log.LvlInfo).New("role", "indexer") - indexer, err := indexer.NewIndexer(indexerLog, db, indexerCfg.Chain, indexerCfg.RPCs, indexerCfg.HTTPServer, indexerCfg.MetricsServer) + ix, err := indexer.NewIndexer(context.Background(), indexerLog, indexerCfg, func(cause error) { + if cause != nil { + t.Fatalf("indexer shut down with critical error: %v", cause) + } + }) require.NoError(t, err) - indexerCtx, indexerStop := context.WithCancel(context.Background()) - go func() { - err := indexer.Run(indexerCtx) - if err != nil { // panicking here ensures that the test will exit - // during service failure. Using t.Fail() wouldn't be caught - // until all awaiting routines finish which would never happen. - panic(err) - } - }() + require.NoError(t, ix.Start(context.Background()), "cleanly start indexer") - apiLog := testlog.Logger(t, log.LvlInfo).New("role", "indexer_api") + t.Cleanup(func() { + require.NoError(t, ix.Stop(context.Background()), "cleanly shut down indexer") + }) - apiCfg := config.ServerConfig{ - Host: "127.0.0.1", - Port: 0, - } + apiLog := testlog.Logger(t, log.LvlInfo).New("role", "indexer_api") - mCfg := config.ServerConfig{ - Host: "127.0.0.1", - Port: 0, + apiCfg := &api.Config{ + DB: &api.TestDBConnector{BridgeTransfers: ix.DB.BridgeTransfers}, // reuse the same DB + HTTPServer: config.ServerConfig{ + Host: "127.0.0.1", + Port: 0, + }, + MetricsServer: config.ServerConfig{ + Host: "127.0.0.1", + Port: 0, + }, } - api := api.NewApi(apiLog, db.BridgeTransfers, apiCfg, mCfg) - apiCtx, apiStop := context.WithCancel(context.Background()) - go func() { - err := api.Run(apiCtx) - if err != nil { - panic(err) - } - }() + apiService, err := api.NewApi(context.Background(), apiLog, apiCfg) + require.NoError(t, err, "create indexer API service") + require.NoError(t, apiService.Start(context.Background()), "start indexer API service") t.Cleanup(func() { - apiStop() - indexerStop() + require.NoError(t, apiService.Stop(context.Background()), "cleanly shut down indexer") }) // Wait for the API to start listening @@ -158,16 +147,15 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { client, err := client.NewClient(&client.Config{ PaginationLimit: 100, - BaseURL: fmt.Sprintf("http://%s:%d", apiCfg.Host, api.Port()), + BaseURL: "http://" + apiService.Addr(), }) - - require.NoError(t, err) + require.NoError(t, err, "must open indexer API client") return E2ETestSuite{ t: t, Client: client, - DB: db, - Indexer: indexer, + DB: ix.DB, + Indexer: ix, OpCfg: &opCfg, OpSys: opSys, L1Client: opSys.Clients["l1"], @@ -203,7 +191,7 @@ func setupTestDatabase(t *testing.T) string { silentLog := log.New() silentLog.SetHandler(log.DiscardHandler()) - db, err := database.NewDB(silentLog, dbConfig) + db, err := database.NewDB(context.Background(), silentLog, dbConfig) require.NoError(t, err) defer db.Close() diff --git a/indexer/etl/etl.go b/indexer/etl/etl.go index f11c69ec7862..e317df87a528 100644 --- a/indexer/etl/etl.go +++ b/indexer/etl/etl.go @@ -7,11 +7,13 @@ import ( "math/big" "time" - "github.com/ethereum-optimism/optimism/indexer/node" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/indexer/node" + "github.com/ethereum-optimism/optimism/op-service/clock" ) type Config struct { @@ -31,9 +33,15 @@ type ETL struct { headerTraversal *node.HeaderTraversal contracts []common.Address - etlBatches chan ETLBatch + etlBatches chan *ETLBatch EthClient node.EthClient + + // A reference that'll stay populated between intervals + // in the event of failures in order to retry. + headers []types.Header + + worker *clock.LoopFn } type ETLBatch struct { @@ -46,47 +54,54 @@ type ETLBatch struct { HeadersWithLog map[common.Hash]bool } -func (etl *ETL) Start(ctx context.Context) error { - done := ctx.Done() - pollTicker := time.NewTicker(etl.loopInterval) - defer pollTicker.Stop() +// Start starts the ETL polling routine. The ETL work should be stopped with Close(). +func (etl *ETL) Start() error { + if etl.worker != nil { + return errors.New("already started") + } + etl.log.Info("starting etl...") + etl.worker = clock.NewLoopFn(clock.SystemClock, etl.tick, func() error { + close(etl.etlBatches) // can close the channel now, to signal to the consumer that we're done + etl.log.Info("stopped etl worker loop") + return nil + }, etl.loopInterval) + return nil +} - // A reference that'll stay populated between intervals - // in the event of failures in order to retry. - var headers []types.Header +func (etl *ETL) Close() error { + if etl.worker == nil { + return nil // worker was not running + } + return etl.worker.Close() +} - etl.log.Info("starting etl...") - for { - select { - case <-done: - etl.log.Info("stopping etl") - return nil - - case <-pollTicker.C: - done := etl.metrics.RecordInterval() - if len(headers) > 0 { - etl.log.Info("retrying previous batch") - } else { - newHeaders, err := etl.headerTraversal.NextFinalizedHeaders(etl.headerBufferSize) - if err != nil { - etl.log.Error("error querying for headers", "err", err) - } else if len(newHeaders) == 0 { - etl.log.Warn("no new headers. processor unexpectedly at head...") - } else { - headers = newHeaders - etl.metrics.RecordBatchHeaders(len(newHeaders)) - } - } - - // only clear the reference if we were able to process this batch - err := etl.processBatch(headers) - if err == nil { - headers = nil - } - - done(err) +func (etl *ETL) tick(_ context.Context) { + done := etl.metrics.RecordInterval() + if len(etl.headers) > 0 { + etl.log.Info("retrying previous batch") + } else { + newHeaders, err := etl.headerTraversal.NextHeaders(etl.headerBufferSize) + if err != nil { + etl.log.Error("error querying for headers", "err", err) + } else if len(newHeaders) == 0 { + etl.log.Warn("no new headers. etl at head?") + } else { + etl.headers = newHeaders + } + + latestHeader := etl.headerTraversal.LatestHeader() + if latestHeader != nil { + etl.metrics.RecordLatestHeight(latestHeader.Number) } } + + // only clear the reference if we were able to process this batch + err := etl.processBatch(etl.headers) + if err == nil { + etl.headers = nil + } + + done(err) } func (etl *ETL) processBatch(headers []types.Header) error { @@ -98,7 +113,6 @@ func (etl *ETL) processBatch(headers []types.Header) error { batchLog := etl.log.New("batch_start_block_number", firstHeader.Number, "batch_end_block_number", lastHeader.Number) batchLog.Info("extracting batch", "size", len(headers)) - etl.metrics.RecordBatchLatestHeight(lastHeader.Number) headerMap := make(map[common.Hash]*types.Header, len(headers)) for i := range headers { header := headers[i] @@ -128,6 +142,7 @@ func (etl *ETL) processBatch(headers []types.Header) error { for i := range logs.Logs { log := logs.Logs[i] + headersWithLog[log.BlockHash] = true if _, ok := headerMap[log.BlockHash]; !ok { // NOTE. Definitely an error state if the none of the headers were re-orged out in between // the blocks and logs retrieval operations. Unlikely as long as the confirmation depth has @@ -135,13 +150,10 @@ func (etl *ETL) processBatch(headers []types.Header) error { batchLog.Error("log found with block hash not in the batch", "block_hash", logs.Logs[i].BlockHash, "log_index", logs.Logs[i].Index) return errors.New("parsed log with a block hash not in the batch") } - - etl.metrics.RecordBatchLog(log.Address) - headersWithLog[log.BlockHash] = true } // ensure we use unique downstream references for the etl batch headersRef := headers - etl.etlBatches <- ETLBatch{Logger: batchLog, Headers: headersRef, HeaderMap: headerMap, Logs: logs.Logs, HeadersWithLog: headersWithLog} + etl.etlBatches <- &ETLBatch{Logger: batchLog, Headers: headersRef, HeaderMap: headerMap, Logs: logs.Logs, HeadersWithLog: headersWithLog} return nil } diff --git a/indexer/etl/l1_etl.go b/indexer/etl/l1_etl.go index a4613928b077..37a19586920a 100644 --- a/indexer/etl/l1_etl.go +++ b/indexer/etl/l1_etl.go @@ -8,26 +8,37 @@ import ( "sync" "time" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/node" "github.com/ethereum-optimism/optimism/op-service/retry" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-service/tasks" ) type L1ETL struct { ETL - db *database.DB - mu *sync.Mutex + // the batch handler may do work that we can interrupt on shutdown + resourceCtx context.Context + resourceCancel context.CancelFunc + + tasks tasks.Group + + db *database.DB + + mu sync.Mutex + listeners []chan interface{} } // NewL1ETL creates a new L1ETL instance that will start indexing from different starting points // depending on the state of the database and the supplied start height. -func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, client node.EthClient, contracts config.L1Contracts) (*L1ETL, error) { +func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, client node.EthClient, + contracts config.L1Contracts, shutdown context.CancelCauseFunc) (*L1ETL, error) { log = log.New("etl", "l1") zeroAddr := common.Address{} @@ -71,8 +82,10 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli } // NOTE - The use of un-buffered channel here assumes that downstream consumers - // will be able to keep up with the rate of incoming batches - etlBatches := make(chan ETLBatch) + // will be able to keep up with the rate of incoming batches. + // When the producer closes the channel we stop consuming from it. + etlBatches := make(chan *ETLBatch) + etl := ETL{ loopInterval: time.Duration(cfg.LoopIntervalMsec) * time.Millisecond, headerBufferSize: uint64(cfg.HeaderBufferSize), @@ -86,81 +99,115 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli EthClient: client, } - return &L1ETL{ETL: etl, db: db, mu: new(sync.Mutex)}, nil + resCtx, resCancel := context.WithCancel(context.Background()) + return &L1ETL{ + ETL: etl, + db: db, + resourceCtx: resCtx, + resourceCancel: resCancel, + tasks: tasks.Group{HandleCrit: func(err error) { + shutdown(fmt.Errorf("critical error in L1 ETL: %w", err)) + }}, + }, nil } -func (l1Etl *L1ETL) Start(ctx context.Context) error { - errCh := make(chan error, 1) - go func() { - errCh <- l1Etl.ETL.Start(ctx) - }() +func (l1Etl *L1ETL) Close() error { + var result error + // close the producer + if err := l1Etl.ETL.Close(); err != nil { + result = errors.Join(result, fmt.Errorf("failed to close internal ETL: %w", err)) + } + // tell the consumer it can stop what it's doing + l1Etl.resourceCancel() + // wait for consumer to pick up on closure of producer + if err := l1Etl.tasks.Wait(); err != nil { + result = errors.Join(result, fmt.Errorf("failed to await batch handler completion: %w", err)) + } + return result +} - for { - select { - case err := <-errCh: - return err - - // Index incoming batches (only L1 blocks that have an emitted log) - case batch := <-l1Etl.etlBatches: - l1BlockHeaders := make([]database.L1BlockHeader, 0, len(batch.Headers)) - for i := range batch.Headers { - if _, ok := batch.HeadersWithLog[batch.Headers[i].Hash()]; ok { - l1BlockHeaders = append(l1BlockHeaders, database.L1BlockHeader{BlockHeader: database.BlockHeaderFromHeader(&batch.Headers[i])}) - } +func (l1Etl *L1ETL) Start() error { + // start ETL batch producer + if err := l1Etl.ETL.Start(); err != nil { + return fmt.Errorf("failed to start internal ETL: %w", err) + } + // start ETL batch consumer + l1Etl.tasks.Go(func() error { + for { + // Index incoming batches (only L1 blocks that have an emitted log) + batch, ok := <-l1Etl.etlBatches + if !ok { + l1Etl.log.Info("No more batches, shutting down L1 batch handler") + return nil } - if len(l1BlockHeaders) == 0 { - batch.Logger.Info("no l1 blocks with logs in batch") - continue + if err := l1Etl.handleBatch(batch); err != nil { + return fmt.Errorf("failed to handle batch, stopping L2 ETL: %w", err) } + } + }) + return nil +} - l1ContractEvents := make([]database.L1ContractEvent, len(batch.Logs)) - for i := range batch.Logs { - timestamp := batch.HeaderMap[batch.Logs[i].BlockHash].Time - l1ContractEvents[i] = database.L1ContractEvent{ContractEvent: database.ContractEventFromLog(&batch.Logs[i], timestamp)} - } +func (l1Etl *L1ETL) handleBatch(batch *ETLBatch) error { + l1BlockHeaders := make([]database.L1BlockHeader, 0, len(batch.Headers)) + for i := range batch.Headers { + if _, ok := batch.HeadersWithLog[batch.Headers[i].Hash()]; ok { + l1BlockHeaders = append(l1BlockHeaders, database.L1BlockHeader{BlockHeader: database.BlockHeaderFromHeader(&batch.Headers[i])}) + } + } + + if len(l1BlockHeaders) == 0 { + batch.Logger.Info("no l1 blocks with logs in batch") + return nil + } + + l1ContractEvents := make([]database.L1ContractEvent, len(batch.Logs)) + for i := range batch.Logs { + timestamp := batch.HeaderMap[batch.Logs[i].BlockHash].Time + l1ContractEvents[i] = database.L1ContractEvent{ContractEvent: database.ContractEventFromLog(&batch.Logs[i], timestamp)} + l1Etl.ETL.metrics.RecordIndexedLog(batch.Logs[i].Address) + } - // Continually try to persist this batch. If it fails after 10 attempts, we simply error out - retryStrategy := &retry.ExponentialStrategy{Min: 1000, Max: 20_000, MaxJitter: 250} - if _, err := retry.Do[interface{}](ctx, 10, retryStrategy, func() (interface{}, error) { - if err := l1Etl.db.Transaction(func(tx *database.DB) error { - if err := tx.Blocks.StoreL1BlockHeaders(l1BlockHeaders); err != nil { - return err - } - // we must have logs if we have l1 blocks - if err := tx.ContractEvents.StoreL1ContractEvents(l1ContractEvents); err != nil { - return err - } - return nil - }); err != nil { - batch.Logger.Error("unable to persist batch", "err", err) - return nil, err - } - - l1Etl.ETL.metrics.RecordIndexedHeaders(len(l1BlockHeaders)) - l1Etl.ETL.metrics.RecordIndexedLatestHeight(l1BlockHeaders[len(l1BlockHeaders)-1].Number) - l1Etl.ETL.metrics.RecordIndexedLogs(len(l1ContractEvents)) - - // a-ok! - return nil, nil - }); err != nil { + // Continually try to persist this batch. If it fails after 10 attempts, we simply error out + retryStrategy := &retry.ExponentialStrategy{Min: 1000, Max: 20_000, MaxJitter: 250} + if _, err := retry.Do[interface{}](l1Etl.resourceCtx, 10, retryStrategy, func() (interface{}, error) { + if err := l1Etl.db.Transaction(func(tx *database.DB) error { + if err := tx.Blocks.StoreL1BlockHeaders(l1BlockHeaders); err != nil { return err } - - batch.Logger.Info("indexed batch") - - // Notify Listeners - l1Etl.mu.Lock() - for i := range l1Etl.listeners { - select { - case l1Etl.listeners[i] <- struct{}{}: - default: - // do nothing if the listener hasn't picked - // up the previous notif - } + // we must have logs if we have l1 blocks + if err := tx.ContractEvents.StoreL1ContractEvents(l1ContractEvents); err != nil { + return err } - l1Etl.mu.Unlock() + return nil + }); err != nil { + batch.Logger.Error("unable to persist batch", "err", err) + return nil, fmt.Errorf("unable to persist batch: %w", err) + } + + l1Etl.ETL.metrics.RecordIndexedHeaders(len(l1BlockHeaders)) + l1Etl.ETL.metrics.RecordIndexedLatestHeight(l1BlockHeaders[len(l1BlockHeaders)-1].Number) + + // a-ok! + return nil, nil + }); err != nil { + return err + } + + batch.Logger.Info("indexed batch") + + // Notify Listeners + l1Etl.mu.Lock() + for i := range l1Etl.listeners { + select { + case l1Etl.listeners[i] <- struct{}{}: + default: + // do nothing if the listener hasn't picked + // up the previous notif } } + l1Etl.mu.Unlock() + return nil } // Notify returns a channel that'll receive a value every time new data has diff --git a/indexer/etl/l1_etl_test.go b/indexer/etl/l1_etl_test.go index c64167f173ca..7ae204afe123 100644 --- a/indexer/etl/l1_etl_test.go +++ b/indexer/etl/l1_etl_test.go @@ -62,7 +62,7 @@ func TestL1ETLConstruction(t *testing.T) { }, assertion: func(etl *L1ETL, err error) { require.NoError(t, err) - require.Equal(t, etl.headerTraversal.LastHeader().ParentHash, common.HexToHash("0x69")) + require.Equal(t, etl.headerTraversal.LastTraversedHeader().ParentHash, common.HexToHash("0x69")) }, }, { @@ -94,7 +94,7 @@ func TestL1ETLConstruction(t *testing.T) { }, assertion: func(etl *L1ETL, err error) { require.NoError(t, err) - header := etl.headerTraversal.LastHeader() + header := etl.headerTraversal.LastTraversedHeader() require.True(t, header.Number.Cmp(big.NewInt(69)) == 0) }, @@ -108,7 +108,9 @@ func TestL1ETLConstruction(t *testing.T) { logger := testlog.Logger(t, log.LvlInfo) cfg := Config{StartHeight: ts.start} - etl, err := NewL1ETL(cfg, logger, ts.db.DB, etlMetrics, ts.client, ts.contracts) + etl, err := NewL1ETL(cfg, logger, ts.db.DB, etlMetrics, ts.client, ts.contracts, func(cause error) { + t.Fatalf("crit error: %v", cause) + }) test.assertion(etl, err) }) } diff --git a/indexer/etl/l2_etl.go b/indexer/etl/l2_etl.go index 72dfff8c7455..36fa7574b489 100644 --- a/indexer/etl/l2_etl.go +++ b/indexer/etl/l2_etl.go @@ -3,24 +3,34 @@ package etl import ( "context" "errors" + "fmt" "time" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/node" "github.com/ethereum-optimism/optimism/op-service/retry" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-service/tasks" ) type L2ETL struct { ETL + // the batch handler may do work that we can interrupt on shutdown + resourceCtx context.Context + resourceCancel context.CancelFunc + + tasks tasks.Group + db *database.DB } -func NewL2ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, client node.EthClient, contracts config.L2Contracts) (*L2ETL, error) { +func NewL2ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, client node.EthClient, + contracts config.L2Contracts, shutdown context.CancelCauseFunc) (*L2ETL, error) { log = log.New("etl", "l2") zeroAddr := common.Address{} @@ -54,7 +64,7 @@ func NewL2ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli log.Info("no indexed state, starting from genesis") } - etlBatches := make(chan ETLBatch) + etlBatches := make(chan *ETLBatch) etl := ETL{ loopInterval: time.Duration(cfg.LoopIntervalMsec) * time.Millisecond, headerBufferSize: uint64(cfg.HeaderBufferSize), @@ -68,64 +78,96 @@ func NewL2ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli EthClient: client, } - return &L2ETL{ETL: etl, db: db}, nil + resCtx, resCancel := context.WithCancel(context.Background()) + return &L2ETL{ + ETL: etl, + resourceCtx: resCtx, + resourceCancel: resCancel, + db: db, + tasks: tasks.Group{HandleCrit: func(err error) { + shutdown(fmt.Errorf("critical error in L2 ETL: %w", err)) + }}, + }, nil } -func (l2Etl *L2ETL) Start(ctx context.Context) error { - errCh := make(chan error, 1) - go func() { - errCh <- l2Etl.ETL.Start(ctx) - }() - - for { - select { - case err := <-errCh: - return err - - // Index incoming batches (all L2 Blocks) - case batch := <-l2Etl.etlBatches: - l2BlockHeaders := make([]database.L2BlockHeader, len(batch.Headers)) - for i := range batch.Headers { - l2BlockHeaders[i] = database.L2BlockHeader{BlockHeader: database.BlockHeaderFromHeader(&batch.Headers[i])} - } +func (l2Etl *L2ETL) Close() error { + var result error + // close the producer + if err := l2Etl.ETL.Close(); err != nil { + result = errors.Join(result, fmt.Errorf("failed to close internal ETL: %w", err)) + } + // tell the consumer it can stop what it's doing + l2Etl.resourceCancel() + // wait for consumer to pick up on closure of producer + if err := l2Etl.tasks.Wait(); err != nil { + result = errors.Join(result, fmt.Errorf("failed to await batch handler completion: %w", err)) + } + return result +} + +func (l2Etl *L2ETL) Start() error { + // start ETL batch producer + if err := l2Etl.ETL.Start(); err != nil { + return fmt.Errorf("failed to start internal ETL: %w", err) + } - l2ContractEvents := make([]database.L2ContractEvent, len(batch.Logs)) - for i := range batch.Logs { - timestamp := batch.HeaderMap[batch.Logs[i].BlockHash].Time - l2ContractEvents[i] = database.L2ContractEvent{ContractEvent: database.ContractEventFromLog(&batch.Logs[i], timestamp)} + // start ETL batch consumer + l2Etl.tasks.Go(func() error { + for { + // Index incoming batches (all L2 blocks) + batch, ok := <-l2Etl.etlBatches + if !ok { + l2Etl.log.Info("No more batches, shutting down L2 batch handler") + return nil } + if err := l2Etl.handleBatch(batch); err != nil { + return fmt.Errorf("failed to handle batch, stopping L2 ETL: %w", err) + } + } + }) + return nil +} - // Continually try to persist this batch. If it fails after 10 attempts, we simply error out - retryStrategy := &retry.ExponentialStrategy{Min: 1000, Max: 20_000, MaxJitter: 250} - if _, err := retry.Do[interface{}](ctx, 10, retryStrategy, func() (interface{}, error) { - if err := l2Etl.db.Transaction(func(tx *database.DB) error { - if err := tx.Blocks.StoreL2BlockHeaders(l2BlockHeaders); err != nil { - return err - } - if len(l2ContractEvents) > 0 { - if err := tx.ContractEvents.StoreL2ContractEvents(l2ContractEvents); err != nil { - return err - } - } - return nil - }); err != nil { - batch.Logger.Error("unable to persist batch", "err", err) - return nil, err - } +func (l2Etl *L2ETL) handleBatch(batch *ETLBatch) error { + l2BlockHeaders := make([]database.L2BlockHeader, len(batch.Headers)) + for i := range batch.Headers { + l2BlockHeaders[i] = database.L2BlockHeader{BlockHeader: database.BlockHeaderFromHeader(&batch.Headers[i])} + } - l2Etl.ETL.metrics.RecordIndexedHeaders(len(l2BlockHeaders)) - l2Etl.ETL.metrics.RecordIndexedLatestHeight(l2BlockHeaders[len(l2BlockHeaders)-1].Number) - if len(l2ContractEvents) > 0 { - l2Etl.ETL.metrics.RecordIndexedLogs(len(l2ContractEvents)) - } + l2ContractEvents := make([]database.L2ContractEvent, len(batch.Logs)) + for i := range batch.Logs { + timestamp := batch.HeaderMap[batch.Logs[i].BlockHash].Time + l2ContractEvents[i] = database.L2ContractEvent{ContractEvent: database.ContractEventFromLog(&batch.Logs[i], timestamp)} + l2Etl.ETL.metrics.RecordIndexedLog(batch.Logs[i].Address) + } - // a-ok! - return nil, nil - }); err != nil { + // Continually try to persist this batch. If it fails after 10 attempts, we simply error out + retryStrategy := &retry.ExponentialStrategy{Min: 1000, Max: 20_000, MaxJitter: 250} + if _, err := retry.Do[interface{}](l2Etl.resourceCtx, 10, retryStrategy, func() (interface{}, error) { + if err := l2Etl.db.Transaction(func(tx *database.DB) error { + if err := tx.Blocks.StoreL2BlockHeaders(l2BlockHeaders); err != nil { return err } - - batch.Logger.Info("indexed batch") + if len(l2ContractEvents) > 0 { + if err := tx.ContractEvents.StoreL2ContractEvents(l2ContractEvents); err != nil { + return err + } + } + return nil + }); err != nil { + batch.Logger.Error("unable to persist batch", "err", err) + return nil, err } + + l2Etl.ETL.metrics.RecordIndexedHeaders(len(l2BlockHeaders)) + l2Etl.ETL.metrics.RecordIndexedLatestHeight(l2BlockHeaders[len(l2BlockHeaders)-1].Number) + + // a-ok! + return nil, nil + }); err != nil { + return err } + + batch.Logger.Info("indexed batch") + return nil } diff --git a/indexer/etl/metrics.go b/indexer/etl/metrics.go index 5cc75ff0ecb8..3a2e70ccc770 100644 --- a/indexer/etl/metrics.go +++ b/indexer/etl/metrics.go @@ -9,35 +9,28 @@ import ( ) var ( - MetricsNamespace string = "etl" + MetricsNamespace string = "op_indexer_etl" ) type Metricer interface { RecordInterval() (done func(err error)) - - // Batch Extraction - RecordBatchLatestHeight(height *big.Int) - RecordBatchHeaders(size int) - RecordBatchLog(contractAddress common.Address) + RecordLatestHeight(height *big.Int) // Indexed Batches RecordIndexedLatestHeight(height *big.Int) RecordIndexedHeaders(size int) - RecordIndexedLogs(size int) + RecordIndexedLog(contractAddress common.Address) } type etlMetrics struct { intervalTick prometheus.Counter intervalDuration prometheus.Histogram - - batchFailures prometheus.Counter - batchLatestHeight prometheus.Gauge - batchHeaders prometheus.Counter - batchLogs *prometheus.CounterVec + intervalFailures prometheus.Counter + latestHeight prometheus.Gauge indexedLatestHeight prometheus.Gauge indexedHeaders prometheus.Counter - indexedLogs prometheus.Counter + indexedLogs *prometheus.CounterVec } func NewMetrics(registry *prometheus.Registry, subsystem string) Metricer { @@ -55,31 +48,17 @@ func NewMetrics(registry *prometheus.Registry, subsystem string) Metricer { Name: "interval_seconds", Help: "duration elapsed for during the processing loop", }), - batchFailures: factory.NewCounter(prometheus.CounterOpts{ - Namespace: MetricsNamespace, - Subsystem: subsystem, - Name: "failures_total", - Help: "number of times the etl encountered a failure to extract a batch", - }), - batchLatestHeight: factory.NewGauge(prometheus.GaugeOpts{ + intervalFailures: factory.NewCounter(prometheus.CounterOpts{ Namespace: MetricsNamespace, Subsystem: subsystem, - Name: "height", - Help: "the latest block height observed by an etl interval", + Name: "interval_failures_total", + Help: "number of times the etl encountered a failure during the processing loop", }), - batchHeaders: factory.NewCounter(prometheus.CounterOpts{ + latestHeight: factory.NewGauge(prometheus.GaugeOpts{ Namespace: MetricsNamespace, Subsystem: subsystem, - Name: "headers_total", - Help: "number of headers observed by the etl", - }), - batchLogs: factory.NewCounterVec(prometheus.CounterOpts{ - Namespace: MetricsNamespace, - Subsystem: subsystem, - Name: "logs_total", - Help: "number of logs observed by the etl", - }, []string{ - "contract", + Name: "latest_height", + Help: "the latest height reported by the connected client", }), indexedLatestHeight: factory.NewGauge(prometheus.GaugeOpts{ Namespace: MetricsNamespace, @@ -93,11 +72,13 @@ func NewMetrics(registry *prometheus.Registry, subsystem string) Metricer { Name: "indexed_headers_total", Help: "number of headers indexed by the etl", }), - indexedLogs: factory.NewCounter(prometheus.CounterOpts{ + indexedLogs: factory.NewCounterVec(prometheus.CounterOpts{ Namespace: MetricsNamespace, Subsystem: subsystem, Name: "indexed_logs_total", Help: "number of logs indexed by the etl", + }, []string{ + "contract", }), } } @@ -107,23 +88,14 @@ func (m *etlMetrics) RecordInterval() func(error) { timer := prometheus.NewTimer(m.intervalDuration) return func(err error) { if err != nil { - m.batchFailures.Inc() + m.intervalFailures.Inc() } - timer.ObserveDuration() } } -func (m *etlMetrics) RecordBatchLatestHeight(height *big.Int) { - m.batchLatestHeight.Set(float64(height.Uint64())) -} - -func (m *etlMetrics) RecordBatchHeaders(size int) { - m.batchHeaders.Add(float64(size)) -} - -func (m *etlMetrics) RecordBatchLog(contractAddress common.Address) { - m.batchLogs.WithLabelValues(contractAddress.String()).Inc() +func (m *etlMetrics) RecordLatestHeight(height *big.Int) { + m.latestHeight.Set(float64(height.Uint64())) } func (m *etlMetrics) RecordIndexedLatestHeight(height *big.Int) { @@ -134,6 +106,6 @@ func (m *etlMetrics) RecordIndexedHeaders(size int) { m.indexedHeaders.Add(float64(size)) } -func (m *etlMetrics) RecordIndexedLogs(size int) { - m.indexedLogs.Add(float64(size)) +func (m *etlMetrics) RecordIndexedLog(addr common.Address) { + m.indexedLogs.WithLabelValues(addr.String()).Inc() } diff --git a/indexer/indexer.go b/indexer/indexer.go index 07f566650604..5509d80dc1d1 100644 --- a/indexer/indexer.go +++ b/indexer/indexer.go @@ -2,12 +2,12 @@ package indexer import ( "context" + "errors" "fmt" "math/big" "net" - "runtime/debug" "strconv" - "sync" + "sync/atomic" "github.com/ethereum/go-ethereum/log" @@ -30,149 +30,230 @@ import ( // indexing the configured L1 and L2 chains type Indexer struct { log log.Logger - db *database.DB + DB *database.DB + + l1Client node.EthClient + l2Client node.EthClient + + // api server only really serves a /health endpoint here, but this may change in the future + apiServer *httputil.HTTPServer + + metricsServer *httputil.HTTPServer - httpConfig config.ServerConfig - metricsConfig config.ServerConfig metricsRegistry *prometheus.Registry L1ETL *etl.L1ETL L2ETL *etl.L2ETL BridgeProcessor *processors.BridgeProcessor + + // shutdown requests the service that maintains the indexer to shut down, + // and provides the error-cause of the critical failure (if any). + shutdown context.CancelCauseFunc + + stopped atomic.Bool } // NewIndexer initializes an instance of the Indexer -func NewIndexer( - log log.Logger, - db *database.DB, - chainConfig config.ChainConfig, - rpcsConfig config.RPCsConfig, - httpConfig config.ServerConfig, - metricsConfig config.ServerConfig, -) (*Indexer, error) { - metricsRegistry := metrics.NewRegistry() - - // L1 - l1EthClient, err := node.DialEthClient(rpcsConfig.L1RPC, node.NewMetrics(metricsRegistry, "l1")) +func NewIndexer(ctx context.Context, log log.Logger, cfg *config.Config, shutdown context.CancelCauseFunc) (*Indexer, error) { + out := &Indexer{ + log: log, + metricsRegistry: metrics.NewRegistry(), + shutdown: shutdown, + } + if err := out.initFromConfig(ctx, cfg); err != nil { + return nil, errors.Join(err, out.Stop(ctx)) + } + return out, nil +} + +func (ix *Indexer) Start(ctx context.Context) error { + // If any of these services has a critical failure, + // the service can request a shutdown, while providing the error cause. + if err := ix.L1ETL.Start(); err != nil { + return fmt.Errorf("failed to start L1 ETL: %w", err) + } + if err := ix.L2ETL.Start(); err != nil { + return fmt.Errorf("failed to start L2 ETL: %w", err) + } + if err := ix.BridgeProcessor.Start(); err != nil { + return fmt.Errorf("failed to start bridge processor: %w", err) + } + return nil +} + +func (ix *Indexer) Stop(ctx context.Context) error { + var result error + + if ix.L1ETL != nil { + if err := ix.L1ETL.Close(); err != nil { + result = errors.Join(result, fmt.Errorf("failed to close L1 ETL: %w", err)) + } + } + + if ix.L2ETL != nil { + if err := ix.L2ETL.Close(); err != nil { + result = errors.Join(result, fmt.Errorf("failed to close L2 ETL: %w", err)) + } + } + + if ix.BridgeProcessor != nil { + if err := ix.BridgeProcessor.Close(); err != nil { + result = errors.Join(result, fmt.Errorf("failed to close bridge processor: %w", err)) + } + } + + // Now that the ETLs are closed, we can stop the RPC clients + if ix.l1Client != nil { + ix.l1Client.Close() + } + if ix.l2Client != nil { + ix.l2Client.Close() + } + + if ix.apiServer != nil { + if err := ix.apiServer.Close(); err != nil { + result = errors.Join(result, fmt.Errorf("failed to close indexer API server: %w", err)) + } + } + + // DB connection can be closed last, after all its potential users have shut down + if ix.DB != nil { + if err := ix.DB.Close(); err != nil { + result = errors.Join(result, fmt.Errorf("failed to close DB: %w", err)) + } + } + + if ix.metricsServer != nil { + if err := ix.metricsServer.Close(); err != nil { + result = errors.Join(result, fmt.Errorf("failed to close metrics server: %w", err)) + } + } + + ix.stopped.Store(true) + + ix.log.Info("indexer stopped") + + return result +} + +func (ix *Indexer) Stopped() bool { + return ix.stopped.Load() +} + +func (ix *Indexer) initFromConfig(ctx context.Context, cfg *config.Config) error { + if err := ix.initRPCClients(ctx, cfg.RPCs); err != nil { + return fmt.Errorf("failed to start RPC clients: %w", err) + } + if err := ix.initDB(ctx, cfg.DB); err != nil { + return fmt.Errorf("failed to init DB: %w", err) + } + if err := ix.initL1ETL(cfg.Chain); err != nil { + return fmt.Errorf("failed to init L1 ETL: %w", err) + } + if err := ix.initL2ETL(cfg.Chain); err != nil { + return fmt.Errorf("failed to init L2 ETL: %w", err) + } + if err := ix.initBridgeProcessor(cfg.Chain); err != nil { + return fmt.Errorf("failed to init Bridge-Processor: %w", err) + } + if err := ix.startHttpServer(ctx, cfg.HTTPServer); err != nil { + return fmt.Errorf("failed to start HTTP server: %w", err) + } + if err := ix.startMetricsServer(ctx, cfg.MetricsServer); err != nil { + return fmt.Errorf("failed to start Metrics server: %w", err) + } + return nil +} + +func (ix *Indexer) initRPCClients(ctx context.Context, rpcsConfig config.RPCsConfig) error { + l1EthClient, err := node.DialEthClient(ctx, rpcsConfig.L1RPC, node.NewMetrics(ix.metricsRegistry, "l1")) + if err != nil { + return fmt.Errorf("failed to dial L1 client: %w", err) + } + ix.l1Client = l1EthClient + + l2EthClient, err := node.DialEthClient(ctx, rpcsConfig.L2RPC, node.NewMetrics(ix.metricsRegistry, "l2")) + if err != nil { + return fmt.Errorf("failed to dial L2 client: %w", err) + } + ix.l2Client = l2EthClient + return nil +} + +func (ix *Indexer) initDB(ctx context.Context, cfg config.DBConfig) error { + db, err := database.NewDB(ctx, ix.log, cfg) if err != nil { - return nil, err + return fmt.Errorf("failed to connect to database: %w", err) } + ix.DB = db + return nil +} + +func (ix *Indexer) initL1ETL(chainConfig config.ChainConfig) error { l1Cfg := etl.Config{ LoopIntervalMsec: chainConfig.L1PollingInterval, HeaderBufferSize: chainConfig.L1HeaderBufferSize, ConfirmationDepth: big.NewInt(int64(chainConfig.L1ConfirmationDepth)), StartHeight: big.NewInt(int64(chainConfig.L1StartingHeight)), } - l1Etl, err := etl.NewL1ETL(l1Cfg, log, db, etl.NewMetrics(metricsRegistry, "l1"), l1EthClient, chainConfig.L1Contracts) + l1Etl, err := etl.NewL1ETL(l1Cfg, ix.log, ix.DB, etl.NewMetrics(ix.metricsRegistry, "l1"), + ix.l1Client, chainConfig.L1Contracts, ix.shutdown) if err != nil { - return nil, err + return err } + ix.L1ETL = l1Etl + return nil +} +func (ix *Indexer) initL2ETL(chainConfig config.ChainConfig) error { // L2 (defaults to predeploy contracts) - l2EthClient, err := node.DialEthClient(rpcsConfig.L2RPC, node.NewMetrics(metricsRegistry, "l2")) - if err != nil { - return nil, err - } l2Cfg := etl.Config{ LoopIntervalMsec: chainConfig.L2PollingInterval, HeaderBufferSize: chainConfig.L2HeaderBufferSize, ConfirmationDepth: big.NewInt(int64(chainConfig.L2ConfirmationDepth)), } - l2Etl, err := etl.NewL2ETL(l2Cfg, log, db, etl.NewMetrics(metricsRegistry, "l2"), l2EthClient, chainConfig.L2Contracts) + l2Etl, err := etl.NewL2ETL(l2Cfg, ix.log, ix.DB, etl.NewMetrics(ix.metricsRegistry, "l2"), + ix.l2Client, chainConfig.L2Contracts, ix.shutdown) if err != nil { - return nil, err + return err } + ix.L2ETL = l2Etl + return nil +} - // Bridge - bridgeProcessor, err := processors.NewBridgeProcessor(log, db, bridge.NewMetrics(metricsRegistry), l1Etl, chainConfig) +func (ix *Indexer) initBridgeProcessor(chainConfig config.ChainConfig) error { + bridgeProcessor, err := processors.NewBridgeProcessor( + ix.log, ix.DB, bridge.NewMetrics(ix.metricsRegistry), ix.L1ETL, chainConfig, ix.shutdown) if err != nil { - return nil, err + return err } - - indexer := &Indexer{ - log: log, - db: db, - - httpConfig: httpConfig, - metricsConfig: metricsConfig, - metricsRegistry: metricsRegistry, - - L1ETL: l1Etl, - L2ETL: l2Etl, - BridgeProcessor: bridgeProcessor, - } - - return indexer, nil + ix.BridgeProcessor = bridgeProcessor + return nil } -func (i *Indexer) startHttpServer(ctx context.Context) error { - i.log.Debug("starting http server...", "port", i.httpConfig.Host) +func (ix *Indexer) startHttpServer(ctx context.Context, cfg config.ServerConfig) error { + ix.log.Debug("starting http server...", "port", cfg.Port) r := chi.NewRouter() r.Use(middleware.Heartbeat("/healthz")) - addr := net.JoinHostPort(i.httpConfig.Host, strconv.Itoa(i.httpConfig.Port)) + addr := net.JoinHostPort(cfg.Host, strconv.Itoa(cfg.Port)) srv, err := httputil.StartHTTPServer(addr, r) if err != nil { return fmt.Errorf("http server failed to start: %w", err) } - i.log.Info("http server started", "addr", srv.Addr()) - <-ctx.Done() - defer i.log.Info("http server stopped") - return srv.Stop(context.Background()) + ix.apiServer = srv + ix.log.Info("http server started", "addr", srv.Addr()) + return nil } -func (i *Indexer) startMetricsServer(ctx context.Context) error { - i.log.Debug("starting metrics server...", "port", i.metricsConfig.Port) - srv, err := metrics.StartServer(i.metricsRegistry, i.metricsConfig.Host, i.metricsConfig.Port) +func (ix *Indexer) startMetricsServer(ctx context.Context, cfg config.ServerConfig) error { + ix.log.Debug("starting metrics server...", "port", cfg.Port) + srv, err := metrics.StartServer(ix.metricsRegistry, cfg.Host, cfg.Port) if err != nil { return fmt.Errorf("metrics server failed to start: %w", err) } - i.log.Info("metrics server started", "addr", srv.Addr()) - <-ctx.Done() - defer i.log.Info("metrics server stopped") - return srv.Stop(context.Background()) -} - -// Start starts the indexing service on L1 and L2 chains -func (i *Indexer) Run(ctx context.Context) error { - var wg sync.WaitGroup - errCh := make(chan error, 5) - - // if any goroutine halts, we stop the entire indexer - processCtx, processCancel := context.WithCancel(ctx) - runProcess := func(start func(ctx context.Context) error) { - wg.Add(1) - go func() { - defer func() { - if err := recover(); err != nil { - i.log.Error("halting indexer on panic", "err", err) - debug.PrintStack() - errCh <- fmt.Errorf("panic: %v", err) - } - - processCancel() - wg.Done() - }() - - errCh <- start(processCtx) - }() - } - - // Kick off all the dependent routines - runProcess(i.L1ETL.Start) - runProcess(i.L2ETL.Start) - runProcess(i.BridgeProcessor.Start) - runProcess(i.startMetricsServer) - runProcess(i.startHttpServer) - wg.Wait() - - err := <-errCh - if err != nil { - i.log.Error("indexer stopped", "err", err) - } else { - i.log.Info("indexer stopped") - } - - return err + ix.metricsServer = srv + ix.log.Info("metrics server started", "addr", srv.Addr()) + return nil } diff --git a/indexer/indexer.toml b/indexer/indexer.toml index b85c2008df27..3f18f6f3df5a 100644 --- a/indexer/indexer.toml +++ b/indexer/indexer.toml @@ -29,6 +29,7 @@ name = "$INDEXER_DB_NAME" [http] host = "127.0.0.1" port = 8080 +timeout = 10 [metrics] host = "127.0.0.1" diff --git a/indexer/node/client.go b/indexer/node/client.go index be046f930b48..1ad6f0a21e0a 100644 --- a/indexer/node/client.go +++ b/indexer/node/client.go @@ -40,23 +40,27 @@ type EthClient interface { StorageHash(common.Address, *big.Int) (common.Hash, error) FilterLogs(ethereum.FilterQuery) (Logs, error) + + // Close closes the underlying RPC connection. + // RPC close does not return any errors, but does shut down e.g. a websocket connection. + Close() } type clnt struct { rpc RPC } -func DialEthClient(rpcUrl string, metrics Metricer) (EthClient, error) { - ctxwt, cancel := context.WithTimeout(context.Background(), defaultDialTimeout) +func DialEthClient(ctx context.Context, rpcUrl string, metrics Metricer) (EthClient, error) { + ctx, cancel := context.WithTimeout(ctx, defaultDialTimeout) defer cancel() bOff := retry.Exponential() - rpcClient, err := retry.Do(ctxwt, defaultDialAttempts, bOff, func() (*rpc.Client, error) { + rpcClient, err := retry.Do(ctx, defaultDialAttempts, bOff, func() (*rpc.Client, error) { if !client.IsURLAvailable(rpcUrl) { return nil, fmt.Errorf("address unavailable (%s)", rpcUrl) } - client, err := rpc.DialContext(ctxwt, rpcUrl) + client, err := rpc.DialContext(ctx, rpcUrl) if err != nil { return nil, fmt.Errorf("failed to dial address (%s): %w", rpcUrl, err) } @@ -192,6 +196,10 @@ func (c *clnt) StorageHash(address common.Address, blockNumber *big.Int) (common return proof.StorageHash, nil } +func (c *clnt) Close() { + c.rpc.Close() +} + type Logs struct { Logs []types.Log ToBlockHeader *types.Header diff --git a/indexer/node/client_test.go b/indexer/node/client_test.go index 39e7eb2974a7..78cf5b5b82a5 100644 --- a/indexer/node/client_test.go +++ b/indexer/node/client_test.go @@ -1,6 +1,7 @@ package node import ( + "context" "fmt" "net" "strings" @@ -21,14 +22,14 @@ func TestDialEthClientUnavailable(t *testing.T) { metrics := &clientMetrics{} // available - _, err = DialEthClient(addr, metrics) + _, err = DialEthClient(context.Background(), addr, metrics) require.NoError(t, err) // :0 requests a new unbound port - _, err = DialEthClient("http://localhost:0", metrics) + _, err = DialEthClient(context.Background(), "http://localhost:0", metrics) require.Error(t, err) // Fail open if we don't recognize the scheme - _, err = DialEthClient("mailto://example.com", metrics) + _, err = DialEthClient(context.Background(), "mailto://example.com", metrics) require.Error(t, err) } diff --git a/indexer/node/header_traversal.go b/indexer/node/header_traversal.go index e925747f2185..3546aa8d1e46 100644 --- a/indexer/node/header_traversal.go +++ b/indexer/node/header_traversal.go @@ -17,38 +17,56 @@ var ( type HeaderTraversal struct { ethClient EthClient - lastHeader *types.Header + latestHeader *types.Header + lastTraversedHeader *types.Header + blockConfirmationDepth *big.Int } // NewHeaderTraversal instantiates a new instance of HeaderTraversal against the supplied rpc client. // The HeaderTraversal will start fetching blocks starting from the supplied header unless nil, indicating genesis. func NewHeaderTraversal(ethClient EthClient, fromHeader *types.Header, confDepth *big.Int) *HeaderTraversal { - return &HeaderTraversal{ethClient: ethClient, lastHeader: fromHeader, blockConfirmationDepth: confDepth} + return &HeaderTraversal{ + ethClient: ethClient, + lastTraversedHeader: fromHeader, + blockConfirmationDepth: confDepth, + } +} + +// LatestHeader returns the latest header reported by underlying eth client +// as headers are traversed via `NextHeaders`. +func (f *HeaderTraversal) LatestHeader() *types.Header { + return f.latestHeader } -// LastHeader returns the last header that was fetched by the HeaderTraversal -// This is useful for testing the state of the HeaderTraversal -func (f *HeaderTraversal) LastHeader() *types.Header { - return f.lastHeader +// LastTraversedHeader returns the last header traversed. +// - This is useful for testing the state of the HeaderTraversal +// - LastTraversedHeader may be << LatestHeader depending on the number +// headers traversed via `NextHeaders`. +func (f *HeaderTraversal) LastTraversedHeader() *types.Header { + return f.lastTraversedHeader } -// NextFinalizedHeaders retrieves the next set of headers that have been +// NextHeaders retrieves the next set of headers that have been // marked as finalized by the connected client, bounded by the supplied size -func (f *HeaderTraversal) NextFinalizedHeaders(maxSize uint64) ([]types.Header, error) { - latestBlockHeader, err := f.ethClient.BlockHeaderByNumber(nil) +func (f *HeaderTraversal) NextHeaders(maxSize uint64) ([]types.Header, error) { + latestHeader, err := f.ethClient.BlockHeaderByNumber(nil) if err != nil { return nil, fmt.Errorf("unable to query latest block: %w", err) + } else if latestHeader == nil { + return nil, fmt.Errorf("latest header unreported") + } else { + f.latestHeader = latestHeader } - endHeight := new(big.Int).Sub(latestBlockHeader.Number, f.blockConfirmationDepth) + endHeight := new(big.Int).Sub(latestHeader.Number, f.blockConfirmationDepth) if endHeight.Sign() < 0 { // No blocks with the provided confirmation depth available return nil, nil } - if f.lastHeader != nil { - cmp := f.lastHeader.Number.Cmp(endHeight) + if f.lastTraversedHeader != nil { + cmp := f.lastTraversedHeader.Number.Cmp(endHeight) if cmp == 0 { // We're synced to head and there are no new headers return nil, nil } else if cmp > 0 { @@ -57,8 +75,8 @@ func (f *HeaderTraversal) NextFinalizedHeaders(maxSize uint64) ([]types.Header, } nextHeight := bigint.Zero - if f.lastHeader != nil { - nextHeight = new(big.Int).Add(f.lastHeader.Number, bigint.One) + if f.lastTraversedHeader != nil { + nextHeight = new(big.Int).Add(f.lastTraversedHeader.Number, bigint.One) } // endHeight = (nextHeight - endHeight) <= maxSize @@ -71,12 +89,12 @@ func (f *HeaderTraversal) NextFinalizedHeaders(maxSize uint64) ([]types.Header, numHeaders := len(headers) if numHeaders == 0 { return nil, nil - } else if f.lastHeader != nil && headers[0].ParentHash != f.lastHeader.Hash() { + } else if f.lastTraversedHeader != nil && headers[0].ParentHash != f.lastTraversedHeader.Hash() { // The indexer's state is in an irrecoverable state relative to the provider. This // should never happen since the indexer is dealing with only finalized blocks. return nil, ErrHeaderTraversalAndProviderMismatchedState } - f.lastHeader = &headers[numHeaders-1] + f.lastTraversedHeader = &headers[numHeaders-1] return headers, nil } diff --git a/indexer/node/header_traversal_test.go b/indexer/node/header_traversal_test.go index 6358fc7c8eb0..603b8fdd3a97 100644 --- a/indexer/node/header_traversal_test.go +++ b/indexer/node/header_traversal_test.go @@ -33,44 +33,55 @@ func makeHeaders(numHeaders uint64, prevHeader *types.Header) []types.Header { return headers } -func TestHeaderTraversalNextFinalizedHeadersNoOp(t *testing.T) { +func TestHeaderTraversalNextHeadersNoOp(t *testing.T) { client := new(MockEthClient) // start from block 10 as the latest fetched block - lastHeader := &types.Header{Number: big.NewInt(10)} - headerTraversal := NewHeaderTraversal(client, lastHeader, bigint.Zero) + LastTraversedHeader := &types.Header{Number: big.NewInt(10)} + headerTraversal := NewHeaderTraversal(client, LastTraversedHeader, bigint.Zero) + + require.Nil(t, headerTraversal.LatestHeader()) + require.NotNil(t, headerTraversal.LastTraversedHeader()) // no new headers when matched with head - client.On("BlockHeaderByNumber", (*big.Int)(nil)).Return(lastHeader, nil) - headers, err := headerTraversal.NextFinalizedHeaders(100) + client.On("BlockHeaderByNumber", (*big.Int)(nil)).Return(LastTraversedHeader, nil) + headers, err := headerTraversal.NextHeaders(100) require.NoError(t, err) require.Empty(t, headers) + + require.NotNil(t, headerTraversal.LatestHeader()) + require.NotNil(t, headerTraversal.LastTraversedHeader()) + require.Equal(t, LastTraversedHeader.Number.Uint64(), headerTraversal.LatestHeader().Number.Uint64()) } -func TestHeaderTraversalNextFinalizedHeadersCursored(t *testing.T) { +func TestHeaderTraversalNextHeadersCursored(t *testing.T) { client := new(MockEthClient) // start from genesis headerTraversal := NewHeaderTraversal(client, nil, bigint.Zero) - // blocks [0..4] - headers := makeHeaders(5, nil) - client.On("BlockHeaderByNumber", (*big.Int)(nil)).Return(&headers[4], nil).Times(1) // Times so that we can override next - client.On("BlockHeadersByRange", mock.MatchedBy(bigint.Matcher(0)), mock.MatchedBy(bigint.Matcher(4))).Return(headers, nil) - headers, err := headerTraversal.NextFinalizedHeaders(5) + headers := makeHeaders(10, nil) + + // blocks [0..4]. Latest reported is 7 + client.On("BlockHeaderByNumber", (*big.Int)(nil)).Return(&headers[7], nil).Times(1) // Times so that we can override next + client.On("BlockHeadersByRange", mock.MatchedBy(bigint.Matcher(0)), mock.MatchedBy(bigint.Matcher(4))).Return(headers[:5], nil) + _, err := headerTraversal.NextHeaders(5) require.NoError(t, err) - require.Len(t, headers, 5) - // blocks [5..9] - headers = makeHeaders(5, &headers[len(headers)-1]) - client.On("BlockHeaderByNumber", (*big.Int)(nil)).Return(&headers[4], nil) - client.On("BlockHeadersByRange", mock.MatchedBy(bigint.Matcher(5)), mock.MatchedBy(bigint.Matcher(9))).Return(headers, nil) - headers, err = headerTraversal.NextFinalizedHeaders(5) + require.Equal(t, uint64(7), headerTraversal.LatestHeader().Number.Uint64()) + require.Equal(t, uint64(4), headerTraversal.LastTraversedHeader().Number.Uint64()) + + // blocks [5..9]. Latest Reported is 9 + client.On("BlockHeaderByNumber", (*big.Int)(nil)).Return(&headers[9], nil) + client.On("BlockHeadersByRange", mock.MatchedBy(bigint.Matcher(5)), mock.MatchedBy(bigint.Matcher(9))).Return(headers[5:], nil) + _, err = headerTraversal.NextHeaders(5) require.NoError(t, err) - require.Len(t, headers, 5) + + require.Equal(t, uint64(9), headerTraversal.LatestHeader().Number.Uint64()) + require.Equal(t, uint64(9), headerTraversal.LastTraversedHeader().Number.Uint64()) } -func TestHeaderTraversalNextFinalizedHeadersMaxSize(t *testing.T) { +func TestHeaderTraversalNextHeadersMaxSize(t *testing.T) { client := new(MockEthClient) // start from genesis @@ -82,16 +93,22 @@ func TestHeaderTraversalNextFinalizedHeadersMaxSize(t *testing.T) { // clamped by the supplied size headers := makeHeaders(5, nil) client.On("BlockHeadersByRange", mock.MatchedBy(bigint.Matcher(0)), mock.MatchedBy(bigint.Matcher(4))).Return(headers, nil) - headers, err := headerTraversal.NextFinalizedHeaders(5) + headers, err := headerTraversal.NextHeaders(5) require.NoError(t, err) require.Len(t, headers, 5) + require.Equal(t, uint64(100), headerTraversal.LatestHeader().Number.Uint64()) + require.Equal(t, uint64(4), headerTraversal.LastTraversedHeader().Number.Uint64()) + // clamped by the supplied size. FinalizedHeight == 100 headers = makeHeaders(10, &headers[len(headers)-1]) client.On("BlockHeadersByRange", mock.MatchedBy(bigint.Matcher(5)), mock.MatchedBy(bigint.Matcher(14))).Return(headers, nil) - headers, err = headerTraversal.NextFinalizedHeaders(10) + headers, err = headerTraversal.NextHeaders(10) require.NoError(t, err) require.Len(t, headers, 10) + + require.Equal(t, uint64(100), headerTraversal.LatestHeader().Number.Uint64()) + require.Equal(t, uint64(14), headerTraversal.LastTraversedHeader().Number.Uint64()) } func TestHeaderTraversalMismatchedProviderStateError(t *testing.T) { @@ -104,7 +121,7 @@ func TestHeaderTraversalMismatchedProviderStateError(t *testing.T) { headers := makeHeaders(5, nil) client.On("BlockHeaderByNumber", (*big.Int)(nil)).Return(&headers[4], nil).Times(1) // Times so that we can override next client.On("BlockHeadersByRange", mock.MatchedBy(bigint.Matcher(0)), mock.MatchedBy(bigint.Matcher(4))).Return(headers, nil) - headers, err := headerTraversal.NextFinalizedHeaders(5) + headers, err := headerTraversal.NextHeaders(5) require.NoError(t, err) require.Len(t, headers, 5) @@ -112,7 +129,7 @@ func TestHeaderTraversalMismatchedProviderStateError(t *testing.T) { headers = makeHeaders(5, nil) client.On("BlockHeaderByNumber", (*big.Int)(nil)).Return(&types.Header{Number: big.NewInt(9)}, nil) client.On("BlockHeadersByRange", mock.MatchedBy(bigint.Matcher(5)), mock.MatchedBy(bigint.Matcher(9))).Return(headers, nil) - headers, err = headerTraversal.NextFinalizedHeaders(5) + headers, err = headerTraversal.NextHeaders(5) require.Nil(t, headers) require.Equal(t, ErrHeaderTraversalAndProviderMismatchedState, err) } diff --git a/indexer/node/metrics.go b/indexer/node/metrics.go index 2304bc18d56a..55da6a127e55 100644 --- a/indexer/node/metrics.go +++ b/indexer/node/metrics.go @@ -12,7 +12,7 @@ import ( ) var ( - MetricsNamespace = "rpc" + MetricsNamespace = "op_indexer_rpc" batchMethod = "" ) diff --git a/indexer/node/mocks.go b/indexer/node/mocks.go index b18196307ee1..e01c6fcb1bca 100644 --- a/indexer/node/mocks.go +++ b/indexer/node/mocks.go @@ -45,3 +45,6 @@ func (m *MockEthClient) FilterLogs(query ethereum.FilterQuery) (Logs, error) { args := m.Called(query) return args.Get(0).(Logs), args.Error(1) } + +func (m *MockEthClient) Close() { +} diff --git a/indexer/processors/bridge.go b/indexer/processors/bridge.go index 3471b550a961..657aa05b2316 100644 --- a/indexer/processors/bridge.go +++ b/indexer/processors/bridge.go @@ -3,16 +3,18 @@ package processors import ( "context" "errors" + "fmt" "math/big" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/indexer/bigint" "github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/etl" "github.com/ethereum-optimism/optimism/indexer/processors/bridge" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-service/tasks" ) type BridgeProcessor struct { @@ -20,6 +22,10 @@ type BridgeProcessor struct { db *database.DB metrics bridge.Metricer + resourceCtx context.Context + resourceCancel context.CancelFunc + tasks tasks.Group + l1Etl *etl.L1ETL chainConfig config.ChainConfig @@ -27,7 +33,8 @@ type BridgeProcessor struct { LatestL2Header *types.Header } -func NewBridgeProcessor(log log.Logger, db *database.DB, metrics bridge.Metricer, l1Etl *etl.L1ETL, chainConfig config.ChainConfig) (*BridgeProcessor, error) { +func NewBridgeProcessor(log log.Logger, db *database.DB, metrics bridge.Metricer, l1Etl *etl.L1ETL, + chainConfig config.ChainConfig, shutdown context.CancelCauseFunc) (*BridgeProcessor, error) { log = log.New("processor", "bridge") latestL1Header, err := db.BridgeTransactions.L1LatestBlockHeader() @@ -57,11 +64,25 @@ func NewBridgeProcessor(log log.Logger, db *database.DB, metrics bridge.Metricer log.Info("detected latest indexed bridge state", "l1_block_number", l1Height, "l2_block_number", l2Height) } - return &BridgeProcessor{log, db, metrics, l1Etl, chainConfig, l1Header, l2Header}, nil + resCtx, resCancel := context.WithCancel(context.Background()) + return &BridgeProcessor{ + log: log, + db: db, + metrics: metrics, + l1Etl: l1Etl, + resourceCtx: resCtx, + resourceCancel: resCancel, + chainConfig: chainConfig, + LatestL1Header: l1Header, + LatestL2Header: l2Header, + tasks: tasks.Group{HandleCrit: func(err error) { + shutdown(fmt.Errorf("critical error in bridge processor: %w", err)) + }}, + }, nil } -func (b *BridgeProcessor) Start(ctx context.Context) error { - done := ctx.Done() +func (b *BridgeProcessor) Start() error { + b.log.Info("starting bridge processor...") // Fire off independently on startup to check for // new data or if we've indexed new L1 data. @@ -69,21 +90,35 @@ func (b *BridgeProcessor) Start(ctx context.Context) error { startup := make(chan interface{}, 1) startup <- nil - b.log.Info("starting bridge processor...") - for { - select { - case <-done: - b.log.Info("stopping bridge processor") - return nil - - // Tickers - case <-startup: - case <-l1EtlUpdates: + b.tasks.Go(func() error { + for { + select { + case <-b.resourceCtx.Done(): + b.log.Info("stopping bridge processor") + return nil + + // Tickers + case <-startup: + case <-l1EtlUpdates: + } + + done := b.metrics.RecordInterval() + // TODO(8013): why log all the errors and return the same thing, if we just return the error, and log here? + err := b.run() + if err != nil { + b.log.Error("bridge processor error", "err", err) + } + done(err) } + }) + return nil +} - done := b.metrics.RecordInterval() - done(b.run()) - } +func (b *BridgeProcessor) Close() error { + // signal that we can stop any ongoing work + b.resourceCancel() + // await the work to stop + return b.tasks.Wait() } // Runs the processing loop. In order to ensure all seen bridge finalization events @@ -231,6 +266,9 @@ func (b *BridgeProcessor) run() error { batchLog.Info("indexed bridge events", "latest_l1_block_number", toL1Height, "latest_l2_block_number", toL2Height) b.LatestL1Header = latestEpoch.L1BlockHeader.RLPHeader.Header() + b.metrics.RecordLatestIndexedL1Height(b.LatestL1Header.Number) + b.LatestL2Header = latestEpoch.L2BlockHeader.RLPHeader.Header() + b.metrics.RecordLatestIndexedL2Height(b.LatestL2Header.Number) return nil } diff --git a/indexer/processors/bridge/metrics.go b/indexer/processors/bridge/metrics.go index 38b4f8bcb956..5d8711642c1c 100644 --- a/indexer/processors/bridge/metrics.go +++ b/indexer/processors/bridge/metrics.go @@ -10,7 +10,7 @@ import ( ) var ( - MetricsNamespace string = "bridge" + MetricsNamespace string = "op_indexer_bridge" ) type L1Metricer interface { @@ -83,7 +83,7 @@ func NewMetrics(registry *prometheus.Registry) Metricer { }), intervalFailures: factory.NewCounter(prometheus.CounterOpts{ Namespace: MetricsNamespace, - Name: "failures_total", + Name: "interval_failures_total", Help: "number of failures encountered", }), latestL1Height: factory.NewGauge(prometheus.GaugeOpts{ diff --git a/op-batcher/batcher/channel_builder_test.go b/op-batcher/batcher/channel_builder_test.go index db8e74e2e932..5ee5c5367134 100644 --- a/op-batcher/batcher/channel_builder_test.go +++ b/op-batcher/batcher/channel_builder_test.go @@ -759,7 +759,7 @@ func TestFramePublished(t *testing.T) { } func ChannelBuilder_PendingFrames_TotalFrames(t *testing.T, batchType uint) { - const tnf = 8 + const tnf = 9 rng := rand.New(rand.NewSource(94572314)) require := require.New(t) cfg := defaultTestChannelConfig @@ -828,7 +828,7 @@ func ChannelBuilder_InputBytes(t *testing.T, batchType uint) { spanBatchBuilder.AppendSingularBatch(singularBatch, l1Info.SequenceNumber) rawSpanBatch, err := spanBatchBuilder.GetRawSpanBatch() require.NoError(err) - batch := derive.NewSpanBatchData(*rawSpanBatch) + batch := derive.NewBatchData(rawSpanBatch) var buf bytes.Buffer require.NoError(batch.EncodeRLP(&buf)) l = buf.Len() @@ -878,7 +878,7 @@ func ChannelBuilder_OutputBytes(t *testing.T, batchType uint) { func blockBatchRlpSize(t *testing.T, b *types.Block) int { t.Helper() singularBatch, _, err := derive.BlockToSingularBatch(b) - batch := derive.NewSingularBatchData(*singularBatch) + batch := derive.NewBatchData(singularBatch) require.NoError(t, err) var buf bytes.Buffer require.NoError(t, batch.EncodeRLP(&buf), "RLP-encoding batch") diff --git a/op-batcher/batcher/channel_manager_test.go b/op-batcher/batcher/channel_manager_test.go index eac3cff44d11..852961c75b9a 100644 --- a/op-batcher/batcher/channel_manager_test.go +++ b/op-batcher/batcher/channel_manager_test.go @@ -318,7 +318,9 @@ func ChannelManagerCloseNoPendingChannel(t *testing.T, batchType uint) { // new channel frames after this point. func ChannelManagerClosePendingChannel(t *testing.T, batchType uint) { require := require.New(t) - rng := rand.New(rand.NewSource(time.Now().UnixNano())) + // The number of batch txs depends on compression of the random data, hence the static test RNG seed. + // Example of different RNG seed that creates less than 2 frames: 1698700588902821588 + rng := rand.New(rand.NewSource(123)) log := testlog.Logger(t, log.LvlCrit) m := NewChannelManager(log, metrics.NoopMetrics, ChannelConfig{ diff --git a/op-batcher/batcher/service.go b/op-batcher/batcher/service.go index 1c9a493d0c7e..9af086a3143a 100644 --- a/op-batcher/batcher/service.go +++ b/op-batcher/batcher/service.go @@ -290,8 +290,10 @@ func (bs *BatcherService) Stop(ctx context.Context) error { bs.Log.Info("Stopping batcher") var result error - if err := bs.driver.StopBatchSubmittingIfRunning(ctx); err != nil { - result = errors.Join(result, fmt.Errorf("failed to stop batch submitting: %w", err)) + if bs.driver != nil { + if err := bs.driver.StopBatchSubmittingIfRunning(ctx); err != nil { + result = errors.Join(result, fmt.Errorf("failed to stop batch submitting: %w", err)) + } } if bs.rpcServer != nil { @@ -328,7 +330,7 @@ func (bs *BatcherService) Stop(ctx context.Context) error { if result == nil { bs.stopped.Store(true) - bs.driver.Log.Info("Batch Submitter stopped") + bs.Log.Info("Batch Submitter stopped") } return result } diff --git a/op-batcher/cmd/main.go b/op-batcher/cmd/main.go index cc64b6eeb459..91e032ff36b4 100644 --- a/op-batcher/cmd/main.go +++ b/op-batcher/cmd/main.go @@ -1,17 +1,19 @@ package main import ( + "context" "os" - opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-batcher/batcher" "github.com/ethereum-optimism/optimism/op-batcher/flags" "github.com/ethereum-optimism/optimism/op-batcher/metrics" + opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/cliapp" oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/metrics/doc" + "github.com/ethereum-optimism/optimism/op-service/opio" "github.com/ethereum/go-ethereum/log" ) @@ -38,7 +40,8 @@ func main() { }, } - err := app.Run(os.Args) + ctx := opio.WithInterruptBlocker(context.Background()) + err := app.RunContext(ctx, os.Args) if err != nil { log.Crit("Application failed", "message", err) } diff --git a/op-bindings/bindings/alphabetvm_more.go b/op-bindings/bindings/alphabetvm_more.go index 1236b475958b..78bacad2b036 100644 --- a/op-bindings/bindings/alphabetvm_more.go +++ b/op-bindings/bindings/alphabetvm_more.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const AlphabetVMStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"test/FaultDisputeGame.t.sol:AlphabetVM\",\"label\":\"oracle\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_contract(IPreimageOracle)1001\"}],\"types\":{\"t_contract(IPreimageOracle)1001\":{\"encoding\":\"inplace\",\"label\":\"contract IPreimageOracle\",\"numberOfBytes\":\"20\"}}}" +const AlphabetVMStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"test/mocks/AlphabetVM.sol:AlphabetVM\",\"label\":\"oracle\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_contract(IPreimageOracle)1001\"}],\"types\":{\"t_contract(IPreimageOracle)1001\":{\"encoding\":\"inplace\",\"label\":\"contract IPreimageOracle\",\"numberOfBytes\":\"20\"}}}" var AlphabetVMStorageLayout = new(solc.StorageLayout) diff --git a/op-bindings/bindings/legacyerc20eth.go b/op-bindings/bindings/legacyerc20eth.go index 46f88532deaf..7b433a8206fe 100644 --- a/op-bindings/bindings/legacyerc20eth.go +++ b/op-bindings/bindings/legacyerc20eth.go @@ -31,7 +31,7 @@ var ( // LegacyERC20ETHMetaData contains all meta data concerning the LegacyERC20ETH contract. var LegacyERC20ETHMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REMOTE_TOKEN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_who\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"remoteToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101406040523480156200001257600080fd5b5073420000000000000000000000000000000000001060006040518060400160405280600581526020016422ba3432b960d91b8152506040518060400160405280600381526020016208aa8960eb1b8152506012600160026001858581600390816200007f919062000167565b5060046200008e828262000167565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff166101205262000233565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620000ed57607f821691505b6020821081036200010e57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200016257600081815260208120601f850160051c810160208610156200013d5750805b601f850160051c820191505b818110156200015e5782815560010162000149565b5050505b505050565b81516001600160401b03811115620001835762000183620000c2565b6200019b81620001948454620000d8565b8462000114565b602080601f831160018114620001d35760008415620001ba5750858301515b600019600386901b1c1916600185901b1785556200015e565b600085815260208120601f198616915b828110156200020457888601518255948401946001909101908401620001e3565b5085821015620002235787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516101005161012051610e79620002916000396000610244015260008181610309015261039e0152600081816101a9015261032f015260006107a40152600061077b015260006107520152610e796000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610353578063e78cea9214610307578063ee9a31a21461039957600080fd5b8063ae1f6aaf14610307578063c01e1bd61461032d578063d6c0b2c41461032d57600080fd5b80639dc29fac116100bd5780639dc29fac146102ce578063a457c2d7146102e1578063a9059cbb146102f457600080fd5b806370a082311461029e57806395d89b41146102c657600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004610ab1565b6103c0565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104b1565b60405161019b9190610b2a565b61018f610213366004610ba4565b610543565b6002545b60405190815260200161019b565b61018f610238366004610bce565b6105d3565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004610ba4565b61065e565b61029461028f366004610ba4565b6106e9565b005b6101f861074b565b61021c6102ac366004610c0a565b73ffffffffffffffffffffffffffffffffffffffff163190565b6101f86107ee565b6102946102dc366004610ba4565b6107fd565b61018f6102ef366004610ba4565b61085f565b61018f610302366004610ba4565b6108ea565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c610361366004610c25565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061047957507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104a857507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104c090610c58565b80601f01602080910402602001604051908101604052809291908181526020018280546104ec90610c58565b80156105395780601f1061050e57610100808354040283529160200191610539565b820191906000526020600020905b81548152906001019060200180831161051c57829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4c656761637945524332304554483a20617070726f766520697320646973616260448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526000906084015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4c656761637945524332304554483a207472616e7366657246726f6d2069732060448201527f64697361626c656400000000000000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a20696e637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206d696e742069732064697361626c656460448201526064016105ca565b60606107767f0000000000000000000000000000000000000000000000000000000000000000610974565b61079f7f0000000000000000000000000000000000000000000000000000000000000000610974565b6107c87f0000000000000000000000000000000000000000000000000000000000000000610974565b6040516020016107da93929190610cab565b604051602081830303815290604052905090565b6060600480546104c090610c58565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206275726e2069732064697361626c656460448201526064016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a206465637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4c656761637945524332304554483a207472616e73666572206973206469736160448201527f626c65640000000000000000000000000000000000000000000000000000000060648201526000906084016105ca565b6060816000036109b757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156109e157806109cb81610d50565b91506109da9050600a83610db7565b91506109bb565b60008167ffffffffffffffff8111156109fc576109fc610dcb565b6040519080825280601f01601f191660200182016040528015610a26576020820181803683370190505b5090505b8415610aa957610a3b600183610dfa565b9150610a48600a86610e11565b610a53906030610e25565b60f81b818381518110610a6857610a68610e3d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610aa2600a86610db7565b9450610a2a565b949350505050565b600060208284031215610ac357600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610af357600080fd5b9392505050565b60005b83811015610b15578181015183820152602001610afd565b83811115610b24576000848401525b50505050565b6020815260008251806020840152610b49816040850160208701610afa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b9f57600080fd5b919050565b60008060408385031215610bb757600080fd5b610bc083610b7b565b946020939093013593505050565b600080600060608486031215610be357600080fd5b610bec84610b7b565b9250610bfa60208501610b7b565b9150604084013590509250925092565b600060208284031215610c1c57600080fd5b610af382610b7b565b60008060408385031215610c3857600080fd5b610c4183610b7b565b9150610c4f60208401610b7b565b90509250929050565b600181811c90821680610c6c57607f821691505b602082108103610ca5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008451610cbd818460208901610afa565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610cf9816001850160208a01610afa565b60019201918201528351610d14816002840160208801610afa565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610d8157610d81610d21565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610dc657610dc6610d88565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015610e0c57610e0c610d21565b500390565b600082610e2057610e20610d88565b500690565b60008219821115610e3857610e38610d21565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", + Bin: "0x60e06040523480156200001157600080fd5b5073420000000000000000000000000000000000001060006040518060400160405280600581526020016422ba3432b960d91b8152506040518060400160405280600381526020016208aa8960eb1b81525060128282816003908162000078919062000152565b50600462000087828262000152565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200021e565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620000d857607f821691505b602082108103620000f957634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200014d57600081815260208120601f850160051c81016020861015620001285750805b601f850160051c820191505b81811015620001495782815560010162000134565b5050505b505050565b81516001600160401b038111156200016e576200016e620000ad565b62000186816200017f8454620000c3565b84620000ff565b602080601f831160018114620001be5760008415620001a55750858301515b600019600386901b1c1916600185901b17855562000149565b600085815260208120601f198616915b82811015620001ef57888601518255948401946001909101908401620001ce565b50858210156200020e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c051610afe6200025c600039600061024401526000818161033d01526103d20152600081816101a901526103630152610afe6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610387578063e78cea921461033b578063ee9a31a2146103cd57600080fd5b8063ae1f6aaf1461033b578063c01e1bd614610361578063d6c0b2c41461036157600080fd5b80639dc29fac116100bd5780639dc29fac14610302578063a457c2d714610315578063a9059cbb1461032857600080fd5b806370a08231146102d257806395d89b41146102fa57600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004610905565b6103f4565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104e5565b60405161019b919061094e565b61018f6102133660046109ea565b610577565b6002545b60405190815260200161019b565b61018f610238366004610a14565b610607565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c3660046109ea565b610692565b61029461028f3660046109ea565b61071d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e0366004610a50565b73ffffffffffffffffffffffffffffffffffffffff163190565b6101f861077f565b6102946103103660046109ea565b61078e565b61018f6103233660046109ea565b6107f0565b61018f6103363660046109ea565b61087b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c610395366004610a6b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104ad57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104dc57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104f490610a9e565b80601f016020809104026020016040519081016040528092919081815260200182805461052090610a9e565b801561056d5780601f106105425761010080835404028352916020019161056d565b820191906000526020600020905b81548152906001019060200180831161055057829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4c656761637945524332304554483a20617070726f766520697320646973616260448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526000906084015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4c656761637945524332304554483a207472616e7366657246726f6d2069732060448201527f64697361626c656400000000000000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a20696e637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206d696e742069732064697361626c656460448201526064016105fe565b6060600480546104f490610a9e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206275726e2069732064697361626c656460448201526064016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a206465637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4c656761637945524332304554483a207472616e73666572206973206469736160448201527f626c65640000000000000000000000000000000000000000000000000000000060648201526000906084016105fe565b60006020828403121561091757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461094757600080fd5b9392505050565b600060208083528351808285015260005b8181101561097b5785810183015185820160400152820161095f565b8181111561098d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146109e557600080fd5b919050565b600080604083850312156109fd57600080fd5b610a06836109c1565b946020939093013593505050565b600080600060608486031215610a2957600080fd5b610a32846109c1565b9250610a40602085016109c1565b9150604084013590509250925092565b600060208284031215610a6257600080fd5b610947826109c1565b60008060408385031215610a7e57600080fd5b610a87836109c1565b9150610a95602084016109c1565b90509250929050565b600181811c90821680610ab257607f821691505b602082108103610aeb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b5091905056fea164736f6c634300080f000a", } // LegacyERC20ETHABI is the input ABI used to generate the binding from. diff --git a/op-bindings/bindings/legacyerc20eth_more.go b/op-bindings/bindings/legacyerc20eth_more.go index cb79ddddc2c8..146d22f90323 100644 --- a/op-bindings/bindings/legacyerc20eth_more.go +++ b/op-bindings/bindings/legacyerc20eth_more.go @@ -13,7 +13,7 @@ const LegacyERC20ETHStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contrac var LegacyERC20ETHStorageLayout = new(solc.StorageLayout) -var LegacyERC20ETHDeployedBin = "0x608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610353578063e78cea9214610307578063ee9a31a21461039957600080fd5b8063ae1f6aaf14610307578063c01e1bd61461032d578063d6c0b2c41461032d57600080fd5b80639dc29fac116100bd5780639dc29fac146102ce578063a457c2d7146102e1578063a9059cbb146102f457600080fd5b806370a082311461029e57806395d89b41146102c657600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004610ab1565b6103c0565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104b1565b60405161019b9190610b2a565b61018f610213366004610ba4565b610543565b6002545b60405190815260200161019b565b61018f610238366004610bce565b6105d3565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004610ba4565b61065e565b61029461028f366004610ba4565b6106e9565b005b6101f861074b565b61021c6102ac366004610c0a565b73ffffffffffffffffffffffffffffffffffffffff163190565b6101f86107ee565b6102946102dc366004610ba4565b6107fd565b61018f6102ef366004610ba4565b61085f565b61018f610302366004610ba4565b6108ea565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c610361366004610c25565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061047957507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104a857507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104c090610c58565b80601f01602080910402602001604051908101604052809291908181526020018280546104ec90610c58565b80156105395780601f1061050e57610100808354040283529160200191610539565b820191906000526020600020905b81548152906001019060200180831161051c57829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4c656761637945524332304554483a20617070726f766520697320646973616260448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526000906084015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4c656761637945524332304554483a207472616e7366657246726f6d2069732060448201527f64697361626c656400000000000000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a20696e637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206d696e742069732064697361626c656460448201526064016105ca565b60606107767f0000000000000000000000000000000000000000000000000000000000000000610974565b61079f7f0000000000000000000000000000000000000000000000000000000000000000610974565b6107c87f0000000000000000000000000000000000000000000000000000000000000000610974565b6040516020016107da93929190610cab565b604051602081830303815290604052905090565b6060600480546104c090610c58565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206275726e2069732064697361626c656460448201526064016105ca565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a206465637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105ca565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4c656761637945524332304554483a207472616e73666572206973206469736160448201527f626c65640000000000000000000000000000000000000000000000000000000060648201526000906084016105ca565b6060816000036109b757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156109e157806109cb81610d50565b91506109da9050600a83610db7565b91506109bb565b60008167ffffffffffffffff8111156109fc576109fc610dcb565b6040519080825280601f01601f191660200182016040528015610a26576020820181803683370190505b5090505b8415610aa957610a3b600183610dfa565b9150610a48600a86610e11565b610a53906030610e25565b60f81b818381518110610a6857610a68610e3d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610aa2600a86610db7565b9450610a2a565b949350505050565b600060208284031215610ac357600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610af357600080fd5b9392505050565b60005b83811015610b15578181015183820152602001610afd565b83811115610b24576000848401525b50505050565b6020815260008251806020840152610b49816040850160208701610afa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610b9f57600080fd5b919050565b60008060408385031215610bb757600080fd5b610bc083610b7b565b946020939093013593505050565b600080600060608486031215610be357600080fd5b610bec84610b7b565b9250610bfa60208501610b7b565b9150604084013590509250925092565b600060208284031215610c1c57600080fd5b610af382610b7b565b60008060408385031215610c3857600080fd5b610c4183610b7b565b9150610c4f60208401610b7b565b90509250929050565b600181811c90821680610c6c57607f821691505b602082108103610ca5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008451610cbd818460208901610afa565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610cf9816001850160208a01610afa565b60019201918201528351610d14816002840160208801610afa565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610d8157610d81610d21565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610dc657610dc6610d88565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015610e0c57610e0c610d21565b500390565b600082610e2057610e20610d88565b500690565b60008219821115610e3857610e38610d21565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" +var LegacyERC20ETHDeployedBin = "0x608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610387578063e78cea921461033b578063ee9a31a2146103cd57600080fd5b8063ae1f6aaf1461033b578063c01e1bd614610361578063d6c0b2c41461036157600080fd5b80639dc29fac116100bd5780639dc29fac14610302578063a457c2d714610315578063a9059cbb1461032857600080fd5b806370a08231146102d257806395d89b41146102fa57600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004610905565b6103f4565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104e5565b60405161019b919061094e565b61018f6102133660046109ea565b610577565b6002545b60405190815260200161019b565b61018f610238366004610a14565b610607565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c3660046109ea565b610692565b61029461028f3660046109ea565b61071d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e0366004610a50565b73ffffffffffffffffffffffffffffffffffffffff163190565b6101f861077f565b6102946103103660046109ea565b61078e565b61018f6103233660046109ea565b6107f0565b61018f6103363660046109ea565b61087b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c610395366004610a6b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104ad57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104dc57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104f490610a9e565b80601f016020809104026020016040519081016040528092919081815260200182805461052090610a9e565b801561056d5780601f106105425761010080835404028352916020019161056d565b820191906000526020600020905b81548152906001019060200180831161055057829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4c656761637945524332304554483a20617070726f766520697320646973616260448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526000906084015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4c656761637945524332304554483a207472616e7366657246726f6d2069732060448201527f64697361626c656400000000000000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a20696e637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206d696e742069732064697361626c656460448201526064016105fe565b6060600480546104f490610a9e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206275726e2069732064697361626c656460448201526064016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a206465637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4c656761637945524332304554483a207472616e73666572206973206469736160448201527f626c65640000000000000000000000000000000000000000000000000000000060648201526000906084016105fe565b60006020828403121561091757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461094757600080fd5b9392505050565b600060208083528351808285015260005b8181101561097b5785810183015185820160400152820161095f565b8181111561098d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146109e557600080fd5b919050565b600080604083850312156109fd57600080fd5b610a06836109c1565b946020939093013593505050565b600080600060608486031215610a2957600080fd5b610a32846109c1565b9250610a40602085016109c1565b9150604084013590509250925092565b600060208284031215610a6257600080fd5b610947826109c1565b60008060408385031215610a7e57600080fd5b610a87836109c1565b9150610a95602084016109c1565b90509250929050565b600181811c90821680610ab257607f821691505b602082108103610aeb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b5091905056fea164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(LegacyERC20ETHStorageLayoutJSON), LegacyERC20ETHStorageLayout); err != nil { diff --git a/op-bindings/bindings/mips_more.go b/op-bindings/bindings/mips_more.go index 8cd25880611b..64a429b42f6c 100644 --- a/op-bindings/bindings/mips_more.go +++ b/op-bindings/bindings/mips_more.go @@ -15,7 +15,7 @@ var MIPSStorageLayout = new(solc.StorageLayout) var MIPSDeployedBin = "0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063155633fe146100465780637dc0d1d01461006b578063836e7b32146100af575b600080fd5b610051634000000081565b60405163ffffffff90911681526020015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610062565b6100c26100bd366004611d2e565b6100d0565b604051908152602001610062565b60006100da611c5b565b608081146100e757600080fd5b604051610600146100f757600080fd5b6084871461010457600080fd5b6101a4851461011257600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b60208110156101bd57823560e01c8252600490920191602090910190600101610199565b505050806101200151156101db576101d361061b565b915050610612565b6101408101805160010167ffffffffffffffff16905260608101516000906102039082610737565b9050603f601a82901c16600281148061022257508063ffffffff166003145b156102775760006002836303ffffff1663ffffffff16901b846080015163f00000001617905061026c8263ffffffff1660021461026057601f610263565b60005b60ff16826107f3565b945050505050610612565b6101608301516000908190601f601086901c81169190601587901c16602081106102a3576102a3611da2565b602002015192508063ffffffff851615806102c457508463ffffffff16601c145b156102fb578661016001518263ffffffff16602081106102e6576102e6611da2565b6020020151925050601f600b86901c166103b7565b60208563ffffffff16101561035d578463ffffffff16600c148061032557508463ffffffff16600d145b8061033657508463ffffffff16600e145b15610347578561ffff1692506103b7565b6103568661ffff1660106108e4565b92506103b7565b60288563ffffffff1610158061037957508463ffffffff166022145b8061038a57508463ffffffff166026145b156103b7578661016001518263ffffffff16602081106103ac576103ac611da2565b602002015192508190505b60048563ffffffff16101580156103d4575060088563ffffffff16105b806103e557508463ffffffff166001145b15610404576103f685878487610957565b975050505050505050610612565b63ffffffff6000602087831610610469576104248861ffff1660106108e4565b9095019463fffffffc861661043a816001610737565b915060288863ffffffff161015801561045a57508763ffffffff16603014155b1561046757809250600093505b505b600061047789888885610b67565b63ffffffff9081169150603f8a1690891615801561049c575060088163ffffffff1610155b80156104ae5750601c8163ffffffff16105b1561058b578063ffffffff16600814806104ce57508063ffffffff166009145b15610505576104f38163ffffffff166008146104ea57856104ed565b60005b896107f3565b9b505050505050505050505050610612565b8063ffffffff16600a03610525576104f3858963ffffffff8a16156112f7565b8063ffffffff16600b03610546576104f3858963ffffffff8a1615156112f7565b8063ffffffff16600c0361055d576104f38d6113dd565b60108163ffffffff161015801561057a5750601c8163ffffffff16105b1561058b576104f381898988611914565b8863ffffffff1660381480156105a6575063ffffffff861615155b156105db5760018b61016001518763ffffffff16602081106105ca576105ca611da2565b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff146105f8576105f884600184611b0e565b610604858360016112f7565b9b5050505050505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b60208110156106ba57601c8601518452602090950194600490930192600101610696565b506000835283830384a06000945080600181146106da5760039550610702565b8280156106f257600181146106fb5760029650610700565b60009650610700565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008061074383611bb2565b9050600384161561075357600080fd5b6020810190358460051c8160005b601b8110156107b95760208501943583821c6001168015610789576001811461079e576107af565b600084815260208390526040902093506107af565b600082815260208590526040902093505b5050600101610761565b5060805191508181146107d457630badf00d60005260206000fd5b5050601f94909416601c0360031b9390931c63ffffffff169392505050565b60006107fd611c5b565b60809050806060015160040163ffffffff16816080015163ffffffff1614610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b60608101805160808301805163ffffffff9081169093528583169052908516156108dc57806008018261016001518663ffffffff16602081106108cb576108cb611da2565b63ffffffff90921660209290920201525b61061261061b565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610941576000610943565b815b90861663ffffffff16179250505092915050565b6000610961611c5b565b608090506000816060015160040163ffffffff16826080015163ffffffff16146109e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f74000000000000000000000000604482015260640161087d565b8663ffffffff1660041480610a0257508663ffffffff166005145b15610a7e5760008261016001518663ffffffff1660208110610a2657610a26611da2565b602002015190508063ffffffff168563ffffffff16148015610a4e57508763ffffffff166004145b80610a7657508063ffffffff168563ffffffff1614158015610a7657508763ffffffff166005145b915050610afb565b8663ffffffff16600603610a9b5760008460030b13159050610afb565b8663ffffffff16600703610ab75760008460030b139050610afb565b8663ffffffff16600103610afb57601f601087901c166000819003610ae05760008560030b1291505b8063ffffffff16600103610af95760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b41576002610b268861ffff1660106108e4565b63ffffffff90811690911b8201600401166080840152610b53565b60808301805160040163ffffffff1690525b610b5b61061b565b98975050505050505050565b6000603f601a86901c16801580610b96575060088163ffffffff1610158015610b965750600f8163ffffffff16105b15610fec57603f86168160088114610bdd5760098114610be657600a8114610bef57600b8114610bf857600c8114610c0157600d8114610c0a57600e8114610c1357610c18565b60209150610c18565b60219150610c18565b602a9150610c18565b602b9150610c18565b60249150610c18565b60259150610c18565b602691505b508063ffffffff16600003610c3f5750505063ffffffff8216601f600686901c161b6112ef565b8063ffffffff16600203610c655750505063ffffffff8216601f600686901c161c6112ef565b8063ffffffff16600303610c9b57601f600688901c16610c9163ffffffff8716821c60208390036108e4565b93505050506112ef565b8063ffffffff16600403610cbd5750505063ffffffff8216601f84161b6112ef565b8063ffffffff16600603610cdf5750505063ffffffff8216601f84161c6112ef565b8063ffffffff16600703610d1257610d098663ffffffff168663ffffffff16901c876020036108e4565b925050506112ef565b8063ffffffff16600803610d2a5785925050506112ef565b8063ffffffff16600903610d425785925050506112ef565b8063ffffffff16600a03610d5a5785925050506112ef565b8063ffffffff16600b03610d725785925050506112ef565b8063ffffffff16600c03610d8a5785925050506112ef565b8063ffffffff16600f03610da25785925050506112ef565b8063ffffffff16601003610dba5785925050506112ef565b8063ffffffff16601103610dd25785925050506112ef565b8063ffffffff16601203610dea5785925050506112ef565b8063ffffffff16601303610e025785925050506112ef565b8063ffffffff16601803610e1a5785925050506112ef565b8063ffffffff16601903610e325785925050506112ef565b8063ffffffff16601a03610e4a5785925050506112ef565b8063ffffffff16601b03610e625785925050506112ef565b8063ffffffff16602003610e7b575050508282016112ef565b8063ffffffff16602103610e94575050508282016112ef565b8063ffffffff16602203610ead575050508183036112ef565b8063ffffffff16602303610ec6575050508183036112ef565b8063ffffffff16602403610edf575050508282166112ef565b8063ffffffff16602503610ef8575050508282176112ef565b8063ffffffff16602603610f11575050508282186112ef565b8063ffffffff16602703610f2b57505050828217196112ef565b8063ffffffff16602a03610f5c578460030b8660030b12610f4d576000610f50565b60015b60ff16925050506112ef565b8063ffffffff16602b03610f84578463ffffffff168663ffffffff1610610f4d576000610f50565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015260640161087d565b50610f84565b8063ffffffff16601c0361107057603f86166002819003611012575050508282026112ef565b8063ffffffff166020148061102d57508063ffffffff166021145b15610fe6578063ffffffff16602003611044579419945b60005b6380000000871615611066576401fffffffe600197881b169601611047565b92506112ef915050565b8063ffffffff16600f0361109257505065ffffffff0000601083901b166112ef565b8063ffffffff166020036110ce576110c68560031660080260180363ffffffff168463ffffffff16901c60ff1660086108e4565b9150506112ef565b8063ffffffff16602103611103576110c68560021660080260100363ffffffff168463ffffffff16901c61ffff1660106108e4565b8063ffffffff1660220361113257505063ffffffff60086003851602811681811b198416918316901b176112ef565b8063ffffffff1660230361114957829150506112ef565b8063ffffffff1660240361117b578460031660080260180363ffffffff168363ffffffff16901c60ff169150506112ef565b8063ffffffff166025036111ae578460021660080260100363ffffffff168363ffffffff16901c61ffff169150506112ef565b8063ffffffff166026036111e057505063ffffffff60086003851602601803811681811c198416918316901c176112ef565b8063ffffffff1660280361121657505060ff63ffffffff60086003861602601803811682811b9091188316918416901b176112ef565b8063ffffffff1660290361124d57505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b176112ef565b8063ffffffff16602a0361127c57505063ffffffff60086003851602811681811c198316918416901c176112ef565b8063ffffffff16602b0361129357839150506112ef565b8063ffffffff16602e036112c557505063ffffffff60086003851602601803811681811b198316918416901b176112ef565b8063ffffffff166030036112dc57829150506112ef565b8063ffffffff16603803610f8457839150505b949350505050565b6000611301611c5b565b506080602063ffffffff861610611374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015260640161087d565b63ffffffff8516158015906113865750825b156113ba57838161016001518663ffffffff16602081106113a9576113a9611da2565b63ffffffff90921660209290920201525b60808101805163ffffffff8082166060850152600490910116905261061261061b565b60006113e7611c5b565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa036114615781610fff81161561143057610fff811661100003015b8363ffffffff166000036114575760e08801805163ffffffff83820116909152955061145b565b8395505b506118d3565b8563ffffffff16610fcd0361147c57634000000094506118d3565b8563ffffffff166110180361149457600194506118d3565b8563ffffffff16611096036114ca57600161012088015260ff83166101008801526114bd61061b565b9998505050505050505050565b8563ffffffff16610fa3036117365763ffffffff8316156118d3577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8416016116f05760006115258363fffffffc166001610737565b60208901519091508060001a60010361159457604080516000838152336020528d83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790505b6040808a015190517fe03110e10000000000000000000000000000000000000000000000000000000081526004810183905263ffffffff9091166024820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e03110e1906044016040805180830381865afa158015611635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116599190611dd1565b91509150600386168060040382811015611671578092505b508186101561167e578591505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b039150811981169050838119871617955050506116d58663fffffffc16600186611b0e565b60408b018051820163ffffffff169052975061173192505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff841601611725578094506118d3565b63ffffffff9450600993505b6118d3565b8563ffffffff16610fa4036118275763ffffffff831660011480611760575063ffffffff83166002145b80611771575063ffffffff83166004145b1561177e578094506118d3565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8416016117255760006117be8363fffffffc166001610737565b602089015190915060038416600403838110156117d9578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b176020880152600060408801529350836118d3565b8563ffffffff16610fd7036118d3578163ffffffff166003036118c75763ffffffff8316158061185d575063ffffffff83166005145b8061186e575063ffffffff83166003145b1561187c57600094506118d3565b63ffffffff831660011480611897575063ffffffff83166002145b806118a8575063ffffffff83166006145b806118b9575063ffffffff83166004145b1561172557600194506118d3565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b015260040190911690526114bd61061b565b600061191e611c5b565b506080600063ffffffff871660100361193c575060c0810151611aa5565b8663ffffffff1660110361195b5763ffffffff861660c0830152611aa5565b8663ffffffff16601203611974575060a0810151611aa5565b8663ffffffff166013036119935763ffffffff861660a0830152611aa5565b8663ffffffff166018036119c75763ffffffff600387810b9087900b02602081901c821660c08501521660a0830152611aa5565b8663ffffffff166019036119f85763ffffffff86811681871602602081901c821660c08501521660a0830152611aa5565b8663ffffffff16601a03611a4e578460030b8660030b81611a1b57611a1b611df5565b0763ffffffff1660c0830152600385810b9087900b81611a3d57611a3d611df5565b0563ffffffff1660a0830152611aa5565b8663ffffffff16601b03611aa5578463ffffffff168663ffffffff1681611a7757611a77611df5565b0663ffffffff90811660c084015285811690871681611a9857611a98611df5565b0463ffffffff1660a08301525b63ffffffff841615611ae057808261016001518563ffffffff1660208110611acf57611acf611da2565b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611b0361061b565b979650505050505050565b6000611b1983611bb2565b90506003841615611b2957600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611ba75760208401933582821c6001168015611b775760018114611b8c57611b9d565b60008581526020839052604090209450611b9d565b600082815260208690526040902094505b5050600101611b4f565b505060805250505050565b60ff8116610380026101a4810190369061052401811015611c55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f6174610000000000000000000000000000000000000000000000000000000000606482015260840161087d565b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611cc1611cc6565b905290565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112611cf757600080fd5b50813567ffffffffffffffff811115611d0f57600080fd5b602083019150836020828501011115611d2757600080fd5b9250929050565b600080600080600060608688031215611d4657600080fd5b853567ffffffffffffffff80821115611d5e57600080fd5b611d6a89838a01611ce5565b90975095506020880135915080821115611d8357600080fd5b50611d9088828901611ce5565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060408385031215611de457600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a" -var MIPSDeployedSourceMap = "1131:40054:144:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1710:45;;1745:10;1710:45;;;;;188:10:310;176:23;;;158:42;;146:2;131:18;1710:45:144;;;;;;;;2448:99;;;412:42:310;2534:6:144;400:55:310;382:74;;370:2;355:18;2448:99:144;211:251:310;26025:6379:144;;;;;;:::i;:::-;;:::i;:::-;;;1755:25:310;;;1743:2;1728:18;26025:6379:144;1609:177:310;26025:6379:144;26128:7;26171:18;;:::i;:::-;26318:4;26311:5;26308:15;26298:134;;26412:1;26409;26402:12;26298:134;26468:4;26462:11;26475:10;26459:27;26449:136;;26565:1;26562;26555:12;26449:136;26634:3;26615:17;26612:26;26602:151;;26733:1;26730;26723:12;26602:151;26798:3;26783:13;26780:22;26770:146;;26896:1;26893;26886:12;26770:146;27176:24;;27521:4;27222:20;27579:2;27280:21;;27176:24;27338:18;27222:20;27280:21;;;27176:24;27153:21;27149:52;;;27338:18;27222:20;;;27280:21;;;27176:24;27149:52;;27222:20;;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;;27338:18;27222:20;27280:21;;;27176:24;27153:21;27149:52;;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;28197:10;27338:18;28187:21;;;27280;;;;28295:1;28280:77;28305:2;28302:1;28299:9;28280:77;;;27176:24;;27153:21;27149:52;27222:20;;28353:1;27280:21;;;;27164:2;27338:18;;;;28323:1;28316:9;28280:77;;;28284:14;;;28435:5;:12;;;28431:71;;;28474:13;:11;:13::i;:::-;28467:20;;;;;28431:71;28516:10;;;:15;;28530:1;28516:15;;;;;28601:8;;;;-1:-1:-1;;28593:20:144;;-1:-1:-1;28593:7:144;:20::i;:::-;28579:34;-1:-1:-1;28643:10:144;28651:2;28643:10;;;;28720:1;28710:11;;;:26;;;28725:6;:11;;28735:1;28725:11;28710:26;28706:310;;;28866:13;28935:1;28913:4;28920:10;28913:17;28912:24;;;;28883:5;:12;;;28898:10;28883:25;28882:54;28866:70;;28961:40;28972:6;:11;;28982:1;28972:11;:20;;28990:2;28972:20;;;28986:1;28972:20;28961:40;;28994:6;28961:10;:40::i;:::-;28954:47;;;;;;;;28706:310;29265:15;;;;29060:9;;;;29197:4;29191:2;29183:10;;;29182:19;;;29265:15;29290:2;29282:10;;;29281:19;29265:36;;;;;;;:::i;:::-;;;;;;-1:-1:-1;29330:5:144;29354:11;;;;;:29;;;29369:6;:14;;29379:4;29369:14;29354:29;29350:832;;;29446:5;:15;;;29462:5;29446:22;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;29509:4:144;29503:2;29495:10;;;29494:19;29350:832;;;29547:4;29538:6;:13;;;29534:648;;;29668:6;:13;;29678:3;29668:13;:30;;;;29685:6;:13;;29695:3;29685:13;29668:30;:47;;;;29702:6;:13;;29712:3;29702:13;29668:47;29664:253;;;29778:4;29785:6;29778:13;29773:18;;29534:648;;29664:253;29877:21;29880:4;29887:6;29880:13;29895:2;29877;:21::i;:::-;29872:26;;29534:648;;;29951:4;29941:6;:14;;;;:32;;;;29959:6;:14;;29969:4;29959:14;29941:32;:50;;;;29977:6;:14;;29987:4;29977:14;29941:50;29937:245;;;30061:5;:15;;;30077:5;30061:22;;;;;;;;;:::i;:::-;;;;;30056:27;;30162:5;30154:13;;29937:245;30211:1;30201:6;:11;;;;:25;;;;;30225:1;30216:6;:10;;;30201:25;30200:42;;;;30231:6;:11;;30241:1;30231:11;30200:42;30196:125;;;30269:37;30282:6;30290:4;30296:5;30303:2;30269:12;:37::i;:::-;30262:44;;;;;;;;;;;30196:125;30354:13;30335:16;30506:4;30496:14;;;;30492:446;;30575:21;30578:4;30585:6;30578:13;30593:2;30575;:21::i;:::-;30569:27;;;;30633:10;30628:15;;30667:16;30628:15;30681:1;30667:7;:16::i;:::-;30661:22;;30715:4;30705:6;:14;;;;:32;;;;;30723:6;:14;;30733:4;30723:14;;30705:32;30701:223;;;30802:4;30790:16;;30904:1;30896:9;;30701:223;30512:426;30492:446;30971:10;30984:26;30992:4;30998:2;31002;31006:3;30984:7;:26::i;:::-;31013:10;30984:39;;;;-1:-1:-1;31109:4:144;31102:11;;;31141;;;:24;;;;;31164:1;31156:4;:9;;;;31141:24;:39;;;;;31176:4;31169;:11;;;31141:39;31137:860;;;31204:4;:9;;31212:1;31204:9;:22;;;;31217:4;:9;;31225:1;31217:9;31204:22;31200:144;;;31288:37;31299:4;:9;;31307:1;31299:9;:21;;31315:5;31299:21;;;31311:1;31299:21;31322:2;31288:10;:37::i;:::-;31281:44;;;;;;;;;;;;;;;31200:144;31366:4;:11;;31374:3;31366:11;31362:121;;31436:28;31445:5;31452:2;31456:7;;;;31436:8;:28::i;31362:121::-;31504:4;:11;;31512:3;31504:11;31500:121;;31574:28;31583:5;31590:2;31594:7;;;;;31574:8;:28::i;31500:121::-;31691:4;:11;;31699:3;31691:11;31687:93;;31733:28;31747:13;31733;:28::i;31687:93::-;31883:4;31875;:12;;;;:27;;;;;31898:4;31891;:11;;;31875:27;31871:112;;;31933:31;31944:4;31950:2;31954;31958:5;31933:10;:31::i;31871:112::-;32057:6;:14;;32067:4;32057:14;:28;;;;-1:-1:-1;32075:10:144;;;;;32057:28;32053:93;;;32130:1;32105:5;:15;;;32121:5;32105:22;;;;;;;;;:::i;:::-;:26;;;;:22;;;;;;:26;32053:93;32192:9;:26;;32205:13;32192:26;32188:92;;32238:27;32247:9;32258:1;32261:3;32238:8;:27::i;:::-;32361:26;32370:5;32377:3;32382:4;32361:8;:26::i;:::-;32354:33;;;;;;;;;;;;;26025:6379;;;;;;;;:::o;3087:2334::-;3634:4;3628:11;;3550:4;3353:31;3342:43;;3413:13;3353:31;3752:2;3452:13;;3342:43;3359:24;3353:31;3452:13;;;3342:43;;;;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3413:13;4180:11;3359:24;3353:31;3452:13;;;3342:43;3413:13;4275:11;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3128:12;;4415:13;;3628:11;;3452:13;;;;4180:11;3128:12;4495:84;4520:2;4517:1;4514:9;4495:84;;;3369:13;3359:24;;3353:31;3342:43;;3373:2;3413:13;;;;4575:1;3452:13;;;;4538:1;4531:9;4495:84;;;4499:14;4642:1;4638:2;4631:13;4737:5;4733:2;4729:14;4722:5;4717:27;4811:1;4797:15;;4832:6;4856:1;4851:273;;;;5191:1;5181:11;;4825:369;;4851:273;4883:8;4941:22;;;;5020:1;5015:22;;;;5107:1;5097:11;;4876:234;;4941:22;4960:1;4950:11;;4941:22;;5015;5034:1;5024:11;;4876:234;;4825:369;-1:-1:-1;;;5317:14:144;;;5300:32;;5360:19;5356:30;5392:3;5388:16;;;;5353:52;;3087:2334;-1:-1:-1;3087:2334:144:o;21746:1831::-;21819:11;21930:14;21947:24;21959:11;21947;:24::i;:::-;21930:41;;22079:1;22072:5;22068:13;22065:33;;;22094:1;22091;22084:12;22065:33;22227:2;22215:15;;;22168:20;22657:5;22654:1;22650:13;22692:4;22728:1;22713:343;22738:2;22735:1;22732:9;22713:343;;;22861:2;22849:15;;;22798:20;22896:12;;;22910:1;22892:20;22933:42;;;;23001:1;22996:42;;;;22885:153;;22933:42;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;22942:31;;22933:42;;22996;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;23005:31;;22885:153;-1:-1:-1;;22756:1:144;22749:9;22713:343;;;22717:14;23166:4;23160:11;23145:26;;23252:7;23246:4;23243:17;23233:124;;23294:10;23291:1;23284:21;23336:2;23333:1;23326:13;23233:124;-1:-1:-1;;23484:2:144;23473:14;;;;23461:10;23457:31;23454:1;23450:39;23518:16;;;;23536:10;23514:33;;21746:1831;-1:-1:-1;;;21746:1831:144:o;18856:823::-;18925:12;19012:18;;:::i;:::-;19080:4;19071:13;;19132:5;:8;;;19143:1;19132:12;19116:28;;:5;:12;;;:28;;;19112:95;;19164:28;;;;;2182:2:310;19164:28:144;;;2164:21:310;2221:2;2201:18;;;2194:30;2260:20;2240:18;;;2233:48;2298:18;;19164:28:144;;;;;;;;19112:95;19296:8;;;;;19329:12;;;;;19318:23;;;;;;;19355:20;;;;;19296:8;19487:13;;;19483:90;;19548:6;19557:1;19548:10;19520:5;:15;;;19536:8;19520:25;;;;;;;;;:::i;:::-;:38;;;;:25;;;;;;:38;19483:90;19649:13;:11;:13::i;2645:339::-;2706:11;2770:18;;;;2779:8;;;;2770:18;;;;;;2769:25;;;;;2786:1;2833:2;:9;;;2827:16;;;;;2826:22;;2825:32;;;;;;;2887:9;;2886:15;2769:25;2944:21;;2964:1;2944:21;;;2955:6;2944:21;2929:11;;;;;:37;;-1:-1:-1;;;2645:339:144;;;;:::o;13732:2026::-;13829:12;13915:18;;:::i;:::-;13983:4;13974:13;;14015:17;14075:5;:8;;;14086:1;14075:12;14059:28;;:5;:12;;;:28;;;14055:97;;14107:30;;;;;2529:2:310;14107:30:144;;;2511:21:310;2568:2;2548:18;;;2541:30;2607:22;2587:18;;;2580:50;2647:18;;14107:30:144;2327:344:310;14055:97:144;14222:7;:12;;14233:1;14222:12;:28;;;;14238:7;:12;;14249:1;14238:12;14222:28;14218:947;;;14270:9;14282:5;:15;;;14298:6;14282:23;;;;;;;;;:::i;:::-;;;;;14270:35;;14346:2;14339:9;;:3;:9;;;:25;;;;;14352:7;:12;;14363:1;14352:12;14339:25;14338:58;;;;14377:2;14370:9;;:3;:9;;;;:25;;;;;14383:7;:12;;14394:1;14383:12;14370:25;14323:73;;14252:159;14218:947;;;14508:7;:12;;14519:1;14508:12;14504:661;;14569:1;14561:3;14555:15;;;;14540:30;;14504:661;;;14673:7;:12;;14684:1;14673:12;14669:496;;14733:1;14726:3;14720:14;;;14705:29;;14669:496;;;14854:7;:12;;14865:1;14854:12;14850:315;;14942:4;14936:2;14927:11;;;14926:20;14912:10;14969:8;;;14965:84;;15029:1;15022:3;15016:14;;;15001:29;;14965:84;15070:3;:8;;15077:1;15070:8;15066:85;;15131:1;15123:3;15117:15;;;;15102:30;;15066:85;14868:297;14850:315;15241:8;;;;;15319:12;;;;15308:23;;;;;15475:178;;;;15566:1;15540:22;15543:5;15551:6;15543:14;15559:2;15540;:22::i;:::-;:27;;;;;;;15526:42;;15535:1;15526:42;15511:57;:12;;;:57;15475:178;;;15622:12;;;;;15637:1;15622:16;15607:31;;;;15475:178;15728:13;:11;:13::i;:::-;15721:20;13732:2026;-1:-1:-1;;;;;;;;13732:2026:144:o;32450:8733::-;32537:10;32599;32607:2;32599:10;;;;32638:11;;;:44;;;32664:1;32654:6;:11;;;;:27;;;;;32678:3;32669:6;:12;;;32654:27;32634:8490;;;32723:4;32716:11;;32847:6;32907:3;32902:25;;;;32982:3;32977:25;;;;33056:3;33051:25;;;;33131:3;33126:25;;;;33205:3;33200:25;;;;33278:3;33273:25;;;;33352:3;33347:25;;;;32840:532;;32902:25;32921:4;32913:12;;32902:25;;32977;32996:4;32988:12;;32977:25;;33051;33070:4;33062:12;;33051:25;;33126;33145:4;33137:12;;33126:25;;33200;33219:4;33211:12;;33200:25;;33273;33292:4;33284:12;;33273:25;;33347;33366:4;33358:12;;32840:532;;33435:4;:12;;33443:4;33435:12;33431:4023;;-1:-1:-1;;;33486:9:144;33478:26;;33499:4;33494:1;33486:9;;;33485:18;33478:26;33471:33;;33431:4023;33572:4;:12;;33580:4;33572:12;33568:3886;;-1:-1:-1;;;33623:9:144;33615:26;;33636:4;33631:1;33623:9;;;33622:18;33615:26;33608:33;;33568:3886;33709:4;:12;;33717:4;33709:12;33705:3749;;33774:4;33769:1;33761:9;;;33760:18;33807:27;33761:9;33810:11;;;;33823:2;:10;;;33807:2;:27::i;:::-;33800:34;;;;;;;33705:3749;33903:4;:12;;33911:4;33903:12;33899:3555;;-1:-1:-1;;;33946:17:144;;;33958:4;33953:9;;33946:17;33939:24;;33899:3555;34032:4;:11;;34040:3;34032:11;34028:3426;;-1:-1:-1;;;34074:17:144;;;34086:4;34081:9;;34074:17;34067:24;;34028:3426;34160:4;:12;;34168:4;34160:12;34156:3298;;34203:21;34212:2;34206:8;;:2;:8;;;;34221:2;34216;:7;34203:2;:21::i;:::-;34196:28;;;;;;34156:3298;34473:4;:12;;34481:4;34473:12;34469:2985;;34516:2;34509:9;;;;;;34469:2985;34587:4;:12;;34595:4;34587:12;34583:2871;;34630:2;34623:9;;;;;;34583:2871;34701:4;:12;;34709:4;34701:12;34697:2757;;34744:2;34737:9;;;;;;34697:2757;34815:4;:12;;34823:4;34815:12;34811:2643;;34858:2;34851:9;;;;;;34811:2643;34932:4;:12;;34940:4;34932:12;34928:2526;;34975:2;34968:9;;;;;;34928:2526;35092:4;:12;;35100:4;35092:12;35088:2366;;35135:2;35128:9;;;;;;35088:2366;35206:4;:12;;35214:4;35206:12;35202:2252;;35249:2;35242:9;;;;;;35202:2252;35320:4;:12;;35328:4;35320:12;35316:2138;;35363:2;35356:9;;;;;;35316:2138;35434:4;:12;;35442:4;35434:12;35430:2024;;35477:2;35470:9;;;;;;35430:2024;35548:4;:12;;35556:4;35548:12;35544:1910;;35591:2;35584:9;;;;;;35544:1910;35662:4;:12;;35670:4;35662:12;35658:1796;;35705:2;35698:9;;;;;;35658:1796;35777:4;:12;;35785:4;35777:12;35773:1681;;35820:2;35813:9;;;;;;35773:1681;35890:4;:12;;35898:4;35890:12;35886:1568;;35933:2;35926:9;;;;;;35886:1568;36004:4;:12;;36012:4;36004:12;36000:1454;;36047:2;36040:9;;;;;;36000:1454;36196:4;:12;;36204:4;36196:12;36192:1262;;-1:-1:-1;;;36240:7:144;;;36232:16;;36192:1262;36317:4;:12;;36325:4;36317:12;36313:1141;;-1:-1:-1;;;36361:7:144;;;36353:16;;36313:1141;36437:4;:12;;36445:4;36437:12;36433:1021;;-1:-1:-1;;;36481:7:144;;;36473:16;;36433:1021;36558:4;:12;;36566:4;36558:12;36554:900;;-1:-1:-1;;;36602:7:144;;;36594:16;;36554:900;36678:4;:12;;36686:4;36678:12;36674:780;;-1:-1:-1;;;36722:7:144;;;36714:16;;36674:780;36797:4;:12;;36805:4;36797:12;36793:661;;-1:-1:-1;;;36841:7:144;;;36833:16;;36793:661;36917:4;:12;;36925:4;36917:12;36913:541;;-1:-1:-1;;;36961:7:144;;;36953:16;;36913:541;37037:4;:12;;37045:4;37037:12;37033:421;;-1:-1:-1;;;37082:7:144;;;37080:10;37073:17;;37033:421;37159:4;:12;;37167:4;37159:12;37155:299;;37220:2;37202:21;;37208:2;37202:21;;;:29;;37230:1;37202:29;;;37226:1;37202:29;37195:36;;;;;;;;37155:299;37301:4;:12;;37309:4;37301:12;37297:157;;37349:2;37344:7;;:2;:7;;;:15;;37358:1;37344:15;;37297:157;37406:29;;;;;2878:2:310;37406:29:144;;;2860:21:310;2917:2;2897:18;;;2890:30;2956:21;2936:18;;;2929:49;2995:18;;37406:29:144;2676:343:310;37297:157:144;32684:4784;32634:8490;;;37524:6;:14;;37534:4;37524:14;37520:3590;;37583:4;37576:11;;37658:3;37650:11;;;37646:549;;-1:-1:-1;;;37703:21:144;;;37689:36;;37646:549;37810:4;:12;;37818:4;37810:12;:28;;;;37826:4;:12;;37834:4;37826:12;37810:28;37806:389;;;37870:4;:12;;37878:4;37870:12;37866:83;;37919:3;;;37866:83;37974:8;38012:127;38024:10;38019:15;;:20;38012:127;;38104:8;38071:3;38104:8;;;;;38071:3;38012:127;;;38171:1;-1:-1:-1;38164:8:144;;-1:-1:-1;;38164:8:144;37520:3590;38262:6;:14;;38272:4;38262:14;38258:2852;;-1:-1:-1;;38307:8:144;38313:2;38307:8;;;;38300:15;;38258:2852;38382:6;:14;;38392:4;38382:14;38378:2732;;38427:42;38445:2;38450:1;38445:6;38455:1;38444:12;38439:2;:17;38431:26;;:3;:26;;;;38461:4;38430:35;38467:1;38427:2;:42::i;:::-;38420:49;;;;;38378:2732;38536:6;:14;;38546:4;38536:14;38532:2578;;38581:45;38599:2;38604:1;38599:6;38609:1;38598:12;38593:2;:17;38585:26;;:3;:26;;;;38615:6;38584:37;38623:2;38581;:45::i;38532:2578::-;38694:6;:14;;38704:4;38694:14;38690:2420;;-1:-1:-1;;38745:21:144;38764:1;38759;38754:6;;38753:12;38745:21;;38802:36;;;38873:5;38868:10;;38745:21;;;;;38867:18;38860:25;;38690:2420;38952:6;:14;;38962:4;38952:14;38948:2162;;38997:3;38990:10;;;;;38948:2162;39068:6;:14;;39078:4;39068:14;39064:2046;;39128:2;39133:1;39128:6;39138:1;39127:12;39122:2;:17;39114:26;;:3;:26;;;;39144:4;39113:35;39106:42;;;;;39064:2046;39217:6;:14;;39227:4;39217:14;39213:1897;;39277:2;39282:1;39277:6;39287:1;39276:12;39271:2;:17;39263:26;;:3;:26;;;;39293:6;39262:37;39255:44;;;;;39213:1897;39368:6;:14;;39378:4;39368:14;39364:1746;;-1:-1:-1;;39419:26:144;39443:1;39438;39433:6;;39432:12;39427:2;:17;39419:26;;39481:41;;;39557:5;39552:10;;39419:26;;;;;39551:18;39544:25;;39364:1746;39637:6;:14;;39647:4;39637:14;39633:1477;;-1:-1:-1;;39694:4:144;39688:34;39720:1;39715;39710:6;;39709:12;39704:2;:17;39688:34;;39778:27;;;39758:48;;;39836:10;;39689:9;;;39688:34;;39835:18;39828:25;;39633:1477;39921:6;:14;;39931:4;39921:14;39917:1193;;-1:-1:-1;;39978:6:144;39972:36;40006:1;40001;39996:6;;39995:12;39990:2;:17;39972:36;;40064:29;;;40044:50;;;40124:10;;39973:11;;;39972:36;;40123:18;40116:25;;39917:1193;40210:6;:14;;40220:4;40210:14;40206:904;;-1:-1:-1;;40261:20:144;40279:1;40274;40269:6;;40268:12;40261:20;;40317:36;;;40389:5;40383:11;;40261:20;;;;;40382:19;40375:26;;40206:904;40469:6;:14;;40479:4;40469:14;40465:645;;40514:2;40507:9;;;;;40465:645;40585:6;:14;;40595:4;40585:14;40581:529;;-1:-1:-1;;40636:25:144;40659:1;40654;40649:6;;40648:12;40643:2;:17;40636:25;;40697:41;;;40774:5;40768:11;;40636:25;;;;;40767:19;40760:26;;40581:529;40853:6;:14;;40863:4;40853:14;40849:261;;40898:3;40891:10;;;;;40849:261;40968:6;:14;;40978:4;40968:14;40964:146;;41013:2;41006:9;;;32450:8733;;;;;;;:::o;19960:782::-;20046:12;20133:18;;:::i;:::-;-1:-1:-1;20201:4:144;20308:2;20296:14;;;;20288:41;;;;;;;3226:2:310;20288:41:144;;;3208:21:310;3265:2;3245:18;;;3238:30;3304:16;3284:18;;;3277:44;3338:18;;20288:41:144;3024:338:310;20288:41:144;20425:14;;;;;;;:30;;;20443:12;20425:30;20421:102;;;20504:4;20475:5;:15;;;20491:9;20475:26;;;;;;;;;:::i;:::-;:33;;;;:26;;;;;;:33;20421:102;20578:12;;;;;20567:23;;;;:8;;;:23;20634:1;20619:16;;;20604:31;;;20712:13;:11;:13::i;5582:7764::-;5646:12;5732:18;;:::i;:::-;-1:-1:-1;5910:15:144;;:18;;;;5800:4;6070:18;;;;6114;;;;6158;;;;;5800:4;;5890:17;;;;6070:18;6114;6248;;;6262:4;6248:18;6244:6792;;6298:2;6327:4;6322:9;;:14;6318:144;;6438:4;6433:9;;6425:4;:18;6419:24;6318:144;6483:2;:7;;6489:1;6483:7;6479:161;;6519:10;;;;;6551:16;;;;;;;;6519:10;-1:-1:-1;6479:161:144;;;6619:2;6614:7;;6479:161;6268:386;6244:6792;;;6756:10;:18;;6770:4;6756:18;6752:6284;;1745:10;6794:14;;6752:6284;;;6892:10;:18;;6906:4;6892:18;6888:6148;;6935:1;6930:6;;6888:6148;;;7060:10;:18;;7074:4;7060:18;7056:5980;;7113:4;7098:12;;;:19;7135:26;;;:14;;;:26;7186:13;:11;:13::i;:::-;7179:20;5582:7764;-1:-1:-1;;;;;;;;;5582:7764:144:o;7056:5980::-;7325:10;:18;;7339:4;7325:18;7321:5715;;7476:14;;;7472:2723;7321:5715;7472:2723;7646:22;;;;;7642:2553;;7771:10;7784:27;7792:2;7797:10;7792:15;7809:1;7784:7;:27::i;:::-;7895:17;;;;7771:40;;-1:-1:-1;7895:17:144;7873:19;8045:14;8064:1;8039:26;8035:146;;1676:4:145;1670:11;;1533:21;1787:15;;;1828:8;1822:4;1815:22;1850:27;;;1996:4;1983:18;;2098:17;;2003:19;1979:44;2025:11;1976:61;8093:65:144;;8035:146;8267:20;;;;;8234:54;;;;;;;;3540:25:310;;;8234:54:144;3601:23:310;;;3581:18;;;3574:51;8203:11:144;;;;8234:19;:6;:19;;;;3513:18:310;;8234:54:144;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8202:86;;;;8515:1;8511:2;8507:10;8612:9;8609:1;8605:17;8694:6;8687:5;8684:17;8681:40;;;8714:5;8704:15;;8681:40;;8797:6;8793:2;8790:14;8787:34;;;8817:2;8807:12;;8787:34;8923:3;8918:1;8910:6;8906:14;8901:3;8897:24;8893:34;8886:41;;9023:3;9019:1;9007:9;8998:6;8995:1;8991:14;8987:30;8983:38;8979:48;8972:55;;9178:1;9174;9170;9158:9;9155:1;9151:17;9147:25;9143:33;9139:41;9305:1;9301;9297;9288:6;9276:9;9273:1;9269:17;9265:30;9261:38;9257:46;9253:54;9235:72;;9436:10;9432:15;9426:4;9422:26;9414:34;;9552:3;9544:4;9540:9;9535:3;9531:19;9528:28;9521:35;;;;9698:33;9707:2;9712:10;9707:15;9724:1;9727:3;9698:8;:33::i;:::-;9753:20;;;:38;;;;;;;;;-1:-1:-1;7642:2553:144;;-1:-1:-1;;;7642:2553:144;;9910:18;;;;;9906:289;;10080:2;10075:7;;7321:5715;;9906:289;10134:10;10129:15;;2053:3;10166:10;;9906:289;7321:5715;;;10324:10;:18;;10338:4;10324:18;10320:2716;;10478:15;;;1824:1;10478:15;;:34;;-1:-1:-1;10497:15:144;;;1859:1;10497:15;10478:34;:57;;;-1:-1:-1;10516:19:144;;;1936:1;10516:19;10478:57;10474:1593;;;10564:2;10559:7;;10320:2716;;10474:1593;10690:23;;;;;10686:1381;;10737:10;10750:27;10758:2;10763:10;10758:15;10775:1;10750:7;:27::i;:::-;10853:17;;;;10737:40;;-1:-1:-1;11096:1:144;11088:10;;11190:1;11186:17;11265:13;;;11262:32;;;11287:5;11281:11;;11262:32;11573:14;;;11379:1;11569:22;;;11565:32;;;;11462:26;11486:1;11371:10;;;11466:18;;;11462:26;11561:43;11367:20;;11669:12;11797:17;;;:23;11865:1;11842:20;;;:24;11375:2;-1:-1:-1;11375:2:144;7321:5715;;10320:2716;12269:10;:18;;12283:4;12269:18;12265:771;;12379:2;:7;;12385:1;12379:7;12375:647;;12472:14;;;;;:40;;-1:-1:-1;12490:22:144;;;1978:1;12490:22;12472:40;:62;;;-1:-1:-1;12516:18:144;;;1897:1;12516:18;12472:62;12468:404;;;12567:1;12562:6;;12375:647;;12468:404;12613:15;;;1824:1;12613:15;;:34;;-1:-1:-1;12632:15:144;;;1859:1;12632:15;12613:34;:61;;;-1:-1:-1;12651:23:144;;;2021:1;12651:23;12613:61;:84;;;-1:-1:-1;12678:19:144;;;1936:1;12678:19;12613:84;12609:263;;;12730:1;12725:6;;7321:5715;;12375:647;12923:10;12918:15;;2087:4;12955:11;;12375:647;13111:15;;;;;:23;;;;:18;;;;:23;;;;13148:15;;:23;;;:18;;;;:23;-1:-1:-1;13237:12:144;;;;13226:23;;;:8;;;:23;13293:1;13278:16;13263:31;;;;;13316:13;:11;:13::i;16084:2480::-;16178:12;16264:18;;:::i;:::-;-1:-1:-1;16332:4:144;16364:10;16472:13;;;16481:4;16472:13;16468:1705;;-1:-1:-1;16511:8:144;;;;16468:1705;;;16630:5;:13;;16639:4;16630:13;16626:1547;;16663:14;;;:8;;;:14;16626:1547;;;16793:5;:13;;16802:4;16793:13;16789:1384;;-1:-1:-1;16832:8:144;;;;16789:1384;;;16951:5;:13;;16960:4;16951:13;16947:1226;;16984:14;;;:8;;;:14;16947:1226;;;17125:5;:13;;17134:4;17125:13;17121:1052;;17252:9;17198:17;17178;;;17198;;;;17178:37;17259:2;17252:9;;;;;17234:8;;;:28;17280:22;:8;;;:22;17121:1052;;;17439:5;:13;;17448:4;17439:13;17435:738;;17506:11;17492;;;17506;;;17492:25;17561:2;17554:9;;;;;17536:8;;;:28;17582:22;:8;;;:22;17435:738;;;17763:5;:13;;17772:4;17763:13;17759:414;;17833:3;17814:23;;17820:3;17814:23;;;;;;;:::i;:::-;;17796:42;;:8;;;:42;17874:23;;;;;;;;;;;;;:::i;:::-;;17856:42;;:8;;;:42;17759:414;;;18067:5;:13;;18076:4;18067:13;18063:110;;18117:3;18111:9;;:3;:9;;;;;;;:::i;:::-;;18100:20;;;;:8;;;:20;18149:9;;;;;;;;;;;:::i;:::-;;18138:20;;:8;;;:20;18063:110;18266:14;;;;18262:85;;18329:3;18300:5;:15;;;18316:9;18300:26;;;;;;;;;:::i;:::-;:32;;;;:26;;;;;;:32;18262:85;18401:12;;;;;18390:23;;;;:8;;;:23;18457:1;18442:16;;;18427:31;;;18534:13;:11;:13::i;:::-;18527:20;16084:2480;-1:-1:-1;;;;;;;16084:2480:144:o;23913:1654::-;24089:14;24106:24;24118:11;24106;:24::i;:::-;24089:41;;24238:1;24231:5;24227:13;24224:33;;;24253:1;24250;24243:12;24224:33;24392:2;24586:15;;;24411:2;24400:14;;24388:10;24384:31;24381:1;24377:39;24542:16;;;24327:20;;24527:10;24516:22;;;24512:27;24502:38;24499:60;25028:5;25025:1;25021:13;25099:1;25084:343;25109:2;25106:1;25103:9;25084:343;;;25232:2;25220:15;;;25169:20;25267:12;;;25281:1;25263:20;25304:42;;;;25372:1;25367:42;;;;25256:153;;25304:42;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;25313:31;;25304:42;;25367;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;25376:31;;25256:153;-1:-1:-1;;25127:1:144;25120:9;25084:343;;;-1:-1:-1;;25526:4:144;25519:18;-1:-1:-1;;;;23913:1654:144:o;20946:586::-;21268:20;;;21292:7;21268:32;21261:3;:40;;;21374:14;;21429:17;;21423:24;;;21415:72;;;;;;;4277:2:310;21415:72:144;;;4259:21:310;4316:2;4296:18;;;4289:30;4355:34;4335:18;;;4328:62;4426:5;4406:18;;;4399:33;4449:19;;21415:72:144;4075:399:310;21415:72:144;21501:14;20946:586;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;467:347:310:-;518:8;528:6;582:3;575:4;567:6;563:17;559:27;549:55;;600:1;597;590:12;549:55;-1:-1:-1;623:20:310;;666:18;655:30;;652:50;;;698:1;695;688:12;652:50;735:4;727:6;723:17;711:29;;787:3;780:4;771:6;763;759:19;755:30;752:39;749:59;;;804:1;801;794:12;749:59;467:347;;;;;:::o;819:785::-;918:6;926;934;942;950;1003:2;991:9;982:7;978:23;974:32;971:52;;;1019:1;1016;1009:12;971:52;1059:9;1046:23;1088:18;1129:2;1121:6;1118:14;1115:34;;;1145:1;1142;1135:12;1115:34;1184:58;1234:7;1225:6;1214:9;1210:22;1184:58;:::i;:::-;1261:8;;-1:-1:-1;1158:84:310;-1:-1:-1;1349:2:310;1334:18;;1321:32;;-1:-1:-1;1365:16:310;;;1362:36;;;1394:1;1391;1384:12;1362:36;;1433:60;1485:7;1474:8;1463:9;1459:24;1433:60;:::i;:::-;819:785;;;;-1:-1:-1;1512:8:310;1594:2;1579:18;1566:32;;819:785;-1:-1:-1;;;;819:785:310:o;1791:184::-;1843:77;1840:1;1833:88;1940:4;1937:1;1930:15;1964:4;1961:1;1954:15;3636:245;3715:6;3723;3776:2;3764:9;3755:7;3751:23;3747:32;3744:52;;;3792:1;3789;3782:12;3744:52;-1:-1:-1;;3815:16:310;;3871:2;3856:18;;;3850:25;3815:16;;3850:25;;-1:-1:-1;3636:245:310:o;3886:184::-;3938:77;3935:1;3928:88;4035:4;4032:1;4025:15;4059:4;4056:1;4049:15" +var MIPSDeployedSourceMap = "1131:40054:144:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1710:45;;1745:10;1710:45;;;;;188:10:319;176:23;;;158:42;;146:2;131:18;1710:45:144;;;;;;;;2448:99;;;412:42:319;2534:6:144;400:55:319;382:74;;370:2;355:18;2448:99:144;211:251:319;26025:6379:144;;;;;;:::i;:::-;;:::i;:::-;;;1755:25:319;;;1743:2;1728:18;26025:6379:144;1609:177:319;26025:6379:144;26128:7;26171:18;;:::i;:::-;26318:4;26311:5;26308:15;26298:134;;26412:1;26409;26402:12;26298:134;26468:4;26462:11;26475:10;26459:27;26449:136;;26565:1;26562;26555:12;26449:136;26634:3;26615:17;26612:26;26602:151;;26733:1;26730;26723:12;26602:151;26798:3;26783:13;26780:22;26770:146;;26896:1;26893;26886:12;26770:146;27176:24;;27521:4;27222:20;27579:2;27280:21;;27176:24;27338:18;27222:20;27280:21;;;27176:24;27153:21;27149:52;;;27338:18;27222:20;;;27280:21;;;27176:24;27149:52;;27222:20;;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;;27338:18;27222:20;27280:21;;;27176:24;27153:21;27149:52;;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;27280:21;;;27176:24;27149:52;;27338:18;27222:20;28197:10;27338:18;28187:21;;;27280;;;;28295:1;28280:77;28305:2;28302:1;28299:9;28280:77;;;27176:24;;27153:21;27149:52;27222:20;;28353:1;27280:21;;;;27164:2;27338:18;;;;28323:1;28316:9;28280:77;;;28284:14;;;28435:5;:12;;;28431:71;;;28474:13;:11;:13::i;:::-;28467:20;;;;;28431:71;28516:10;;;:15;;28530:1;28516:15;;;;;28601:8;;;;-1:-1:-1;;28593:20:144;;-1:-1:-1;28593:7:144;:20::i;:::-;28579:34;-1:-1:-1;28643:10:144;28651:2;28643:10;;;;28720:1;28710:11;;;:26;;;28725:6;:11;;28735:1;28725:11;28710:26;28706:310;;;28866:13;28935:1;28913:4;28920:10;28913:17;28912:24;;;;28883:5;:12;;;28898:10;28883:25;28882:54;28866:70;;28961:40;28972:6;:11;;28982:1;28972:11;:20;;28990:2;28972:20;;;28986:1;28972:20;28961:40;;28994:6;28961:10;:40::i;:::-;28954:47;;;;;;;;28706:310;29265:15;;;;29060:9;;;;29197:4;29191:2;29183:10;;;29182:19;;;29265:15;29290:2;29282:10;;;29281:19;29265:36;;;;;;;:::i;:::-;;;;;;-1:-1:-1;29330:5:144;29354:11;;;;;:29;;;29369:6;:14;;29379:4;29369:14;29354:29;29350:832;;;29446:5;:15;;;29462:5;29446:22;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;29509:4:144;29503:2;29495:10;;;29494:19;29350:832;;;29547:4;29538:6;:13;;;29534:648;;;29668:6;:13;;29678:3;29668:13;:30;;;;29685:6;:13;;29695:3;29685:13;29668:30;:47;;;;29702:6;:13;;29712:3;29702:13;29668:47;29664:253;;;29778:4;29785:6;29778:13;29773:18;;29534:648;;29664:253;29877:21;29880:4;29887:6;29880:13;29895:2;29877;:21::i;:::-;29872:26;;29534:648;;;29951:4;29941:6;:14;;;;:32;;;;29959:6;:14;;29969:4;29959:14;29941:32;:50;;;;29977:6;:14;;29987:4;29977:14;29941:50;29937:245;;;30061:5;:15;;;30077:5;30061:22;;;;;;;;;:::i;:::-;;;;;30056:27;;30162:5;30154:13;;29937:245;30211:1;30201:6;:11;;;;:25;;;;;30225:1;30216:6;:10;;;30201:25;30200:42;;;;30231:6;:11;;30241:1;30231:11;30200:42;30196:125;;;30269:37;30282:6;30290:4;30296:5;30303:2;30269:12;:37::i;:::-;30262:44;;;;;;;;;;;30196:125;30354:13;30335:16;30506:4;30496:14;;;;30492:446;;30575:21;30578:4;30585:6;30578:13;30593:2;30575;:21::i;:::-;30569:27;;;;30633:10;30628:15;;30667:16;30628:15;30681:1;30667:7;:16::i;:::-;30661:22;;30715:4;30705:6;:14;;;;:32;;;;;30723:6;:14;;30733:4;30723:14;;30705:32;30701:223;;;30802:4;30790:16;;30904:1;30896:9;;30701:223;30512:426;30492:446;30971:10;30984:26;30992:4;30998:2;31002;31006:3;30984:7;:26::i;:::-;31013:10;30984:39;;;;-1:-1:-1;31109:4:144;31102:11;;;31141;;;:24;;;;;31164:1;31156:4;:9;;;;31141:24;:39;;;;;31176:4;31169;:11;;;31141:39;31137:860;;;31204:4;:9;;31212:1;31204:9;:22;;;;31217:4;:9;;31225:1;31217:9;31204:22;31200:144;;;31288:37;31299:4;:9;;31307:1;31299:9;:21;;31315:5;31299:21;;;31311:1;31299:21;31322:2;31288:10;:37::i;:::-;31281:44;;;;;;;;;;;;;;;31200:144;31366:4;:11;;31374:3;31366:11;31362:121;;31436:28;31445:5;31452:2;31456:7;;;;31436:8;:28::i;31362:121::-;31504:4;:11;;31512:3;31504:11;31500:121;;31574:28;31583:5;31590:2;31594:7;;;;;31574:8;:28::i;31500:121::-;31691:4;:11;;31699:3;31691:11;31687:93;;31733:28;31747:13;31733;:28::i;31687:93::-;31883:4;31875;:12;;;;:27;;;;;31898:4;31891;:11;;;31875:27;31871:112;;;31933:31;31944:4;31950:2;31954;31958:5;31933:10;:31::i;31871:112::-;32057:6;:14;;32067:4;32057:14;:28;;;;-1:-1:-1;32075:10:144;;;;;32057:28;32053:93;;;32130:1;32105:5;:15;;;32121:5;32105:22;;;;;;;;;:::i;:::-;:26;;;;:22;;;;;;:26;32053:93;32192:9;:26;;32205:13;32192:26;32188:92;;32238:27;32247:9;32258:1;32261:3;32238:8;:27::i;:::-;32361:26;32370:5;32377:3;32382:4;32361:8;:26::i;:::-;32354:33;;;;;;;;;;;;;26025:6379;;;;;;;;:::o;3087:2334::-;3634:4;3628:11;;3550:4;3353:31;3342:43;;3413:13;3353:31;3752:2;3452:13;;3342:43;3359:24;3353:31;3452:13;;;3342:43;;;;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3413:13;4180:11;3359:24;3353:31;3452:13;;;3342:43;3413:13;4275:11;3359:24;3353:31;3452:13;;;3342:43;3359:24;3353:31;3452:13;;;3342:43;3128:12;;4415:13;;3628:11;;3452:13;;;;4180:11;3128:12;4495:84;4520:2;4517:1;4514:9;4495:84;;;3369:13;3359:24;;3353:31;3342:43;;3373:2;3413:13;;;;4575:1;3452:13;;;;4538:1;4531:9;4495:84;;;4499:14;4642:1;4638:2;4631:13;4737:5;4733:2;4729:14;4722:5;4717:27;4811:1;4797:15;;4832:6;4856:1;4851:273;;;;5191:1;5181:11;;4825:369;;4851:273;4883:8;4941:22;;;;5020:1;5015:22;;;;5107:1;5097:11;;4876:234;;4941:22;4960:1;4950:11;;4941:22;;5015;5034:1;5024:11;;4876:234;;4825:369;-1:-1:-1;;;5317:14:144;;;5300:32;;5360:19;5356:30;5392:3;5388:16;;;;5353:52;;3087:2334;-1:-1:-1;3087:2334:144:o;21746:1831::-;21819:11;21930:14;21947:24;21959:11;21947;:24::i;:::-;21930:41;;22079:1;22072:5;22068:13;22065:33;;;22094:1;22091;22084:12;22065:33;22227:2;22215:15;;;22168:20;22657:5;22654:1;22650:13;22692:4;22728:1;22713:343;22738:2;22735:1;22732:9;22713:343;;;22861:2;22849:15;;;22798:20;22896:12;;;22910:1;22892:20;22933:42;;;;23001:1;22996:42;;;;22885:153;;22933:42;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;22942:31;;22933:42;;22996;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;23005:31;;22885:153;-1:-1:-1;;22756:1:144;22749:9;22713:343;;;22717:14;23166:4;23160:11;23145:26;;23252:7;23246:4;23243:17;23233:124;;23294:10;23291:1;23284:21;23336:2;23333:1;23326:13;23233:124;-1:-1:-1;;23484:2:144;23473:14;;;;23461:10;23457:31;23454:1;23450:39;23518:16;;;;23536:10;23514:33;;21746:1831;-1:-1:-1;;;21746:1831:144:o;18856:823::-;18925:12;19012:18;;:::i;:::-;19080:4;19071:13;;19132:5;:8;;;19143:1;19132:12;19116:28;;:5;:12;;;:28;;;19112:95;;19164:28;;;;;2182:2:319;19164:28:144;;;2164:21:319;2221:2;2201:18;;;2194:30;2260:20;2240:18;;;2233:48;2298:18;;19164:28:144;;;;;;;;19112:95;19296:8;;;;;19329:12;;;;;19318:23;;;;;;;19355:20;;;;;19296:8;19487:13;;;19483:90;;19548:6;19557:1;19548:10;19520:5;:15;;;19536:8;19520:25;;;;;;;;;:::i;:::-;:38;;;;:25;;;;;;:38;19483:90;19649:13;:11;:13::i;2645:339::-;2706:11;2770:18;;;;2779:8;;;;2770:18;;;;;;2769:25;;;;;2786:1;2833:2;:9;;;2827:16;;;;;2826:22;;2825:32;;;;;;;2887:9;;2886:15;2769:25;2944:21;;2964:1;2944:21;;;2955:6;2944:21;2929:11;;;;;:37;;-1:-1:-1;;;2645:339:144;;;;:::o;13732:2026::-;13829:12;13915:18;;:::i;:::-;13983:4;13974:13;;14015:17;14075:5;:8;;;14086:1;14075:12;14059:28;;:5;:12;;;:28;;;14055:97;;14107:30;;;;;2529:2:319;14107:30:144;;;2511:21:319;2568:2;2548:18;;;2541:30;2607:22;2587:18;;;2580:50;2647:18;;14107:30:144;2327:344:319;14055:97:144;14222:7;:12;;14233:1;14222:12;:28;;;;14238:7;:12;;14249:1;14238:12;14222:28;14218:947;;;14270:9;14282:5;:15;;;14298:6;14282:23;;;;;;;;;:::i;:::-;;;;;14270:35;;14346:2;14339:9;;:3;:9;;;:25;;;;;14352:7;:12;;14363:1;14352:12;14339:25;14338:58;;;;14377:2;14370:9;;:3;:9;;;;:25;;;;;14383:7;:12;;14394:1;14383:12;14370:25;14323:73;;14252:159;14218:947;;;14508:7;:12;;14519:1;14508:12;14504:661;;14569:1;14561:3;14555:15;;;;14540:30;;14504:661;;;14673:7;:12;;14684:1;14673:12;14669:496;;14733:1;14726:3;14720:14;;;14705:29;;14669:496;;;14854:7;:12;;14865:1;14854:12;14850:315;;14942:4;14936:2;14927:11;;;14926:20;14912:10;14969:8;;;14965:84;;15029:1;15022:3;15016:14;;;15001:29;;14965:84;15070:3;:8;;15077:1;15070:8;15066:85;;15131:1;15123:3;15117:15;;;;15102:30;;15066:85;14868:297;14850:315;15241:8;;;;;15319:12;;;;15308:23;;;;;15475:178;;;;15566:1;15540:22;15543:5;15551:6;15543:14;15559:2;15540;:22::i;:::-;:27;;;;;;;15526:42;;15535:1;15526:42;15511:57;:12;;;:57;15475:178;;;15622:12;;;;;15637:1;15622:16;15607:31;;;;15475:178;15728:13;:11;:13::i;:::-;15721:20;13732:2026;-1:-1:-1;;;;;;;;13732:2026:144:o;32450:8733::-;32537:10;32599;32607:2;32599:10;;;;32638:11;;;:44;;;32664:1;32654:6;:11;;;;:27;;;;;32678:3;32669:6;:12;;;32654:27;32634:8490;;;32723:4;32716:11;;32847:6;32907:3;32902:25;;;;32982:3;32977:25;;;;33056:3;33051:25;;;;33131:3;33126:25;;;;33205:3;33200:25;;;;33278:3;33273:25;;;;33352:3;33347:25;;;;32840:532;;32902:25;32921:4;32913:12;;32902:25;;32977;32996:4;32988:12;;32977:25;;33051;33070:4;33062:12;;33051:25;;33126;33145:4;33137:12;;33126:25;;33200;33219:4;33211:12;;33200:25;;33273;33292:4;33284:12;;33273:25;;33347;33366:4;33358:12;;32840:532;;33435:4;:12;;33443:4;33435:12;33431:4023;;-1:-1:-1;;;33486:9:144;33478:26;;33499:4;33494:1;33486:9;;;33485:18;33478:26;33471:33;;33431:4023;33572:4;:12;;33580:4;33572:12;33568:3886;;-1:-1:-1;;;33623:9:144;33615:26;;33636:4;33631:1;33623:9;;;33622:18;33615:26;33608:33;;33568:3886;33709:4;:12;;33717:4;33709:12;33705:3749;;33774:4;33769:1;33761:9;;;33760:18;33807:27;33761:9;33810:11;;;;33823:2;:10;;;33807:2;:27::i;:::-;33800:34;;;;;;;33705:3749;33903:4;:12;;33911:4;33903:12;33899:3555;;-1:-1:-1;;;33946:17:144;;;33958:4;33953:9;;33946:17;33939:24;;33899:3555;34032:4;:11;;34040:3;34032:11;34028:3426;;-1:-1:-1;;;34074:17:144;;;34086:4;34081:9;;34074:17;34067:24;;34028:3426;34160:4;:12;;34168:4;34160:12;34156:3298;;34203:21;34212:2;34206:8;;:2;:8;;;;34221:2;34216;:7;34203:2;:21::i;:::-;34196:28;;;;;;34156:3298;34473:4;:12;;34481:4;34473:12;34469:2985;;34516:2;34509:9;;;;;;34469:2985;34587:4;:12;;34595:4;34587:12;34583:2871;;34630:2;34623:9;;;;;;34583:2871;34701:4;:12;;34709:4;34701:12;34697:2757;;34744:2;34737:9;;;;;;34697:2757;34815:4;:12;;34823:4;34815:12;34811:2643;;34858:2;34851:9;;;;;;34811:2643;34932:4;:12;;34940:4;34932:12;34928:2526;;34975:2;34968:9;;;;;;34928:2526;35092:4;:12;;35100:4;35092:12;35088:2366;;35135:2;35128:9;;;;;;35088:2366;35206:4;:12;;35214:4;35206:12;35202:2252;;35249:2;35242:9;;;;;;35202:2252;35320:4;:12;;35328:4;35320:12;35316:2138;;35363:2;35356:9;;;;;;35316:2138;35434:4;:12;;35442:4;35434:12;35430:2024;;35477:2;35470:9;;;;;;35430:2024;35548:4;:12;;35556:4;35548:12;35544:1910;;35591:2;35584:9;;;;;;35544:1910;35662:4;:12;;35670:4;35662:12;35658:1796;;35705:2;35698:9;;;;;;35658:1796;35777:4;:12;;35785:4;35777:12;35773:1681;;35820:2;35813:9;;;;;;35773:1681;35890:4;:12;;35898:4;35890:12;35886:1568;;35933:2;35926:9;;;;;;35886:1568;36004:4;:12;;36012:4;36004:12;36000:1454;;36047:2;36040:9;;;;;;36000:1454;36196:4;:12;;36204:4;36196:12;36192:1262;;-1:-1:-1;;;36240:7:144;;;36232:16;;36192:1262;36317:4;:12;;36325:4;36317:12;36313:1141;;-1:-1:-1;;;36361:7:144;;;36353:16;;36313:1141;36437:4;:12;;36445:4;36437:12;36433:1021;;-1:-1:-1;;;36481:7:144;;;36473:16;;36433:1021;36558:4;:12;;36566:4;36558:12;36554:900;;-1:-1:-1;;;36602:7:144;;;36594:16;;36554:900;36678:4;:12;;36686:4;36678:12;36674:780;;-1:-1:-1;;;36722:7:144;;;36714:16;;36674:780;36797:4;:12;;36805:4;36797:12;36793:661;;-1:-1:-1;;;36841:7:144;;;36833:16;;36793:661;36917:4;:12;;36925:4;36917:12;36913:541;;-1:-1:-1;;;36961:7:144;;;36953:16;;36913:541;37037:4;:12;;37045:4;37037:12;37033:421;;-1:-1:-1;;;37082:7:144;;;37080:10;37073:17;;37033:421;37159:4;:12;;37167:4;37159:12;37155:299;;37220:2;37202:21;;37208:2;37202:21;;;:29;;37230:1;37202:29;;;37226:1;37202:29;37195:36;;;;;;;;37155:299;37301:4;:12;;37309:4;37301:12;37297:157;;37349:2;37344:7;;:2;:7;;;:15;;37358:1;37344:15;;37297:157;37406:29;;;;;2878:2:319;37406:29:144;;;2860:21:319;2917:2;2897:18;;;2890:30;2956:21;2936:18;;;2929:49;2995:18;;37406:29:144;2676:343:319;37297:157:144;32684:4784;32634:8490;;;37524:6;:14;;37534:4;37524:14;37520:3590;;37583:4;37576:11;;37658:3;37650:11;;;37646:549;;-1:-1:-1;;;37703:21:144;;;37689:36;;37646:549;37810:4;:12;;37818:4;37810:12;:28;;;;37826:4;:12;;37834:4;37826:12;37810:28;37806:389;;;37870:4;:12;;37878:4;37870:12;37866:83;;37919:3;;;37866:83;37974:8;38012:127;38024:10;38019:15;;:20;38012:127;;38104:8;38071:3;38104:8;;;;;38071:3;38012:127;;;38171:1;-1:-1:-1;38164:8:144;;-1:-1:-1;;38164:8:144;37520:3590;38262:6;:14;;38272:4;38262:14;38258:2852;;-1:-1:-1;;38307:8:144;38313:2;38307:8;;;;38300:15;;38258:2852;38382:6;:14;;38392:4;38382:14;38378:2732;;38427:42;38445:2;38450:1;38445:6;38455:1;38444:12;38439:2;:17;38431:26;;:3;:26;;;;38461:4;38430:35;38467:1;38427:2;:42::i;:::-;38420:49;;;;;38378:2732;38536:6;:14;;38546:4;38536:14;38532:2578;;38581:45;38599:2;38604:1;38599:6;38609:1;38598:12;38593:2;:17;38585:26;;:3;:26;;;;38615:6;38584:37;38623:2;38581;:45::i;38532:2578::-;38694:6;:14;;38704:4;38694:14;38690:2420;;-1:-1:-1;;38745:21:144;38764:1;38759;38754:6;;38753:12;38745:21;;38802:36;;;38873:5;38868:10;;38745:21;;;;;38867:18;38860:25;;38690:2420;38952:6;:14;;38962:4;38952:14;38948:2162;;38997:3;38990:10;;;;;38948:2162;39068:6;:14;;39078:4;39068:14;39064:2046;;39128:2;39133:1;39128:6;39138:1;39127:12;39122:2;:17;39114:26;;:3;:26;;;;39144:4;39113:35;39106:42;;;;;39064:2046;39217:6;:14;;39227:4;39217:14;39213:1897;;39277:2;39282:1;39277:6;39287:1;39276:12;39271:2;:17;39263:26;;:3;:26;;;;39293:6;39262:37;39255:44;;;;;39213:1897;39368:6;:14;;39378:4;39368:14;39364:1746;;-1:-1:-1;;39419:26:144;39443:1;39438;39433:6;;39432:12;39427:2;:17;39419:26;;39481:41;;;39557:5;39552:10;;39419:26;;;;;39551:18;39544:25;;39364:1746;39637:6;:14;;39647:4;39637:14;39633:1477;;-1:-1:-1;;39694:4:144;39688:34;39720:1;39715;39710:6;;39709:12;39704:2;:17;39688:34;;39778:27;;;39758:48;;;39836:10;;39689:9;;;39688:34;;39835:18;39828:25;;39633:1477;39921:6;:14;;39931:4;39921:14;39917:1193;;-1:-1:-1;;39978:6:144;39972:36;40006:1;40001;39996:6;;39995:12;39990:2;:17;39972:36;;40064:29;;;40044:50;;;40124:10;;39973:11;;;39972:36;;40123:18;40116:25;;39917:1193;40210:6;:14;;40220:4;40210:14;40206:904;;-1:-1:-1;;40261:20:144;40279:1;40274;40269:6;;40268:12;40261:20;;40317:36;;;40389:5;40383:11;;40261:20;;;;;40382:19;40375:26;;40206:904;40469:6;:14;;40479:4;40469:14;40465:645;;40514:2;40507:9;;;;;40465:645;40585:6;:14;;40595:4;40585:14;40581:529;;-1:-1:-1;;40636:25:144;40659:1;40654;40649:6;;40648:12;40643:2;:17;40636:25;;40697:41;;;40774:5;40768:11;;40636:25;;;;;40767:19;40760:26;;40581:529;40853:6;:14;;40863:4;40853:14;40849:261;;40898:3;40891:10;;;;;40849:261;40968:6;:14;;40978:4;40968:14;40964:146;;41013:2;41006:9;;;32450:8733;;;;;;;:::o;19960:782::-;20046:12;20133:18;;:::i;:::-;-1:-1:-1;20201:4:144;20308:2;20296:14;;;;20288:41;;;;;;;3226:2:319;20288:41:144;;;3208:21:319;3265:2;3245:18;;;3238:30;3304:16;3284:18;;;3277:44;3338:18;;20288:41:144;3024:338:319;20288:41:144;20425:14;;;;;;;:30;;;20443:12;20425:30;20421:102;;;20504:4;20475:5;:15;;;20491:9;20475:26;;;;;;;;;:::i;:::-;:33;;;;:26;;;;;;:33;20421:102;20578:12;;;;;20567:23;;;;:8;;;:23;20634:1;20619:16;;;20604:31;;;20712:13;:11;:13::i;5582:7764::-;5646:12;5732:18;;:::i;:::-;-1:-1:-1;5910:15:144;;:18;;;;5800:4;6070:18;;;;6114;;;;6158;;;;;5800:4;;5890:17;;;;6070:18;6114;6248;;;6262:4;6248:18;6244:6792;;6298:2;6327:4;6322:9;;:14;6318:144;;6438:4;6433:9;;6425:4;:18;6419:24;6318:144;6483:2;:7;;6489:1;6483:7;6479:161;;6519:10;;;;;6551:16;;;;;;;;6519:10;-1:-1:-1;6479:161:144;;;6619:2;6614:7;;6479:161;6268:386;6244:6792;;;6756:10;:18;;6770:4;6756:18;6752:6284;;1745:10;6794:14;;6752:6284;;;6892:10;:18;;6906:4;6892:18;6888:6148;;6935:1;6930:6;;6888:6148;;;7060:10;:18;;7074:4;7060:18;7056:5980;;7113:4;7098:12;;;:19;7135:26;;;:14;;;:26;7186:13;:11;:13::i;:::-;7179:20;5582:7764;-1:-1:-1;;;;;;;;;5582:7764:144:o;7056:5980::-;7325:10;:18;;7339:4;7325:18;7321:5715;;7476:14;;;7472:2723;7321:5715;7472:2723;7646:22;;;;;7642:2553;;7771:10;7784:27;7792:2;7797:10;7792:15;7809:1;7784:7;:27::i;:::-;7895:17;;;;7771:40;;-1:-1:-1;7895:17:144;7873:19;8045:14;8064:1;8039:26;8035:146;;1676:4:145;1670:11;;1533:21;1787:15;;;1828:8;1822:4;1815:22;1850:27;;;1996:4;1983:18;;2098:17;;2003:19;1979:44;2025:11;1976:61;8093:65:144;;8035:146;8267:20;;;;;8234:54;;;;;;;;3540:25:319;;;8234:54:144;3601:23:319;;;3581:18;;;3574:51;8203:11:144;;;;8234:19;:6;:19;;;;3513:18:319;;8234:54:144;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8202:86;;;;8515:1;8511:2;8507:10;8612:9;8609:1;8605:17;8694:6;8687:5;8684:17;8681:40;;;8714:5;8704:15;;8681:40;;8797:6;8793:2;8790:14;8787:34;;;8817:2;8807:12;;8787:34;8923:3;8918:1;8910:6;8906:14;8901:3;8897:24;8893:34;8886:41;;9023:3;9019:1;9007:9;8998:6;8995:1;8991:14;8987:30;8983:38;8979:48;8972:55;;9178:1;9174;9170;9158:9;9155:1;9151:17;9147:25;9143:33;9139:41;9305:1;9301;9297;9288:6;9276:9;9273:1;9269:17;9265:30;9261:38;9257:46;9253:54;9235:72;;9436:10;9432:15;9426:4;9422:26;9414:34;;9552:3;9544:4;9540:9;9535:3;9531:19;9528:28;9521:35;;;;9698:33;9707:2;9712:10;9707:15;9724:1;9727:3;9698:8;:33::i;:::-;9753:20;;;:38;;;;;;;;;-1:-1:-1;7642:2553:144;;-1:-1:-1;;;7642:2553:144;;9910:18;;;;;9906:289;;10080:2;10075:7;;7321:5715;;9906:289;10134:10;10129:15;;2053:3;10166:10;;9906:289;7321:5715;;;10324:10;:18;;10338:4;10324:18;10320:2716;;10478:15;;;1824:1;10478:15;;:34;;-1:-1:-1;10497:15:144;;;1859:1;10497:15;10478:34;:57;;;-1:-1:-1;10516:19:144;;;1936:1;10516:19;10478:57;10474:1593;;;10564:2;10559:7;;10320:2716;;10474:1593;10690:23;;;;;10686:1381;;10737:10;10750:27;10758:2;10763:10;10758:15;10775:1;10750:7;:27::i;:::-;10853:17;;;;10737:40;;-1:-1:-1;11096:1:144;11088:10;;11190:1;11186:17;11265:13;;;11262:32;;;11287:5;11281:11;;11262:32;11573:14;;;11379:1;11569:22;;;11565:32;;;;11462:26;11486:1;11371:10;;;11466:18;;;11462:26;11561:43;11367:20;;11669:12;11797:17;;;:23;11865:1;11842:20;;;:24;11375:2;-1:-1:-1;11375:2:144;7321:5715;;10320:2716;12269:10;:18;;12283:4;12269:18;12265:771;;12379:2;:7;;12385:1;12379:7;12375:647;;12472:14;;;;;:40;;-1:-1:-1;12490:22:144;;;1978:1;12490:22;12472:40;:62;;;-1:-1:-1;12516:18:144;;;1897:1;12516:18;12472:62;12468:404;;;12567:1;12562:6;;12375:647;;12468:404;12613:15;;;1824:1;12613:15;;:34;;-1:-1:-1;12632:15:144;;;1859:1;12632:15;12613:34;:61;;;-1:-1:-1;12651:23:144;;;2021:1;12651:23;12613:61;:84;;;-1:-1:-1;12678:19:144;;;1936:1;12678:19;12613:84;12609:263;;;12730:1;12725:6;;7321:5715;;12375:647;12923:10;12918:15;;2087:4;12955:11;;12375:647;13111:15;;;;;:23;;;;:18;;;;:23;;;;13148:15;;:23;;;:18;;;;:23;-1:-1:-1;13237:12:144;;;;13226:23;;;:8;;;:23;13293:1;13278:16;13263:31;;;;;13316:13;:11;:13::i;16084:2480::-;16178:12;16264:18;;:::i;:::-;-1:-1:-1;16332:4:144;16364:10;16472:13;;;16481:4;16472:13;16468:1705;;-1:-1:-1;16511:8:144;;;;16468:1705;;;16630:5;:13;;16639:4;16630:13;16626:1547;;16663:14;;;:8;;;:14;16626:1547;;;16793:5;:13;;16802:4;16793:13;16789:1384;;-1:-1:-1;16832:8:144;;;;16789:1384;;;16951:5;:13;;16960:4;16951:13;16947:1226;;16984:14;;;:8;;;:14;16947:1226;;;17125:5;:13;;17134:4;17125:13;17121:1052;;17252:9;17198:17;17178;;;17198;;;;17178:37;17259:2;17252:9;;;;;17234:8;;;:28;17280:22;:8;;;:22;17121:1052;;;17439:5;:13;;17448:4;17439:13;17435:738;;17506:11;17492;;;17506;;;17492:25;17561:2;17554:9;;;;;17536:8;;;:28;17582:22;:8;;;:22;17435:738;;;17763:5;:13;;17772:4;17763:13;17759:414;;17833:3;17814:23;;17820:3;17814:23;;;;;;;:::i;:::-;;17796:42;;:8;;;:42;17874:23;;;;;;;;;;;;;:::i;:::-;;17856:42;;:8;;;:42;17759:414;;;18067:5;:13;;18076:4;18067:13;18063:110;;18117:3;18111:9;;:3;:9;;;;;;;:::i;:::-;;18100:20;;;;:8;;;:20;18149:9;;;;;;;;;;;:::i;:::-;;18138:20;;:8;;;:20;18063:110;18266:14;;;;18262:85;;18329:3;18300:5;:15;;;18316:9;18300:26;;;;;;;;;:::i;:::-;:32;;;;:26;;;;;;:32;18262:85;18401:12;;;;;18390:23;;;;:8;;;:23;18457:1;18442:16;;;18427:31;;;18534:13;:11;:13::i;:::-;18527:20;16084:2480;-1:-1:-1;;;;;;;16084:2480:144:o;23913:1654::-;24089:14;24106:24;24118:11;24106;:24::i;:::-;24089:41;;24238:1;24231:5;24227:13;24224:33;;;24253:1;24250;24243:12;24224:33;24392:2;24586:15;;;24411:2;24400:14;;24388:10;24384:31;24381:1;24377:39;24542:16;;;24327:20;;24527:10;24516:22;;;24512:27;24502:38;24499:60;25028:5;25025:1;25021:13;25099:1;25084:343;25109:2;25106:1;25103:9;25084:343;;;25232:2;25220:15;;;25169:20;25267:12;;;25281:1;25263:20;25304:42;;;;25372:1;25367:42;;;;25256:153;;25304:42;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;25313:31;;25304:42;;25367;22391:1;22384:12;;;22424:2;22417:13;;;22469:2;22456:16;;25376:31;;25256:153;-1:-1:-1;;25127:1:144;25120:9;25084:343;;;-1:-1:-1;;25526:4:144;25519:18;-1:-1:-1;;;;23913:1654:144:o;20946:586::-;21268:20;;;21292:7;21268:32;21261:3;:40;;;21374:14;;21429:17;;21423:24;;;21415:72;;;;;;;4277:2:319;21415:72:144;;;4259:21:319;4316:2;4296:18;;;4289:30;4355:34;4335:18;;;4328:62;4426:5;4406:18;;;4399:33;4449:19;;21415:72:144;4075:399:319;21415:72:144;21501:14;20946:586;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;467:347:319:-;518:8;528:6;582:3;575:4;567:6;563:17;559:27;549:55;;600:1;597;590:12;549:55;-1:-1:-1;623:20:319;;666:18;655:30;;652:50;;;698:1;695;688:12;652:50;735:4;727:6;723:17;711:29;;787:3;780:4;771:6;763;759:19;755:30;752:39;749:59;;;804:1;801;794:12;749:59;467:347;;;;;:::o;819:785::-;918:6;926;934;942;950;1003:2;991:9;982:7;978:23;974:32;971:52;;;1019:1;1016;1009:12;971:52;1059:9;1046:23;1088:18;1129:2;1121:6;1118:14;1115:34;;;1145:1;1142;1135:12;1115:34;1184:58;1234:7;1225:6;1214:9;1210:22;1184:58;:::i;:::-;1261:8;;-1:-1:-1;1158:84:319;-1:-1:-1;1349:2:319;1334:18;;1321:32;;-1:-1:-1;1365:16:319;;;1362:36;;;1394:1;1391;1384:12;1362:36;;1433:60;1485:7;1474:8;1463:9;1459:24;1433:60;:::i;:::-;819:785;;;;-1:-1:-1;1512:8:319;1594:2;1579:18;1566:32;;819:785;-1:-1:-1;;;;819:785:319:o;1791:184::-;1843:77;1840:1;1833:88;1940:4;1937:1;1930:15;1964:4;1961:1;1954:15;3636:245;3715:6;3723;3776:2;3764:9;3755:7;3751:23;3747:32;3744:52;;;3792:1;3789;3782:12;3744:52;-1:-1:-1;;3815:16:319;;3871:2;3856:18;;;3850:25;3815:16;;3850:25;;-1:-1:-1;3636:245:319:o;3886:184::-;3938:77;3935:1;3928:88;4035:4;4032:1;4025:15;4059:4;4056:1;4049:15" func init() { if err := json.Unmarshal([]byte(MIPSStorageLayoutJSON), MIPSStorageLayout); err != nil { diff --git a/op-bindings/bindings/optimismmintableerc20.go b/op-bindings/bindings/optimismmintableerc20.go index 0450ec37f705..f9ac81a2a95a 100644 --- a/op-bindings/bindings/optimismmintableerc20.go +++ b/op-bindings/bindings/optimismmintableerc20.go @@ -31,7 +31,7 @@ var ( // OptimismMintableERC20MetaData contains all meta data concerning the OptimismMintableERC20 contract. var OptimismMintableERC20MetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REMOTE_TOKEN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"remoteToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101406040523480156200001257600080fd5b5060405162001ad738038062001ad7833981016040819052620000359162000177565b6001600281858560036200004a8382620002b2565b506004620000598282620002b2565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff16610120526200037e565b80516001600160a01b0381168114620000a557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000d257600080fd5b81516001600160401b0380821115620000ef57620000ef620000aa565b604051601f8301601f19908116603f011681019082821181831017156200011a576200011a620000aa565b816040528381526020925086838588010111156200013757600080fd5b600091505b838210156200015b57858201830151818301840152908201906200013c565b838211156200016d5760008385830101525b9695505050505050565b600080600080600060a086880312156200019057600080fd5b6200019b866200008d565b9450620001ab602087016200008d565b60408701519094506001600160401b0380821115620001c957600080fd5b620001d789838a01620000c0565b94506060880151915080821115620001ee57600080fd5b50620001fd88828901620000c0565b925050608086015160ff811681146200021557600080fd5b809150509295509295909350565b600181811c908216806200023857607f821691505b6020821081036200025957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002ad57600081815260208120601f850160051c81016020861015620002885750805b601f850160051c820191505b81811015620002a95782815560010162000294565b5050505b505050565b81516001600160401b03811115620002ce57620002ce620000aa565b620002e681620002df845462000223565b846200025f565b602080601f8311600181146200031e5760008415620003055750858301515b600019600386901b1c1916600185901b178555620002a9565b600085815260208120601f198616915b828110156200034f578886015182559484019460019091019084016200032e565b50858210156200036e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516116ed620003ea6000396000610244015260008181610317015281816103ac015281816105f101526107cb0152600081816101a9015261033d0152600061075a015260006107310152600061070801526116ed6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", + Bin: "0x60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000a", } // OptimismMintableERC20ABI is the input ABI used to generate the binding from. diff --git a/op-bindings/bindings/optimismmintableerc20_more.go b/op-bindings/bindings/optimismmintableerc20_more.go index 9370be0182c4..4a6e59f67e88 100644 --- a/op-bindings/bindings/optimismmintableerc20_more.go +++ b/op-bindings/bindings/optimismmintableerc20_more.go @@ -13,7 +13,7 @@ const OptimismMintableERC20StorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\" var OptimismMintableERC20StorageLayout = new(solc.StorageLayout) -var OptimismMintableERC20DeployedBin = "0x608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" +var OptimismMintableERC20DeployedBin = "0x608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(OptimismMintableERC20StorageLayoutJSON), OptimismMintableERC20StorageLayout); err != nil { diff --git a/op-bindings/bindings/optimismmintableerc20factory.go b/op-bindings/bindings/optimismmintableerc20factory.go index 59ea87305e34..597a71b641ca 100644 --- a/op-bindings/bindings/optimismmintableerc20factory.go +++ b/op-bindings/bindings/optimismmintableerc20factory.go @@ -31,7 +31,7 @@ var ( // OptimismMintableERC20FactoryMetaData contains all meta data concerning the OptimismMintableERC20Factory contract. var OptimismMintableERC20FactoryMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\"}],\"name\":\"OptimismMintableERC20Created\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"StandardL2TokenCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createOptimismMintableERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"name\":\"createOptimismMintableERC20WithDecimals\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createStandardL2Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061001b6000610020565b610118565b600054600390610100900460ff16158015610042575060005460ff8083169116105b6100a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805461010060ff841661ffff19909216821717610100600160b01b03191661ff0019620100006001600160a01b0387160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6123ce806101276000396000f3fe60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e362e3100000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b611ad780620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe6101406040523480156200001257600080fd5b5060405162001ad738038062001ad7833981016040819052620000359162000177565b6001600281858560036200004a8382620002b2565b506004620000598282620002b2565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff16610120526200037e565b80516001600160a01b0381168114620000a557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000d257600080fd5b81516001600160401b0380821115620000ef57620000ef620000aa565b604051601f8301601f19908116603f011681019082821181831017156200011a576200011a620000aa565b816040528381526020925086838588010111156200013757600080fd5b600091505b838210156200015b57858201830151818301840152908201906200013c565b838211156200016d5760008385830101525b9695505050505050565b600080600080600060a086880312156200019057600080fd5b6200019b866200008d565b9450620001ab602087016200008d565b60408701519094506001600160401b0380821115620001c957600080fd5b620001d789838a01620000c0565b94506060880151915080821115620001ee57600080fd5b50620001fd88828901620000c0565b925050608086015160ff811681146200021557600080fd5b809150509295509295909350565b600181811c908216806200023857607f821691505b6020821081036200025957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002ad57600081815260208120601f850160051c81016020861015620002885750805b601f850160051c820191505b81811015620002a95782815560010162000294565b5050505b505050565b81516001600160401b03811115620002ce57620002ce620000aa565b620002e681620002df845462000223565b846200025f565b602080601f8311600181146200031e5760008415620003055750858301515b600019600386901b1c1916600185901b178555620002a9565b600085815260208120601f198616915b828110156200034f578886015182559484019460019091019084016200032e565b50858210156200036e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516116ed620003ea6000396000610244015260008181610317015281816103ac015281816105f101526107cb0152600081816101a9015261033d0152600061075a015260006107310152600061070801526116ed6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a", + Bin: "0x608060405234801561001057600080fd5b5061001b6000610020565b610118565b600054600390610100900460ff16158015610042575060005460ff8083169116105b6100a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805461010060ff841661ffff19909216821717610100600160b01b03191661ff0019620100006001600160a01b0387160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b612081806101276000396000f3fe60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e372e3000000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b61178a80620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a", } // OptimismMintableERC20FactoryABI is the input ABI used to generate the binding from. diff --git a/op-bindings/bindings/optimismmintableerc20factory_more.go b/op-bindings/bindings/optimismmintableerc20factory_more.go index 1542700419d7..955da8c91ed5 100644 --- a/op-bindings/bindings/optimismmintableerc20factory_more.go +++ b/op-bindings/bindings/optimismmintableerc20factory_more.go @@ -13,7 +13,7 @@ const OptimismMintableERC20FactoryStorageLayoutJSON = "{\"storage\":[{\"astId\": var OptimismMintableERC20FactoryStorageLayout = new(solc.StorageLayout) -var OptimismMintableERC20FactoryDeployedBin = "0x60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e362e3100000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b611ad780620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe6101406040523480156200001257600080fd5b5060405162001ad738038062001ad7833981016040819052620000359162000177565b6001600281858560036200004a8382620002b2565b506004620000598282620002b2565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff16610120526200037e565b80516001600160a01b0381168114620000a557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000d257600080fd5b81516001600160401b0380821115620000ef57620000ef620000aa565b604051601f8301601f19908116603f011681019082821181831017156200011a576200011a620000aa565b816040528381526020925086838588010111156200013757600080fd5b600091505b838210156200015b57858201830151818301840152908201906200013c565b838211156200016d5760008385830101525b9695505050505050565b600080600080600060a086880312156200019057600080fd5b6200019b866200008d565b9450620001ab602087016200008d565b60408701519094506001600160401b0380821115620001c957600080fd5b620001d789838a01620000c0565b94506060880151915080821115620001ee57600080fd5b50620001fd88828901620000c0565b925050608086015160ff811681146200021557600080fd5b809150509295509295909350565b600181811c908216806200023857607f821691505b6020821081036200025957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002ad57600081815260208120601f850160051c81016020861015620002885750805b601f850160051c820191505b81811015620002a95782815560010162000294565b5050505b505050565b81516001600160401b03811115620002ce57620002ce620000aa565b620002e681620002df845462000223565b846200025f565b602080601f8311600181146200031e5760008415620003055750858301515b600019600386901b1c1916600185901b178555620002a9565b600085815260208120601f198616915b828110156200034f578886015182559484019460019091019084016200032e565b50858210156200036e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516116ed620003ea6000396000610244015260008181610317015281816103ac015281816105f101526107cb0152600081816101a9015261033d0152600061075a015260006107310152600061070801526116ed6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a" +var OptimismMintableERC20FactoryDeployedBin = "0x60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e372e3000000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b61178a80620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(OptimismMintableERC20FactoryStorageLayoutJSON), OptimismMintableERC20FactoryStorageLayout); err != nil { diff --git a/op-bindings/bindings/preimageoracle_more.go b/op-bindings/bindings/preimageoracle_more.go index c5578cb53502..085699713b21 100644 --- a/op-bindings/bindings/preimageoracle_more.go +++ b/op-bindings/bindings/preimageoracle_more.go @@ -15,7 +15,7 @@ var PreimageOracleStorageLayout = new(solc.StorageLayout) var PreimageOracleDeployedBin = "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063e03110e111610050578063e03110e114610106578063e15926111461012e578063fef2b4ed1461014357600080fd5b806361238bde146100775780638542cf50146100b5578063c0c220c9146100f3575b600080fd5b6100a26100853660046104df565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6100e36100c33660046104df565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016100ac565b6100a2610101366004610501565b610163565b6101196101143660046104df565b610238565b604080519283526020830191909152016100ac565b61014161013c36600461053c565b610329565b005b6100a26101513660046105b8565b60006020819052908152604090205481565b600061016f8686610432565b905061017c836008610600565b8211806101895750602083115b156101c0576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b6000828152600260209081526040808320848452909152812054819060ff166102c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546102dd816008610600565b6102e8856020610600565b1061030657836102f9826008610600565b6103039190610618565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018611156103485763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316176104d8818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b600080604083850312156104f257600080fd5b50508035926020909101359150565b600080600080600060a0868803121561051957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060006040848603121561055157600080fd5b83359250602084013567ffffffffffffffff8082111561057057600080fd5b818601915086601f83011261058457600080fd5b81358181111561059357600080fd5b8760208285010111156105a557600080fd5b6020830194508093505050509250925092565b6000602082840312156105ca57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610613576106136105d1565b500190565b60008282101561062a5761062a6105d1565b50039056fea164736f6c634300080f000a" -var PreimageOracleDeployedSourceMap = "306:3911:146:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;537:68;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;413:25:310;;;401:2;386:18;537:68:146;;;;;;;;680:66;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;614:14:310;;607:22;589:41;;577:2;562:18;680:66:146;449:187:310;1367:1211:146;;;;;;:::i;:::-;;:::i;789:536::-;;;;;;:::i;:::-;;:::i;:::-;;;;1274:25:310;;;1330:2;1315:18;;1308:34;;;;1247:18;789:536:146;1100:248:310;2620:1595:146;;;;;;:::i;:::-;;:::i;:::-;;419:50;;;;;;:::i;:::-;;;;;;;;;;;;;;;1367:1211;1560:12;1665:51;1694:6;1702:13;1665:28;:51::i;:::-;1658:58;-1:-1:-1;1810:9:146;:5;1818:1;1810:9;:::i;:::-;1796:11;:23;:37;;;;1831:2;1823:5;:10;1796:37;1792:90;;;1856:15;;;;;;;;;;;;;;1792:90;1951:12;2051:4;2044:18;;;2152:3;2148:15;;;2135:29;;2184:4;2177:19;;;;2286:18;;2376:20;;;:14;:20;;;;;;:33;;;;;;;;:40;;;;2412:4;2376:40;;;;;;2426:19;;;;;;;;:32;;;;;;;;;:39;2542:21;;;;;;;;;:29;2391:4;1367:1211;-1:-1:-1;;1367:1211:146:o;789:536::-;865:12;914:20;;;:14;:20;;;;;;;;:29;;;;;;;;;865:12;;914:29;;906:62;;;;;;;2908:2:310;906:62:146;;;2890:21:310;2947:2;2927:18;;;2920:30;2986:22;2966:18;;;2959:50;3026:18;;906:62:146;;;;;;;;-1:-1:-1;1099:14:146;1116:21;;;1087:2;1116:21;;;;;;;;1167:10;1116:21;1176:1;1167:10;:::i;:::-;1151:12;:7;1161:2;1151:12;:::i;:::-;:26;1147:87;;1216:7;1203:10;:6;1212:1;1203:10;:::i;:::-;:20;;;;:::i;:::-;1193:30;;1147:87;-1:-1:-1;1290:19:146;;;;:13;:19;;;;;;;;:28;;;;;;;;;;;;789:536;;-1:-1:-1;789:536:146:o;2620:1595::-;2916:4;2903:18;2721:12;;3045:1;3035:12;;3019:29;;3016:210;;;3120:10;3117:1;3110:21;3210:1;3204:4;3197:15;3016:210;3469:3;3465:14;;;3369:4;3453:27;3500:11;3474:4;3619:16;3500:11;3601:41;3832:29;;;3836:11;3832:29;3826:36;3884:20;;;;4031:19;4024:27;4053:11;4021:44;4084:19;;;;4062:1;4084:19;;;;;;;;:32;;;;;;;;:39;;;;4119:4;4084:39;;;;;;4133:18;;;;;;;;:31;;;;;;;;;:38;;;;4181:20;;;;;;;;;;;:27;;;;-1:-1:-1;;;;2620:1595:146:o;552:449:145:-;835:11;860:19;848:32;;832:49;965:29;832:49;980:13;1676:4;1670:11;;1533:21;1787:15;;;1828:8;1822:4;1815:22;1850:27;;;1996:4;1983:18;;;2098:17;;2003:19;1979:44;2025:11;1976:61;;1455:676;965:29;958:36;552:449;-1:-1:-1;;;552:449:145:o;14:248:310:-;82:6;90;143:2;131:9;122:7;118:23;114:32;111:52;;;159:1;156;149:12;111:52;-1:-1:-1;;182:23:310;;;252:2;237:18;;;224:32;;-1:-1:-1;14:248:310:o;641:454::-;736:6;744;752;760;768;821:3;809:9;800:7;796:23;792:33;789:53;;;838:1;835;828:12;789:53;-1:-1:-1;;861:23:310;;;931:2;916:18;;903:32;;-1:-1:-1;982:2:310;967:18;;954:32;;1033:2;1018:18;;1005:32;;-1:-1:-1;1084:3:310;1069:19;1056:33;;-1:-1:-1;641:454:310;-1:-1:-1;641:454:310:o;1353:659::-;1432:6;1440;1448;1501:2;1489:9;1480:7;1476:23;1472:32;1469:52;;;1517:1;1514;1507:12;1469:52;1553:9;1540:23;1530:33;;1614:2;1603:9;1599:18;1586:32;1637:18;1678:2;1670:6;1667:14;1664:34;;;1694:1;1691;1684:12;1664:34;1732:6;1721:9;1717:22;1707:32;;1777:7;1770:4;1766:2;1762:13;1758:27;1748:55;;1799:1;1796;1789:12;1748:55;1839:2;1826:16;1865:2;1857:6;1854:14;1851:34;;;1881:1;1878;1871:12;1851:34;1926:7;1921:2;1912:6;1908:2;1904:15;1900:24;1897:37;1894:57;;;1947:1;1944;1937:12;1894:57;1978:2;1974;1970:11;1960:21;;2000:6;1990:16;;;;;1353:659;;;;;:::o;2017:180::-;2076:6;2129:2;2117:9;2108:7;2104:23;2100:32;2097:52;;;2145:1;2142;2135:12;2097:52;-1:-1:-1;2168:23:310;;2017:180;-1:-1:-1;2017:180:310:o;2384:184::-;2436:77;2433:1;2426:88;2533:4;2530:1;2523:15;2557:4;2554:1;2547:15;2573:128;2613:3;2644:1;2640:6;2637:1;2634:13;2631:39;;;2650:18;;:::i;:::-;-1:-1:-1;2686:9:310;;2573:128::o;3055:125::-;3095:4;3123:1;3120;3117:8;3114:34;;;3128:18;;:::i;:::-;-1:-1:-1;3165:9:310;;3055:125::o" +var PreimageOracleDeployedSourceMap = "306:3911:146:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;537:68;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;413:25:319;;;401:2;386:18;537:68:146;;;;;;;;680:66;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;614:14:319;;607:22;589:41;;577:2;562:18;680:66:146;449:187:319;1367:1211:146;;;;;;:::i;:::-;;:::i;789:536::-;;;;;;:::i;:::-;;:::i;:::-;;;;1274:25:319;;;1330:2;1315:18;;1308:34;;;;1247:18;789:536:146;1100:248:319;2620:1595:146;;;;;;:::i;:::-;;:::i;:::-;;419:50;;;;;;:::i;:::-;;;;;;;;;;;;;;;1367:1211;1560:12;1665:51;1694:6;1702:13;1665:28;:51::i;:::-;1658:58;-1:-1:-1;1810:9:146;:5;1818:1;1810:9;:::i;:::-;1796:11;:23;:37;;;;1831:2;1823:5;:10;1796:37;1792:90;;;1856:15;;;;;;;;;;;;;;1792:90;1951:12;2051:4;2044:18;;;2152:3;2148:15;;;2135:29;;2184:4;2177:19;;;;2286:18;;2376:20;;;:14;:20;;;;;;:33;;;;;;;;:40;;;;2412:4;2376:40;;;;;;2426:19;;;;;;;;:32;;;;;;;;;:39;2542:21;;;;;;;;;:29;2391:4;1367:1211;-1:-1:-1;;1367:1211:146:o;789:536::-;865:12;914:20;;;:14;:20;;;;;;;;:29;;;;;;;;;865:12;;914:29;;906:62;;;;;;;2908:2:319;906:62:146;;;2890:21:319;2947:2;2927:18;;;2920:30;2986:22;2966:18;;;2959:50;3026:18;;906:62:146;;;;;;;;-1:-1:-1;1099:14:146;1116:21;;;1087:2;1116:21;;;;;;;;1167:10;1116:21;1176:1;1167:10;:::i;:::-;1151:12;:7;1161:2;1151:12;:::i;:::-;:26;1147:87;;1216:7;1203:10;:6;1212:1;1203:10;:::i;:::-;:20;;;;:::i;:::-;1193:30;;1147:87;-1:-1:-1;1290:19:146;;;;:13;:19;;;;;;;;:28;;;;;;;;;;;;789:536;;-1:-1:-1;789:536:146:o;2620:1595::-;2916:4;2903:18;2721:12;;3045:1;3035:12;;3019:29;;3016:210;;;3120:10;3117:1;3110:21;3210:1;3204:4;3197:15;3016:210;3469:3;3465:14;;;3369:4;3453:27;3500:11;3474:4;3619:16;3500:11;3601:41;3832:29;;;3836:11;3832:29;3826:36;3884:20;;;;4031:19;4024:27;4053:11;4021:44;4084:19;;;;4062:1;4084:19;;;;;;;;:32;;;;;;;;:39;;;;4119:4;4084:39;;;;;;4133:18;;;;;;;;:31;;;;;;;;;:38;;;;4181:20;;;;;;;;;;;:27;;;;-1:-1:-1;;;;2620:1595:146:o;552:449:145:-;835:11;860:19;848:32;;832:49;965:29;832:49;980:13;1676:4;1670:11;;1533:21;1787:15;;;1828:8;1822:4;1815:22;1850:27;;;1996:4;1983:18;;;2098:17;;2003:19;1979:44;2025:11;1976:61;;1455:676;965:29;958:36;552:449;-1:-1:-1;;;552:449:145:o;14:248:319:-;82:6;90;143:2;131:9;122:7;118:23;114:32;111:52;;;159:1;156;149:12;111:52;-1:-1:-1;;182:23:319;;;252:2;237:18;;;224:32;;-1:-1:-1;14:248:319:o;641:454::-;736:6;744;752;760;768;821:3;809:9;800:7;796:23;792:33;789:53;;;838:1;835;828:12;789:53;-1:-1:-1;;861:23:319;;;931:2;916:18;;903:32;;-1:-1:-1;982:2:319;967:18;;954:32;;1033:2;1018:18;;1005:32;;-1:-1:-1;1084:3:319;1069:19;1056:33;;-1:-1:-1;641:454:319;-1:-1:-1;641:454:319:o;1353:659::-;1432:6;1440;1448;1501:2;1489:9;1480:7;1476:23;1472:32;1469:52;;;1517:1;1514;1507:12;1469:52;1553:9;1540:23;1530:33;;1614:2;1603:9;1599:18;1586:32;1637:18;1678:2;1670:6;1667:14;1664:34;;;1694:1;1691;1684:12;1664:34;1732:6;1721:9;1717:22;1707:32;;1777:7;1770:4;1766:2;1762:13;1758:27;1748:55;;1799:1;1796;1789:12;1748:55;1839:2;1826:16;1865:2;1857:6;1854:14;1851:34;;;1881:1;1878;1871:12;1851:34;1926:7;1921:2;1912:6;1908:2;1904:15;1900:24;1897:37;1894:57;;;1947:1;1944;1937:12;1894:57;1978:2;1974;1970:11;1960:21;;2000:6;1990:16;;;;;1353:659;;;;;:::o;2017:180::-;2076:6;2129:2;2117:9;2108:7;2104:23;2100:32;2097:52;;;2145:1;2142;2135:12;2097:52;-1:-1:-1;2168:23:319;;2017:180;-1:-1:-1;2017:180:319:o;2384:184::-;2436:77;2433:1;2426:88;2533:4;2530:1;2523:15;2557:4;2554:1;2547:15;2573:128;2613:3;2644:1;2640:6;2637:1;2634:13;2631:39;;;2650:18;;:::i;:::-;-1:-1:-1;2686:9:319;;2573:128::o;3055:125::-;3095:4;3123:1;3120;3117:8;3114:34;;;3128:18;;:::i;:::-;-1:-1:-1;3165:9:319;;3055:125::o" func init() { if err := json.Unmarshal([]byte(PreimageOracleStorageLayoutJSON), PreimageOracleStorageLayout); err != nil { diff --git a/op-chain-ops/cmd/op-upgrade/main.go b/op-chain-ops/cmd/op-upgrade/main.go index aec5c07addfb..7fdf67c8967e 100644 --- a/op-chain-ops/cmd/op-upgrade/main.go +++ b/op-chain-ops/cmd/op-upgrade/main.go @@ -112,7 +112,7 @@ func entrypoint(ctx *cli.Context) error { name, _ := toDeployConfigName(chainConfig) config, err := genesis.NewDeployConfigWithNetwork(name, deployConfig) if err != nil { - log.Warn("Cannot find deploy config for network", "name", chainConfig.Name, "deploy-config-name", name, "path", deployConfig) + log.Warn("Cannot find deploy config for network", "name", chainConfig.Name, "deploy-config-name", name, "path", deployConfig, "err", err) } if config != nil { diff --git a/op-challenger/cmd/main_test.go b/op-challenger/cmd/main_test.go index c749c68bce4a..6c48087985b7 100644 --- a/op-challenger/cmd/main_test.go +++ b/op-challenger/cmd/main_test.go @@ -7,7 +7,6 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-challenger/config" - "github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" @@ -17,8 +16,8 @@ import ( var ( l1EthRpc = "http://example.com:8545" gameFactoryAddressValue = "0xbb00000000000000000000000000000000000000" - cannonNetwork = chaincfg.AvailableNetworks()[0] - otherCannonNetwork = chaincfg.AvailableNetworks()[1] + cannonNetwork = "op-mainnet" + otherCannonNetwork = "op-goerli" cannonBin = "./bin/cannon" cannonServer = "./bin/op-program" cannonPreState = "./pre.json" diff --git a/op-challenger/game/fault/agent.go b/op-challenger/game/fault/agent.go index a650a3b2a095..f589f9c78aa1 100644 --- a/op-challenger/game/fault/agent.go +++ b/op-challenger/game/fault/agent.go @@ -25,7 +25,7 @@ type Responder interface { } type ClaimLoader interface { - FetchClaims(ctx context.Context) ([]types.Claim, error) + GetAllClaims(ctx context.Context) ([]types.Claim, error) } type Agent struct { @@ -136,7 +136,7 @@ func (a *Agent) tryResolve(ctx context.Context) bool { var errNoResolvableClaims = errors.New("no resolvable claims") func (a *Agent) tryResolveClaims(ctx context.Context) error { - claims, err := a.loader.FetchClaims(ctx) + claims, err := a.loader.GetAllClaims(ctx) if err != nil { return fmt.Errorf("failed to fetch claims: %w", err) } @@ -189,7 +189,7 @@ func (a *Agent) resolveClaims(ctx context.Context) error { // newGameFromContracts initializes a new game state from the state in the contract func (a *Agent) newGameFromContracts(ctx context.Context) (types.Game, error) { - claims, err := a.loader.FetchClaims(ctx) + claims, err := a.loader.GetAllClaims(ctx) if err != nil { return nil, fmt.Errorf("failed to fetch claims: %w", err) } diff --git a/op-challenger/game/fault/agent_test.go b/op-challenger/game/fault/agent_test.go index c6b1904c74b1..44e3bb6313cb 100644 --- a/op-challenger/game/fault/agent_test.go +++ b/op-challenger/game/fault/agent_test.go @@ -124,7 +124,7 @@ type stubClaimLoader struct { claims []types.Claim } -func (s *stubClaimLoader) FetchClaims(ctx context.Context) ([]types.Claim, error) { +func (s *stubClaimLoader) GetAllClaims(ctx context.Context) ([]types.Claim, error) { s.callCount++ return s.claims, nil } diff --git a/op-challenger/game/fault/contracts/faultdisputegame.go b/op-challenger/game/fault/contracts/faultdisputegame.go new file mode 100644 index 000000000000..e50883e7447f --- /dev/null +++ b/op-challenger/game/fault/contracts/faultdisputegame.go @@ -0,0 +1,128 @@ +package contracts + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum/go-ethereum/common" +) + +const ( + methodGameDuration = "GAME_DURATION" + methodMaxGameDepth = "MAX_GAME_DEPTH" + methodAbsolutePrestate = "ABSOLUTE_PRESTATE" + methodStatus = "status" + methodClaimCount = "claimDataLen" + methodClaim = "claimData" +) + +type FaultDisputeGameContract struct { + multiCaller *batching.MultiCaller + contract *batching.BoundContract +} + +func NewFaultDisputeGameContract(addr common.Address, caller *batching.MultiCaller) (*FaultDisputeGameContract, error) { + fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi() + if err != nil { + return nil, fmt.Errorf("failed to load fault dispute game ABI: %w", err) + } + + return &FaultDisputeGameContract{ + multiCaller: caller, + contract: batching.NewBoundContract(fdgAbi, addr), + }, nil +} + +func (f *FaultDisputeGameContract) GetGameDuration(ctx context.Context) (uint64, error) { + result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodGameDuration)) + if err != nil { + return 0, fmt.Errorf("failed to fetch game duration: %w", err) + } + return result.GetUint64(0), nil +} + +func (f *FaultDisputeGameContract) GetMaxGameDepth(ctx context.Context) (uint64, error) { + result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodMaxGameDepth)) + if err != nil { + return 0, fmt.Errorf("failed to fetch max game depth: %w", err) + } + return result.GetBigInt(0).Uint64(), nil +} + +func (f *FaultDisputeGameContract) GetAbsolutePrestateHash(ctx context.Context) (common.Hash, error) { + result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodAbsolutePrestate)) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to fetch absolute prestate hash: %w", err) + } + return result.GetHash(0), nil +} + +func (f *FaultDisputeGameContract) GetStatus(ctx context.Context) (gameTypes.GameStatus, error) { + result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodStatus)) + if err != nil { + return 0, fmt.Errorf("failed to fetch status: %w", err) + } + return gameTypes.GameStatusFromUint8(result.GetUint8(0)) +} + +func (f *FaultDisputeGameContract) GetClaimCount(ctx context.Context) (uint64, error) { + result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodClaimCount)) + if err != nil { + return 0, fmt.Errorf("failed to fetch claim count: %w", err) + } + return result.GetBigInt(0).Uint64(), nil +} + +func (f *FaultDisputeGameContract) GetClaim(ctx context.Context, idx uint64) (types.Claim, error) { + result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodClaim, new(big.Int).SetUint64(idx))) + if err != nil { + return types.Claim{}, fmt.Errorf("failed to fetch claim %v: %w", idx, err) + } + return f.decodeClaim(result, int(idx)), nil +} + +func (f *FaultDisputeGameContract) GetAllClaims(ctx context.Context) ([]types.Claim, error) { + count, err := f.GetClaimCount(ctx) + if err != nil { + return nil, fmt.Errorf("failed to load claim count: %w", err) + } + + calls := make([]*batching.ContractCall, count) + for i := uint64(0); i < count; i++ { + calls[i] = f.contract.Call(methodClaim, new(big.Int).SetUint64(i)) + } + + results, err := f.multiCaller.Call(ctx, batching.BlockLatest, calls...) + if err != nil { + return nil, fmt.Errorf("failed to fetch claim data: %w", err) + } + + var claims []types.Claim + for idx, result := range results { + claims = append(claims, f.decodeClaim(result, idx)) + } + return claims, nil +} + +func (f *FaultDisputeGameContract) decodeClaim(result *batching.CallResult, contractIndex int) types.Claim { + parentIndex := result.GetUint32(0) + countered := result.GetBool(1) + claim := result.GetHash(2) + position := result.GetBigInt(3) + clock := result.GetBigInt(4) + return types.Claim{ + ClaimData: types.ClaimData{ + Value: claim, + Position: types.NewPositionFromGIndex(position), + }, + Countered: countered, + Clock: clock.Uint64(), + ContractIndex: contractIndex, + ParentContractIndex: int(parentIndex), + } +} diff --git a/op-challenger/game/fault/contracts/faultdisputegame_test.go b/op-challenger/game/fault/contracts/faultdisputegame_test.go new file mode 100644 index 000000000000..6c9e6f2d8075 --- /dev/null +++ b/op-challenger/game/fault/contracts/faultdisputegame_test.go @@ -0,0 +1,169 @@ +package contracts + +import ( + "context" + "math" + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + batchingTest "github.com/ethereum-optimism/optimism/op-service/sources/batching/test" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestSimpleGetters(t *testing.T) { + tests := []struct { + method string + args []interface{} + result interface{} + expected interface{} // Defaults to expecting the same as result + call func(game *FaultDisputeGameContract) (any, error) + }{ + { + method: methodStatus, + result: types.GameStatusChallengerWon, + call: func(game *FaultDisputeGameContract) (any, error) { + return game.GetStatus(context.Background()) + }, + }, + { + method: methodGameDuration, + result: uint64(5566), + call: func(game *FaultDisputeGameContract) (any, error) { + return game.GetGameDuration(context.Background()) + }, + }, + { + method: methodMaxGameDepth, + result: big.NewInt(128), + expected: uint64(128), + call: func(game *FaultDisputeGameContract) (any, error) { + return game.GetMaxGameDepth(context.Background()) + }, + }, + { + method: methodAbsolutePrestate, + result: common.Hash{0xab}, + call: func(game *FaultDisputeGameContract) (any, error) { + return game.GetAbsolutePrestateHash(context.Background()) + }, + }, + { + method: methodClaimCount, + result: big.NewInt(9876), + expected: uint64(9876), + call: func(game *FaultDisputeGameContract) (any, error) { + return game.GetClaimCount(context.Background()) + }, + }, + } + for _, test := range tests { + test := test + t.Run(test.method, func(t *testing.T) { + stubRpc, game := setup(t) + stubRpc.SetResponse(test.method, batching.BlockLatest, nil, []interface{}{test.result}) + status, err := test.call(game) + require.NoError(t, err) + expected := test.expected + if expected == nil { + expected = test.result + } + require.Equal(t, expected, status) + }) + } +} + +func TestGetClaim(t *testing.T) { + stubRpc, game := setup(t) + idx := big.NewInt(2) + parentIndex := uint32(1) + countered := true + value := common.Hash{0xab} + position := big.NewInt(2) + clock := big.NewInt(1234) + stubRpc.SetResponse(methodClaim, batching.BlockLatest, []interface{}{idx}, []interface{}{parentIndex, countered, value, position, clock}) + status, err := game.GetClaim(context.Background(), idx.Uint64()) + require.NoError(t, err) + require.Equal(t, faultTypes.Claim{ + ClaimData: faultTypes.ClaimData{ + Value: value, + Position: faultTypes.NewPositionFromGIndex(position), + }, + Countered: true, + Clock: 1234, + ContractIndex: int(idx.Uint64()), + ParentContractIndex: 1, + }, status) +} + +func TestGetAllClaims(t *testing.T) { + stubRpc, game := setup(t) + claim0 := faultTypes.Claim{ + ClaimData: faultTypes.ClaimData{ + Value: common.Hash{0xaa}, + Position: faultTypes.NewPositionFromGIndex(big.NewInt(1)), + }, + Countered: true, + Clock: 1234, + ContractIndex: 0, + ParentContractIndex: math.MaxUint32, + } + claim1 := faultTypes.Claim{ + ClaimData: faultTypes.ClaimData{ + Value: common.Hash{0xab}, + Position: faultTypes.NewPositionFromGIndex(big.NewInt(2)), + }, + Countered: true, + Clock: 4455, + ContractIndex: 1, + ParentContractIndex: 0, + } + claim2 := faultTypes.Claim{ + ClaimData: faultTypes.ClaimData{ + Value: common.Hash{0xbb}, + Position: faultTypes.NewPositionFromGIndex(big.NewInt(6)), + }, + Countered: false, + Clock: 7777, + ContractIndex: 2, + ParentContractIndex: 1, + } + expectedClaims := []faultTypes.Claim{claim0, claim1, claim2} + stubRpc.SetResponse(methodClaimCount, batching.BlockLatest, nil, []interface{}{big.NewInt(int64(len(expectedClaims)))}) + for _, claim := range expectedClaims { + expectGetClaim(stubRpc, claim) + } + claims, err := game.GetAllClaims(context.Background()) + require.NoError(t, err) + require.Equal(t, expectedClaims, claims) +} + +func expectGetClaim(stubRpc *batchingTest.AbiBasedRpc, claim faultTypes.Claim) { + stubRpc.SetResponse( + methodClaim, + batching.BlockLatest, + []interface{}{big.NewInt(int64(claim.ContractIndex))}, + []interface{}{ + uint32(claim.ParentContractIndex), + claim.Countered, + claim.Value, + claim.Position.ToGIndex(), + big.NewInt(int64(claim.Clock)), + }) +} + +func setup(t *testing.T) (*batchingTest.AbiBasedRpc, *FaultDisputeGameContract) { + fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi() + require.NoError(t, err) + address := common.HexToAddress("0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB") + + stubRpc := batchingTest.NewAbiBasedRpc(t, fdgAbi, address) + caller := batching.NewMultiCaller(stubRpc, 100) + game, err := NewFaultDisputeGameContract(address, caller) + require.NoError(t, err) + return stubRpc, game +} diff --git a/op-challenger/game/fault/contracts/gamefactory.go b/op-challenger/game/fault/contracts/gamefactory.go new file mode 100644 index 000000000000..7b74ba533ade --- /dev/null +++ b/op-challenger/game/fault/contracts/gamefactory.go @@ -0,0 +1,60 @@ +package contracts + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum/go-ethereum/common" +) + +const ( + methodGameCount = "gameCount" + methodGameAtIndex = "gameAtIndex" +) + +type DisputeGameFactoryContract struct { + multiCaller *batching.MultiCaller + contract *batching.BoundContract +} + +func NewDisputeGameFactoryContract(addr common.Address, caller *batching.MultiCaller) (*DisputeGameFactoryContract, error) { + factoryAbi, err := bindings.DisputeGameFactoryMetaData.GetAbi() + if err != nil { + return nil, fmt.Errorf("failed to load dispute game factory ABI: %w", err) + } + return &DisputeGameFactoryContract{ + multiCaller: caller, + contract: batching.NewBoundContract(factoryAbi, addr), + }, nil +} + +func (f *DisputeGameFactoryContract) GetGameCount(ctx context.Context, blockNum uint64) (uint64, error) { + result, err := f.multiCaller.SingleCall(ctx, batching.BlockByNumber(blockNum), f.contract.Call(methodGameCount)) + if err != nil { + return 0, fmt.Errorf("failed to load game count: %w", err) + } + return result.GetBigInt(0).Uint64(), nil +} + +func (f *DisputeGameFactoryContract) GetGame(ctx context.Context, idx uint64, blockNum uint64) (types.GameMetadata, error) { + result, err := f.multiCaller.SingleCall(ctx, batching.BlockByNumber(blockNum), f.contract.Call(methodGameAtIndex, new(big.Int).SetUint64(idx))) + if err != nil { + return types.GameMetadata{}, fmt.Errorf("failed to load game %v: %w", idx, err) + } + return f.decodeGame(result), nil +} + +func (f *DisputeGameFactoryContract) decodeGame(result *batching.CallResult) types.GameMetadata { + gameType := result.GetUint8(0) + timestamp := result.GetUint64(1) + proxy := result.GetAddress(2) + return types.GameMetadata{ + GameType: gameType, + Timestamp: timestamp, + Proxy: proxy, + } +} diff --git a/op-challenger/game/fault/contracts/gamefactory_test.go b/op-challenger/game/fault/contracts/gamefactory_test.go new file mode 100644 index 000000000000..15888cc41970 --- /dev/null +++ b/op-challenger/game/fault/contracts/gamefactory_test.go @@ -0,0 +1,99 @@ +package contracts + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + batchingTest "github.com/ethereum-optimism/optimism/op-service/sources/batching/test" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestDisputeGameFactorySimpleGetters(t *testing.T) { + blockNum := uint64(23) + tests := []struct { + method string + args []interface{} + result interface{} + expected interface{} // Defaults to expecting the same as result + call func(game *DisputeGameFactoryContract) (any, error) + }{ + { + method: methodGameCount, + result: big.NewInt(9876), + expected: uint64(9876), + call: func(game *DisputeGameFactoryContract) (any, error) { + return game.GetGameCount(context.Background(), blockNum) + }, + }, + } + for _, test := range tests { + test := test + t.Run(test.method, func(t *testing.T) { + stubRpc, factory := setupDisputeGameFactoryTest(t) + stubRpc.SetResponse(test.method, batching.BlockByNumber(blockNum), nil, []interface{}{test.result}) + status, err := test.call(factory) + require.NoError(t, err) + expected := test.expected + if expected == nil { + expected = test.result + } + require.Equal(t, expected, status) + }) + } +} + +func TestLoadGame(t *testing.T) { + blockNum := uint64(23) + stubRpc, factory := setupDisputeGameFactoryTest(t) + game0 := types.GameMetadata{ + GameType: 0, + Timestamp: 1234, + Proxy: common.Address{0xaa}, + } + game1 := types.GameMetadata{ + GameType: 1, + Timestamp: 5678, + Proxy: common.Address{0xbb}, + } + game2 := types.GameMetadata{ + GameType: 99, + Timestamp: 9988, + Proxy: common.Address{0xcc}, + } + expectedGames := []types.GameMetadata{game0, game1, game2} + for idx, expected := range expectedGames { + expectGetGame(stubRpc, idx, blockNum, expected) + actual, err := factory.GetGame(context.Background(), uint64(idx), blockNum) + require.NoError(t, err) + require.Equal(t, expected, actual) + } +} + +func expectGetGame(stubRpc *batchingTest.AbiBasedRpc, idx int, blockNum uint64, game types.GameMetadata) { + stubRpc.SetResponse( + methodGameAtIndex, + batching.BlockByNumber(blockNum), + []interface{}{big.NewInt(int64(idx))}, + []interface{}{ + game.GameType, + game.Timestamp, + game.Proxy, + }) +} + +func setupDisputeGameFactoryTest(t *testing.T) (*batchingTest.AbiBasedRpc, *DisputeGameFactoryContract) { + fdgAbi, err := bindings.DisputeGameFactoryMetaData.GetAbi() + require.NoError(t, err) + address := common.HexToAddress("0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB") + + stubRpc := batchingTest.NewAbiBasedRpc(t, fdgAbi, address) + caller := batching.NewMultiCaller(stubRpc, 100) + factory, err := NewDisputeGameFactoryContract(address, caller) + require.NoError(t, err) + return stubRpc, factory +} diff --git a/op-challenger/game/fault/loader.go b/op-challenger/game/fault/loader.go deleted file mode 100644 index 55bfbae90b5f..000000000000 --- a/op-challenger/game/fault/loader.go +++ /dev/null @@ -1,141 +0,0 @@ -package fault - -import ( - "context" - "math/big" - - "github.com/ethereum-optimism/optimism/op-bindings/bindings" - "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" - gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" -) - -// MinimalFaultDisputeGameCaller is a minimal interface around [bindings.FaultDisputeGameCaller]. -// This needs to be updated if the [bindings.FaultDisputeGameCaller] interface changes. -type MinimalFaultDisputeGameCaller interface { - ClaimData(opts *bind.CallOpts, arg0 *big.Int) (struct { - ParentIndex uint32 - Countered bool - Claim [32]byte - Position *big.Int - Clock *big.Int - }, error) - Status(opts *bind.CallOpts) (uint8, error) - ClaimDataLen(opts *bind.CallOpts) (*big.Int, error) - MAXGAMEDEPTH(opts *bind.CallOpts) (*big.Int, error) - ABSOLUTEPRESTATE(opts *bind.CallOpts) ([32]byte, error) -} - -// loader pulls in fault dispute game claim data periodically and over subscriptions. -type loader struct { - caller MinimalFaultDisputeGameCaller -} - -// NewLoader creates a new [loader]. -func NewLoader(caller MinimalFaultDisputeGameCaller) *loader { - return &loader{ - caller: caller, - } -} - -// NewLoaderFromBindings creates a new [loader] from a [bindings.FaultDisputeGameCaller]. -func NewLoaderFromBindings(fdgAddr common.Address, client bind.ContractCaller) (*loader, error) { - caller, err := bindings.NewFaultDisputeGameCaller(fdgAddr, client) - if err != nil { - return nil, err - } - return NewLoader(caller), nil -} - -// GetGameStatus returns the current game status. -func (l *loader) GetGameStatus(ctx context.Context) (gameTypes.GameStatus, error) { - status, err := l.caller.Status(&bind.CallOpts{Context: ctx}) - return gameTypes.GameStatus(status), err -} - -// GetClaimCount returns the number of claims in the game. -func (l *loader) GetClaimCount(ctx context.Context) (uint64, error) { - count, err := l.caller.ClaimDataLen(&bind.CallOpts{Context: ctx}) - if err != nil { - return 0, err - } - return count.Uint64(), nil -} - -// FetchGameDepth fetches the game depth from the fault dispute game. -func (l *loader) FetchGameDepth(ctx context.Context) (uint64, error) { - callOpts := bind.CallOpts{ - Context: ctx, - } - - gameDepth, err := l.caller.MAXGAMEDEPTH(&callOpts) - if err != nil { - return 0, err - } - - return gameDepth.Uint64(), nil -} - -// fetchClaim fetches a single [Claim] with a hydrated parent. -func (l *loader) fetchClaim(ctx context.Context, arrIndex uint64) (types.Claim, error) { - callOpts := bind.CallOpts{ - Context: ctx, - } - - fetchedClaim, err := l.caller.ClaimData(&callOpts, new(big.Int).SetUint64(arrIndex)) - if err != nil { - return types.Claim{}, err - } - - claim := types.Claim{ - ClaimData: types.ClaimData{ - Value: fetchedClaim.Claim, - Position: types.NewPositionFromGIndex(fetchedClaim.Position), - }, - Countered: fetchedClaim.Countered, - Clock: fetchedClaim.Clock.Uint64(), - ContractIndex: int(arrIndex), - ParentContractIndex: int(fetchedClaim.ParentIndex), - } - - return claim, nil -} - -// FetchClaims fetches all claims from the fault dispute game. -func (l *loader) FetchClaims(ctx context.Context) ([]types.Claim, error) { - // Get the current claim count. - claimCount, err := l.caller.ClaimDataLen(&bind.CallOpts{ - Context: ctx, - }) - if err != nil { - return nil, err - } - - // Fetch each claim and build a list. - claimList := make([]types.Claim, claimCount.Uint64()) - for i := uint64(0); i < claimCount.Uint64(); i++ { - claim, err := l.fetchClaim(ctx, i) - if err != nil { - return nil, err - } - claimList[i] = claim - } - - return claimList, nil -} - -// FetchAbsolutePrestateHash fetches the hashed absolute prestate from the fault dispute game. -func (l *loader) FetchAbsolutePrestateHash(ctx context.Context) (common.Hash, error) { - callOpts := bind.CallOpts{ - Context: ctx, - } - - absolutePrestate, err := l.caller.ABSOLUTEPRESTATE(&callOpts) - if err != nil { - return common.Hash{}, err - } - - return absolutePrestate, nil -} diff --git a/op-challenger/game/fault/loader_test.go b/op-challenger/game/fault/loader_test.go deleted file mode 100644 index 886076373432..000000000000 --- a/op-challenger/game/fault/loader_test.go +++ /dev/null @@ -1,266 +0,0 @@ -package fault - -import ( - "context" - "fmt" - "math/big" - "testing" - - "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" - gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" -) - -var ( - mockClaimDataError = fmt.Errorf("claim data errored") - mockClaimLenError = fmt.Errorf("claim len errored") - mockMaxGameDepthError = fmt.Errorf("max game depth errored") - mockPrestateError = fmt.Errorf("prestate errored") - mockStatusError = fmt.Errorf("status errored") -) - -// TestLoader_GetGameStatus tests fetching the game status. -func TestLoader_GetGameStatus(t *testing.T) { - tests := []struct { - name string - status uint8 - expectedError bool - }{ - { - name: "challenger won status", - status: uint8(gameTypes.GameStatusChallengerWon), - }, - { - name: "defender won status", - status: uint8(gameTypes.GameStatusDefenderWon), - }, - { - name: "in progress status", - status: uint8(gameTypes.GameStatusInProgress), - }, - { - name: "error bubbled up", - expectedError: true, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - mockCaller := newMockCaller() - mockCaller.status = test.status - mockCaller.statusError = test.expectedError - loader := NewLoader(mockCaller) - status, err := loader.GetGameStatus(context.Background()) - if test.expectedError { - require.ErrorIs(t, err, mockStatusError) - } else { - require.NoError(t, err) - require.Equal(t, gameTypes.GameStatus(test.status), status) - } - }) - } -} - -// TestLoader_FetchGameDepth tests fetching the game depth. -func TestLoader_FetchGameDepth(t *testing.T) { - t.Run("Succeeds", func(t *testing.T) { - mockCaller := newMockCaller() - mockCaller.maxGameDepth = 10 - loader := NewLoader(mockCaller) - depth, err := loader.FetchGameDepth(context.Background()) - require.NoError(t, err) - require.Equal(t, uint64(10), depth) - }) - - t.Run("Errors", func(t *testing.T) { - mockCaller := newMockCaller() - mockCaller.maxGameDepthError = true - loader := NewLoader(mockCaller) - depth, err := loader.FetchGameDepth(context.Background()) - require.ErrorIs(t, mockMaxGameDepthError, err) - require.Equal(t, depth, uint64(0)) - }) -} - -// TestLoader_FetchAbsolutePrestateHash tests fetching the absolute prestate hash. -func TestLoader_FetchAbsolutePrestateHash(t *testing.T) { - t.Run("Succeeds", func(t *testing.T) { - mockCaller := newMockCaller() - loader := NewLoader(mockCaller) - prestate, err := loader.FetchAbsolutePrestateHash(context.Background()) - require.NoError(t, err) - require.ElementsMatch(t, common.HexToHash("0xdEad"), prestate) - }) - - t.Run("Errors", func(t *testing.T) { - mockCaller := newMockCaller() - mockCaller.prestateError = true - loader := NewLoader(mockCaller) - prestate, err := loader.FetchAbsolutePrestateHash(context.Background()) - require.Error(t, err) - require.ElementsMatch(t, common.Hash{}, prestate) - }) -} - -// TestLoader_FetchClaims tests fetching claims. -func TestLoader_FetchClaims(t *testing.T) { - t.Run("Succeeds", func(t *testing.T) { - mockCaller := newMockCaller() - expectedClaims := mockCaller.returnClaims - loader := NewLoader(mockCaller) - claims, err := loader.FetchClaims(context.Background()) - require.NoError(t, err) - require.ElementsMatch(t, []types.Claim{ - { - ClaimData: types.ClaimData{ - Value: expectedClaims[0].Claim, - Position: types.NewPositionFromGIndex(expectedClaims[0].Position), - }, - Countered: false, - Clock: uint64(0), - ContractIndex: 0, - }, - { - ClaimData: types.ClaimData{ - Value: expectedClaims[1].Claim, - Position: types.NewPositionFromGIndex(expectedClaims[1].Position), - }, - Countered: false, - Clock: uint64(0), - ContractIndex: 1, - ParentContractIndex: 0, - }, - { - ClaimData: types.ClaimData{ - Value: expectedClaims[2].Claim, - Position: types.NewPositionFromGIndex(expectedClaims[2].Position), - }, - Countered: false, - Clock: uint64(0), - ContractIndex: 2, - ParentContractIndex: 1, - }, - }, claims) - }) - - t.Run("Claim Data Errors", func(t *testing.T) { - mockCaller := newMockCaller() - mockCaller.claimDataError = true - loader := NewLoader(mockCaller) - claims, err := loader.FetchClaims(context.Background()) - require.ErrorIs(t, err, mockClaimDataError) - require.Empty(t, claims) - }) - - t.Run("Claim Len Errors", func(t *testing.T) { - mockCaller := newMockCaller() - mockCaller.claimLenError = true - loader := NewLoader(mockCaller) - claims, err := loader.FetchClaims(context.Background()) - require.ErrorIs(t, err, mockClaimLenError) - require.Empty(t, claims) - }) -} - -type mockCaller struct { - claimDataError bool - claimLenError bool - maxGameDepthError bool - prestateError bool - statusError bool - maxGameDepth uint64 - currentIndex uint64 - status uint8 - returnClaims []struct { - ParentIndex uint32 - Countered bool - Claim [32]byte - Position *big.Int - Clock *big.Int - } -} - -func newMockCaller() *mockCaller { - return &mockCaller{ - returnClaims: []struct { - ParentIndex uint32 - Countered bool - Claim [32]byte - Position *big.Int - Clock *big.Int - }{ - { - Claim: [32]byte{0x00}, - Position: big.NewInt(1), - Countered: false, - Clock: big.NewInt(0), - }, - { - Claim: [32]byte{0x01}, - Position: big.NewInt(2), - Countered: false, - Clock: big.NewInt(0), - ParentIndex: 0, - }, - { - Claim: [32]byte{0x02}, - Position: big.NewInt(3), - Countered: false, - Clock: big.NewInt(0), - ParentIndex: 1, - }, - }, - } -} - -func (m *mockCaller) ClaimData(opts *bind.CallOpts, arg0 *big.Int) (struct { - ParentIndex uint32 - Countered bool - Claim [32]byte - Position *big.Int - Clock *big.Int -}, error) { - if m.claimDataError { - return struct { - ParentIndex uint32 - Countered bool - Claim [32]byte - Position *big.Int - Clock *big.Int - }{}, mockClaimDataError - } - returnClaim := m.returnClaims[arg0.Uint64()] - m.currentIndex++ - return returnClaim, nil -} - -func (m *mockCaller) Status(opts *bind.CallOpts) (uint8, error) { - if m.statusError { - return 0, mockStatusError - } - return m.status, nil -} - -func (m *mockCaller) ClaimDataLen(opts *bind.CallOpts) (*big.Int, error) { - if m.claimLenError { - return big.NewInt(0), mockClaimLenError - } - return big.NewInt(int64(len(m.returnClaims))), nil -} - -func (m *mockCaller) MAXGAMEDEPTH(opts *bind.CallOpts) (*big.Int, error) { - if m.maxGameDepthError { - return nil, mockMaxGameDepthError - } - return big.NewInt(int64(m.maxGameDepth)), nil -} - -func (m *mockCaller) ABSOLUTEPRESTATE(opts *bind.CallOpts) ([32]byte, error) { - if m.prestateError { - return [32]byte{}, mockPrestateError - } - return common.HexToHash("0xdEad"), nil -} diff --git a/op-challenger/game/fault/player.go b/op-challenger/game/fault/player.go index f3d1917cd8e0..ca019e5c3041 100644 --- a/op-challenger/game/fault/player.go +++ b/op-challenger/game/fault/player.go @@ -5,22 +5,23 @@ import ( "context" "fmt" - "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-challenger/config" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/responder" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-challenger/metrics" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" "github.com/ethereum-optimism/optimism/op-service/txmgr" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" ) type actor func(ctx context.Context) error type GameInfo interface { - GetGameStatus(context.Context) (gameTypes.GameStatus, error) + GetStatus(context.Context) (gameTypes.GameStatus, error) GetClaimCount(context.Context) (uint64, error) } @@ -42,18 +43,16 @@ func NewGamePlayer( dir string, addr common.Address, txMgr txmgr.TxManager, - client bind.ContractCaller, + client *ethclient.Client, creator resourceCreator, ) (*GamePlayer, error) { logger = logger.New("game", addr) - contract, err := bindings.NewFaultDisputeGameCaller(addr, client) + loader, err := contracts.NewFaultDisputeGameContract(addr, batching.NewMultiCaller(client.Client(), batching.DefaultBatchSize)) if err != nil { - return nil, fmt.Errorf("failed to bind the fault dispute game contract: %w", err) + return nil, fmt.Errorf("failed to create fault dispute game contract wrapper: %w", err) } - loader := NewLoader(contract) - - status, err := loader.GetGameStatus(ctx) + status, err := loader.GetStatus(ctx) if err != nil { return nil, fmt.Errorf("failed to fetch game status: %w", err) } @@ -72,7 +71,7 @@ func NewGamePlayer( }, nil } - gameDepth, err := loader.FetchGameDepth(ctx) + gameDepth, err := loader.GetMaxGameDepth(ctx) if err != nil { return nil, fmt.Errorf("failed to fetch the game depth: %w", err) } @@ -114,7 +113,7 @@ func (g *GamePlayer) ProgressGame(ctx context.Context) gameTypes.GameStatus { if err := g.act(ctx); err != nil { g.logger.Error("Error when acting on game", "err", err) } - status, err := g.loader.GetGameStatus(ctx) + status, err := g.loader.GetStatus(ctx) if err != nil { g.logger.Warn("Unable to retrieve game status", "err", err) return gameTypes.GameStatusInProgress @@ -148,7 +147,7 @@ func (g *GamePlayer) logGameStatus(ctx context.Context, status gameTypes.GameSta } type PrestateLoader interface { - FetchAbsolutePrestateHash(ctx context.Context) (common.Hash, error) + GetAbsolutePrestateHash(ctx context.Context) (common.Hash, error) } // ValidateAbsolutePrestate validates the absolute prestate of the fault game. @@ -157,7 +156,7 @@ func ValidateAbsolutePrestate(ctx context.Context, trace types.TraceProvider, lo if err != nil { return fmt.Errorf("failed to get the trace provider's absolute prestate: %w", err) } - onchainPrestate, err := loader.FetchAbsolutePrestateHash(ctx) + onchainPrestate, err := loader.GetAbsolutePrestateHash(ctx) if err != nil { return fmt.Errorf("failed to get the onchain absolute prestate: %w", err) } diff --git a/op-challenger/game/fault/player_test.go b/op-challenger/game/fault/player_test.go index 3ed906c94f62..7375e2146d8a 100644 --- a/op-challenger/game/fault/player_test.go +++ b/op-challenger/game/fault/player_test.go @@ -181,7 +181,7 @@ func (s *stubGameState) Act(ctx context.Context) error { return s.actErr } -func (s *stubGameState) GetGameStatus(ctx context.Context) (gameTypes.GameStatus, error) { +func (s *stubGameState) GetStatus(ctx context.Context) (gameTypes.GameStatus, error) { return s.status, nil } @@ -234,7 +234,7 @@ func newMockPrestateLoader(prestateError bool, prestate common.Hash) *mockLoader prestate: prestate, } } -func (m *mockLoader) FetchAbsolutePrestateHash(ctx context.Context) (common.Hash, error) { +func (m *mockLoader) GetAbsolutePrestateHash(ctx context.Context) (common.Hash, error) { if m.prestateError { return common.Hash{}, mockLoaderError } diff --git a/op-challenger/game/fault/register.go b/op-challenger/game/fault/register.go index 26816907695e..54748bc99797 100644 --- a/op-challenger/game/fault/register.go +++ b/op-challenger/game/fault/register.go @@ -12,8 +12,8 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-service/txmgr" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" ) @@ -33,7 +33,7 @@ func RegisterGameTypes( m metrics.Metricer, cfg *config.Config, txMgr txmgr.TxManager, - client bind.ContractCaller, + client *ethclient.Client, ) { if cfg.TraceTypeEnabled(config.TraceTypeCannon) { resourceCreator := func(addr common.Address, gameDepth uint64, dir string) (faultTypes.TraceProvider, faultTypes.OracleUpdater, error) { diff --git a/op-challenger/game/fault/trace/alphabet/provider.go b/op-challenger/game/fault/trace/alphabet/provider.go index 929764250736..ac64a6da6639 100644 --- a/op-challenger/game/fault/trace/alphabet/provider.go +++ b/op-challenger/game/fault/trace/alphabet/provider.go @@ -14,6 +14,7 @@ import ( var ( ErrIndexTooLarge = errors.New("index is larger than the maximum index") + absolutePrestate = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000060") ) // AlphabetTraceProvider is a [TraceProvider] that provides claims for specific @@ -36,11 +37,7 @@ func NewTraceProvider(state string, depth uint64) *AlphabetTraceProvider { func (ap *AlphabetTraceProvider) GetStepData(ctx context.Context, i types.Position) ([]byte, []byte, *types.PreimageOracleData, error) { traceIndex := i.TraceIndex(int(ap.depth)) if traceIndex.Cmp(common.Big0) == 0 { - prestate, err := ap.AbsolutePreState(ctx) - if err != nil { - return nil, nil, nil, err - } - return prestate, []byte{}, nil, nil + return absolutePrestate, []byte{}, nil, nil } // We want the pre-state which is the value prior to the one requested traceIndex = traceIndex.Sub(traceIndex, big.NewInt(1)) @@ -67,17 +64,8 @@ func (ap *AlphabetTraceProvider) Get(ctx context.Context, i types.Position) (com return alphabetStateHash(claimBytes), nil } -// AbsolutePreState returns the absolute pre-state for the alphabet trace. -func (ap *AlphabetTraceProvider) AbsolutePreState(ctx context.Context) ([]byte, error) { - return common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000060"), nil -} - -func (ap *AlphabetTraceProvider) AbsolutePreStateCommitment(ctx context.Context) (common.Hash, error) { - prestate, err := ap.AbsolutePreState(ctx) - if err != nil { - return common.Hash{}, err - } - hash := common.BytesToHash(crypto.Keccak256(prestate)) +func (ap *AlphabetTraceProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { + hash := common.BytesToHash(crypto.Keccak256(absolutePrestate)) hash[0] = mipsevm.VMStatusUnfinished return hash, nil } diff --git a/op-challenger/game/fault/trace/cannon/provider.go b/op-challenger/game/fault/trace/cannon/provider.go index 1a2832baf020..c2c7e9c4b0a6 100644 --- a/op-challenger/game/fault/trace/cannon/provider.go +++ b/op-challenger/game/fault/trace/cannon/provider.go @@ -129,7 +129,7 @@ func (p *CannonTraceProvider) GetStepData(ctx context.Context, pos types.Positio return value, data, oracleData, nil } -func (p *CannonTraceProvider) AbsolutePreState(ctx context.Context) ([]byte, error) { +func (p *CannonTraceProvider) absolutePreState() ([]byte, error) { state, err := parseState(p.prestate) if err != nil { return nil, fmt.Errorf("cannot load absolute pre-state: %w", err) @@ -137,8 +137,8 @@ func (p *CannonTraceProvider) AbsolutePreState(ctx context.Context) ([]byte, err return state.EncodeWitness(), nil } -func (p *CannonTraceProvider) AbsolutePreStateCommitment(ctx context.Context) (common.Hash, error) { - state, err := p.AbsolutePreState(ctx) +func (p *CannonTraceProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { + state, err := p.absolutePreState() if err != nil { return common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err) } diff --git a/op-challenger/game/fault/trace/cannon/provider_test.go b/op-challenger/game/fault/trace/cannon/provider_test.go index 30f926bf0ca3..fdf969345e29 100644 --- a/op-challenger/game/fault/trace/cannon/provider_test.go +++ b/op-challenger/game/fault/trace/cannon/provider_test.go @@ -216,28 +216,28 @@ func TestGetStepData(t *testing.T) { }) } -func TestAbsolutePreState(t *testing.T) { +func TestAbsolutePreStateCommitment(t *testing.T) { dataDir := t.TempDir() prestate := "state.json" t.Run("StateUnavailable", func(t *testing.T) { provider, _ := setupWithTestData(t, "/dir/does/not/exist", prestate) - _, err := provider.AbsolutePreState(context.Background()) + _, err := provider.AbsolutePreStateCommitment(context.Background()) require.ErrorIs(t, err, os.ErrNotExist) }) t.Run("InvalidStateFile", func(t *testing.T) { setupPreState(t, dataDir, "invalid.json") provider, _ := setupWithTestData(t, dataDir, prestate) - _, err := provider.AbsolutePreState(context.Background()) + _, err := provider.AbsolutePreStateCommitment(context.Background()) require.ErrorContains(t, err, "invalid mipsevm state") }) t.Run("ExpectedAbsolutePreState", func(t *testing.T) { setupPreState(t, dataDir, "state.json") provider, _ := setupWithTestData(t, dataDir, prestate) - preState, err := provider.AbsolutePreState(context.Background()) + actual, err := provider.AbsolutePreStateCommitment(context.Background()) require.NoError(t, err) state := mipsevm.State{ Memory: mipsevm.NewMemory(), @@ -253,7 +253,9 @@ func TestAbsolutePreState(t *testing.T) { Step: 0, Registers: [32]uint32{}, } - require.Equal(t, []byte(state.EncodeWitness()), preState) + expected, err := state.EncodeWitness().StateHash() + require.NoError(t, err) + require.Equal(t, expected, actual) }) } diff --git a/op-challenger/game/fault/trace/split/provider.go b/op-challenger/game/fault/trace/split/provider.go index 6d61c8ab9a13..eb77f198116c 100644 --- a/op-challenger/game/fault/trace/split/provider.go +++ b/op-challenger/game/fault/trace/split/provider.go @@ -56,11 +56,6 @@ func (s *SplitTraceProvider) AbsolutePreStateCommitment(ctx context.Context) (ha return s.bottomProvider.AbsolutePreStateCommitment(ctx) } -// AbsolutePreState routes the AbsolutePreState request to the lowest internal [types.TraceProvider]. -func (s *SplitTraceProvider) AbsolutePreState(ctx context.Context) (preimage []byte, err error) { - return s.bottomProvider.AbsolutePreState(ctx) -} - // GetStepData routes the GetStepData request to the lowest internal [types.TraceProvider]. func (s *SplitTraceProvider) GetStepData(ctx context.Context, pos types.Position) (prestate []byte, proofData []byte, preimageData *types.PreimageOracleData, err error) { ancestorDepth, provider := s.providerForDepth(uint64(pos.Depth())) diff --git a/op-challenger/game/fault/trace/split/provider_test.go b/op-challenger/game/fault/trace/split/provider_test.go index 2845bfc66cb4..b63ab6d93349 100644 --- a/op-challenger/game/fault/trace/split/provider_test.go +++ b/op-challenger/game/fault/trace/split/provider_test.go @@ -64,24 +64,6 @@ func TestAbsolutePreStateCommitment(t *testing.T) { }) } -func TestAbsolutePreState(t *testing.T) { - t.Run("ErrorBubblesUp", func(t *testing.T) { - mockOutputProvider := mockTraceProvider{absolutePreStateError: mockGetError} - splitProvider := newSplitTraceProvider(t, nil, &mockOutputProvider, 40) - _, err := splitProvider.AbsolutePreState(context.Background()) - require.ErrorIs(t, err, mockGetError) - }) - - t.Run("ReturnsCorrectPreimageData", func(t *testing.T) { - expectedPreimage := []byte{1, 2, 3, 4} - mockOutputProvider := mockTraceProvider{preImageData: expectedPreimage} - splitProvider := newSplitTraceProvider(t, nil, &mockOutputProvider, 40) - output, err := splitProvider.AbsolutePreState(context.Background()) - require.NoError(t, err) - require.Equal(t, expectedPreimage, output) - }) -} - func TestGetStepData(t *testing.T) { t.Run("ErrorBubblesUp", func(t *testing.T) { mockOutputProvider := mockTraceProvider{getStepDataError: mockGetError} diff --git a/op-challenger/game/fault/types/types.go b/op-challenger/game/fault/types/types.go index 68497a377e66..12eb5c416300 100644 --- a/op-challenger/game/fault/types/types.go +++ b/op-challenger/game/fault/types/types.go @@ -69,9 +69,6 @@ type TraceProvider interface { // The prestate returned from GetStepData for trace 10 should be the pre-image of the claim from trace 9 GetStepData(ctx context.Context, i Position) (prestate []byte, proofData []byte, preimageData *PreimageOracleData, err error) - // AbsolutePreState is the pre-image value of the trace that transitions to the trace value at index 0 - AbsolutePreState(ctx context.Context) (preimage []byte, err error) - // AbsolutePreStateCommitment is the commitment of the pre-image value of the trace that transitions to the trace value at index 0 AbsolutePreStateCommitment(ctx context.Context) (hash common.Hash, err error) } diff --git a/op-challenger/game/loader/game_loader.go b/op-challenger/game/loader/game_loader.go index d5afee62ebc0..12b126cfc054 100644 --- a/op-challenger/game/loader/game_loader.go +++ b/op-challenger/game/loader/game_loader.go @@ -4,11 +4,8 @@ import ( "context" "errors" "fmt" - "math/big" "github.com/ethereum-optimism/optimism/op-challenger/game/types" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" ) var ( @@ -18,12 +15,8 @@ var ( // MinimalDisputeGameFactoryCaller is a minimal interface around [bindings.DisputeGameFactoryCaller]. // This needs to be updated if the [bindings.DisputeGameFactoryCaller] interface changes. type MinimalDisputeGameFactoryCaller interface { - GameCount(opts *bind.CallOpts) (*big.Int, error) - GameAtIndex(opts *bind.CallOpts, _index *big.Int) (struct { - GameType uint8 - Timestamp uint64 - Proxy common.Address - }, error) + GetGameCount(ctx context.Context, blockNum uint64) (uint64, error) + GetGame(ctx context.Context, idx uint64, blockNum uint64) (types.GameMetadata, error) } type GameLoader struct { @@ -38,27 +31,17 @@ func NewGameLoader(caller MinimalDisputeGameFactoryCaller) *GameLoader { } // FetchAllGamesAtBlock fetches all dispute games from the factory at a given block number. -func (l *GameLoader) FetchAllGamesAtBlock(ctx context.Context, earliestTimestamp uint64, blockNumber *big.Int) ([]types.GameMetadata, error) { - if blockNumber == nil { - return nil, ErrMissingBlockNumber - } - callOpts := &bind.CallOpts{ - Context: ctx, - BlockNumber: blockNumber, - } - gameCount, err := l.caller.GameCount(callOpts) +func (l *GameLoader) FetchAllGamesAtBlock(ctx context.Context, earliestTimestamp uint64, blockNumber uint64) ([]types.GameMetadata, error) { + gameCount, err := l.caller.GetGameCount(ctx, blockNumber) if err != nil { return nil, fmt.Errorf("failed to fetch game count: %w", err) } - games := make([]types.GameMetadata, 0) - if gameCount.Uint64() == 0 { - return games, nil - } - for i := gameCount.Uint64(); i > 0; i-- { - game, err := l.caller.GameAtIndex(callOpts, big.NewInt(int64(i-1))) + games := make([]types.GameMetadata, 0, gameCount) + for i := gameCount; i > 0; i-- { + game, err := l.caller.GetGame(ctx, i-1, blockNumber) if err != nil { - return nil, fmt.Errorf("failed to fetch game at index %d: %w", i, err) + return nil, fmt.Errorf("failed to fetch game at index %d: %w", i-1, err) } if game.Timestamp < earliestTimestamp { break diff --git a/op-challenger/game/loader/game_loader_test.go b/op-challenger/game/loader/game_loader_test.go index 1c6959be3b85..ac25d0b0cf9c 100644 --- a/op-challenger/game/loader/game_loader_test.go +++ b/op-challenger/game/loader/game_loader_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-challenger/game/types" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ) @@ -25,44 +24,39 @@ func TestGameLoader_FetchAllGames(t *testing.T) { name string caller *mockMinimalDisputeGameFactoryCaller earliest uint64 - blockNumber *big.Int + blockNumber uint64 expectedErr error expectedLen int }{ { name: "success", caller: newMockMinimalDisputeGameFactoryCaller(10, false, false), - blockNumber: big.NewInt(1), + blockNumber: 1, expectedLen: 10, }, { name: "expired game ignored", caller: newMockMinimalDisputeGameFactoryCaller(10, false, false), earliest: 500, - blockNumber: big.NewInt(1), + blockNumber: 1, expectedLen: 5, }, { name: "game count error", caller: newMockMinimalDisputeGameFactoryCaller(10, true, false), - blockNumber: big.NewInt(1), + blockNumber: 1, expectedErr: gameCountErr, }, { name: "game index error", caller: newMockMinimalDisputeGameFactoryCaller(10, false, true), - blockNumber: big.NewInt(1), + blockNumber: 1, expectedErr: gameIndexErr, }, { name: "no games", caller: newMockMinimalDisputeGameFactoryCaller(0, false, false), - blockNumber: big.NewInt(1), - }, - { - name: "missing block number", - caller: newMockMinimalDisputeGameFactoryCaller(0, false, false), - expectedErr: ErrMissingBlockNumber, + blockNumber: 1, }, } @@ -144,20 +138,15 @@ func newMockMinimalDisputeGameFactoryCaller(count uint64, gameCountErr bool, ind } } -func (m *mockMinimalDisputeGameFactoryCaller) GameCount(opts *bind.CallOpts) (*big.Int, error) { +func (m *mockMinimalDisputeGameFactoryCaller) GetGameCount(_ context.Context, blockNum uint64) (uint64, error) { if m.gameCountErr { - return nil, gameCountErr + return 0, gameCountErr } - return big.NewInt(int64(m.gameCount)), nil + return m.gameCount, nil } -func (m *mockMinimalDisputeGameFactoryCaller) GameAtIndex(opts *bind.CallOpts, _index *big.Int) (struct { - GameType uint8 - Timestamp uint64 - Proxy common.Address -}, error) { - index := _index.Uint64() +func (m *mockMinimalDisputeGameFactoryCaller) GetGame(_ context.Context, index uint64, blockNum uint64) (types.GameMetadata, error) { if m.indexErrors[index] { return struct { GameType uint8 @@ -166,13 +155,5 @@ func (m *mockMinimalDisputeGameFactoryCaller) GameAtIndex(opts *bind.CallOpts, _ }{}, gameIndexErr } - return struct { - GameType uint8 - Timestamp uint64 - Proxy common.Address - }{ - GameType: m.games[index].GameType, - Timestamp: m.games[index].Timestamp, - Proxy: m.games[index].Proxy, - }, nil + return m.games[index], nil } diff --git a/op-challenger/game/monitor.go b/op-challenger/game/monitor.go index a8c9c694b20c..e217bf040ff8 100644 --- a/op-challenger/game/monitor.go +++ b/op-challenger/game/monitor.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "math/big" "time" "github.com/ethereum-optimism/optimism/op-challenger/game/scheduler" @@ -23,7 +22,7 @@ type blockNumberFetcher func(ctx context.Context) (uint64, error) // gameSource loads information about the games available to play type gameSource interface { - FetchAllGamesAtBlock(ctx context.Context, earliest uint64, blockNumber *big.Int) ([]types.GameMetadata, error) + FetchAllGamesAtBlock(ctx context.Context, earliest uint64, blockNumber uint64) ([]types.GameMetadata, error) } type gameScheduler interface { @@ -101,7 +100,7 @@ func (m *gameMonitor) minGameTimestamp() uint64 { } func (m *gameMonitor) progressGames(ctx context.Context, blockNum uint64) error { - games, err := m.source.FetchAllGamesAtBlock(ctx, m.minGameTimestamp(), new(big.Int).SetUint64(blockNum)) + games, err := m.source.FetchAllGamesAtBlock(ctx, m.minGameTimestamp(), blockNum) if err != nil { return fmt.Errorf("failed to load games: %w", err) } diff --git a/op-challenger/game/monitor_test.go b/op-challenger/game/monitor_test.go index 7295fdb74a3d..e800bd64e8ac 100644 --- a/op-challenger/game/monitor_test.go +++ b/op-challenger/game/monitor_test.go @@ -230,7 +230,7 @@ type stubGameSource struct { func (s *stubGameSource) FetchAllGamesAtBlock( ctx context.Context, earliest uint64, - blockNumber *big.Int, + blockNumber uint64, ) ([]types.GameMetadata, error) { return s.games, nil } diff --git a/op-challenger/game/service.go b/op-challenger/game/service.go index 20c155d28e69..7c43447dd87b 100644 --- a/op-challenger/game/service.go +++ b/op-challenger/game/service.go @@ -5,9 +5,9 @@ import ( "errors" "fmt" - "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/game/fault" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" "github.com/ethereum-optimism/optimism/op-challenger/game/loader" "github.com/ethereum-optimism/optimism/op-challenger/game/registry" "github.com/ethereum-optimism/optimism/op-challenger/game/scheduler" @@ -18,6 +18,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/dial" "github.com/ethereum-optimism/optimism/op-service/httputil" oppprof "github.com/ethereum-optimism/optimism/op-service/pprof" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/log" ) @@ -88,7 +89,7 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Se m.StartBalanceMetrics(ctx, logger, l1Client, txMgr.From()) } - factoryContract, err := bindings.NewDisputeGameFactory(cfg.GameFactoryAddress, l1Client) + factoryContract, err := contracts.NewDisputeGameFactoryContract(cfg.GameFactoryAddress, batching.NewMultiCaller(l1Client.Client(), batching.DefaultBatchSize)) if err != nil { return nil, errors.Join(fmt.Errorf("failed to bind the fault dispute game factory contract: %w", err), s.Stop(ctx)) } diff --git a/op-e2e/Makefile b/op-e2e/Makefile index 5f92b5e458c0..8f53508e9ffd 100644 --- a/op-e2e/Makefile +++ b/op-e2e/Makefile @@ -21,7 +21,11 @@ test-ws: pre-test test-http: pre-test OP_E2E_USE_HTTP=true $(go_test) $(go_test_flags) ./... -.PHONY: test-ws +.PHONY: test-http + +test-span-batch: pre-test + OP_E2E_USE_SPAN_BATCH=true $(go_test) $(go_test_flags) ./... +.PHONY: test-span-batch cannon-prestate: make -C .. cannon-prestate diff --git a/op-e2e/actions/garbage_channel_out.go b/op-e2e/actions/garbage_channel_out.go index d412f80d5566..34056abdf714 100644 --- a/op-e2e/actions/garbage_channel_out.go +++ b/op-e2e/actions/garbage_channel_out.go @@ -255,13 +255,13 @@ func blockToBatch(block *types.Block) (*derive.BatchData, error) { return nil, fmt.Errorf("could not parse the L1 Info deposit: %w", err) } - return &derive.BatchData{ - SingularBatch: derive.SingularBatch{ - ParentHash: block.ParentHash(), - EpochNum: rollup.Epoch(l1Info.Number), - EpochHash: l1Info.BlockHash, - Timestamp: block.Time(), - Transactions: opaqueTxs, - }, - }, nil + singularBatch := &derive.SingularBatch{ + ParentHash: block.ParentHash(), + EpochNum: rollup.Epoch(l1Info.Number), + EpochHash: l1Info.BlockHash, + Timestamp: block.Time(), + Transactions: opaqueTxs, + } + + return derive.NewBatchData(singularBatch), nil } diff --git a/op-e2e/actions/l2_batcher.go b/op-e2e/actions/l2_batcher.go index 7431e7985bda..4ed14c139383 100644 --- a/op-e2e/actions/l2_batcher.go +++ b/op-e2e/actions/l2_batcher.go @@ -46,6 +46,10 @@ type BatcherCfg struct { GarbageCfg *GarbageChannelCfg } +type L2BlockRefs interface { + L2BlockRefByHash(ctx context.Context, hash common.Hash) (eth.L2BlockRef, error) +} + // L2Batcher buffers and submits L2 batches to L1. // // TODO: note the batcher shares little logic/state with actual op-batcher, @@ -59,24 +63,26 @@ type L2Batcher struct { syncStatusAPI SyncStatusAPI l2 BlocksAPI l1 L1TxAPI + engCl L2BlockRefs l1Signer types.Signer l2ChannelOut ChannelOutIface l2Submitting bool // when the channel out is being submitted, and not safe to write to without resetting - l2BufferedBlock eth.BlockID - l2SubmittedBlock eth.BlockID + l2BufferedBlock eth.L2BlockRef + l2SubmittedBlock eth.L2BlockRef l2BatcherCfg *BatcherCfg batcherAddr common.Address } -func NewL2Batcher(log log.Logger, rollupCfg *rollup.Config, batcherCfg *BatcherCfg, api SyncStatusAPI, l1 L1TxAPI, l2 BlocksAPI) *L2Batcher { +func NewL2Batcher(log log.Logger, rollupCfg *rollup.Config, batcherCfg *BatcherCfg, api SyncStatusAPI, l1 L1TxAPI, l2 BlocksAPI, engCl L2BlockRefs) *L2Batcher { return &L2Batcher{ log: log, rollupCfg: rollupCfg, syncStatusAPI: api, l1: l1, l2: l2, + engCl: engCl, l2BatcherCfg: batcherCfg, l1Signer: types.LatestSignerForChainID(rollupCfg.L1ChainID), batcherAddr: crypto.PubkeyToAddress(batcherCfg.BatcherKey.PublicKey), @@ -103,31 +109,39 @@ func (s *L2Batcher) Buffer(t Testing) error { syncStatus, err := s.syncStatusAPI.SyncStatus(t.Ctx()) require.NoError(t, err, "no sync status error") // If we just started, start at safe-head - if s.l2SubmittedBlock == (eth.BlockID{}) { + if s.l2SubmittedBlock == (eth.L2BlockRef{}) { s.log.Info("Starting batch-submitter work at safe-head", "safe", syncStatus.SafeL2) - s.l2SubmittedBlock = syncStatus.SafeL2.ID() - s.l2BufferedBlock = syncStatus.SafeL2.ID() + s.l2SubmittedBlock = syncStatus.SafeL2 + s.l2BufferedBlock = syncStatus.SafeL2 s.l2ChannelOut = nil } // If it's lagging behind, catch it up. if s.l2SubmittedBlock.Number < syncStatus.SafeL2.Number { s.log.Warn("last submitted block lagged behind L2 safe head: batch submission will continue from the safe head now", "last", s.l2SubmittedBlock, "safe", syncStatus.SafeL2) - s.l2SubmittedBlock = syncStatus.SafeL2.ID() - s.l2BufferedBlock = syncStatus.SafeL2.ID() + s.l2SubmittedBlock = syncStatus.SafeL2 + s.l2BufferedBlock = syncStatus.SafeL2 s.l2ChannelOut = nil } // Add the next unsafe block to the channel if s.l2BufferedBlock.Number >= syncStatus.UnsafeL2.Number { if s.l2BufferedBlock.Number > syncStatus.UnsafeL2.Number || s.l2BufferedBlock.Hash != syncStatus.UnsafeL2.Hash { s.log.Error("detected a reorg in L2 chain vs previous buffered information, resetting to safe head now", "safe_head", syncStatus.SafeL2) - s.l2SubmittedBlock = syncStatus.SafeL2.ID() - s.l2BufferedBlock = syncStatus.SafeL2.ID() + s.l2SubmittedBlock = syncStatus.SafeL2 + s.l2BufferedBlock = syncStatus.SafeL2 s.l2ChannelOut = nil } else { s.log.Info("nothing left to submit") return nil } } + block, err := s.l2.BlockByNumber(t.Ctx(), big.NewInt(int64(s.l2BufferedBlock.Number+1))) + require.NoError(t, err, "need l2 block %d from sync status", s.l2SubmittedBlock.Number+1) + if block.ParentHash() != s.l2BufferedBlock.Hash { + s.log.Error("detected a reorg in L2 chain vs previous submitted information, resetting to safe head now", "safe_head", syncStatus.SafeL2) + s.l2SubmittedBlock = syncStatus.SafeL2 + s.l2BufferedBlock = syncStatus.SafeL2 + s.l2ChannelOut = nil + } // Create channel if we don't have one yet if s.l2ChannelOut == nil { var ch ChannelOutIface @@ -140,23 +154,24 @@ func (s *L2Batcher) Buffer(t Testing) error { ApproxComprRatio: 1, }) require.NoError(t, e, "failed to create compressor") - ch, err = derive.NewChannelOut(derive.SingularBatchType, c, nil) + + var batchType uint = derive.SingularBatchType + var spanBatchBuilder *derive.SpanBatchBuilder = nil + if s.rollupCfg.IsSpanBatch(block.Time()) { + batchType = derive.SpanBatchType + spanBatchBuilder = derive.NewSpanBatchBuilder(s.rollupCfg.Genesis.L2Time, s.rollupCfg.L2ChainID) + } + ch, err = derive.NewChannelOut(batchType, c, spanBatchBuilder) } require.NoError(t, err, "failed to create channel") s.l2ChannelOut = ch } - block, err := s.l2.BlockByNumber(t.Ctx(), big.NewInt(int64(s.l2BufferedBlock.Number+1))) - require.NoError(t, err, "need l2 block %d from sync status", s.l2SubmittedBlock.Number+1) - if block.ParentHash() != s.l2BufferedBlock.Hash { - s.log.Error("detected a reorg in L2 chain vs previous submitted information, resetting to safe head now", "safe_head", syncStatus.SafeL2) - s.l2SubmittedBlock = syncStatus.SafeL2.ID() - s.l2BufferedBlock = syncStatus.SafeL2.ID() - s.l2ChannelOut = nil - } if _, err := s.l2ChannelOut.AddBlock(block); err != nil { // should always succeed return err } - s.l2BufferedBlock = eth.ToBlockID(block) + ref, err := s.engCl.L2BlockRefByHash(t.Ctx(), block.Hash()) + require.NoError(t, err, "failed to get L2BlockRef") + s.l2BufferedBlock = ref return nil } diff --git a/op-e2e/actions/l2_batcher_test.go b/op-e2e/actions/l2_batcher_test.go index aa986dcd80cc..bc467f0f7b1d 100644 --- a/op-e2e/actions/l2_batcher_test.go +++ b/op-e2e/actions/l2_batcher_test.go @@ -39,7 +39,7 @@ func TestBatcher(gt *testing.T) { MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient()) + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) // Alice makes a L2 tx cl := seqEngine.EthClient() @@ -137,7 +137,7 @@ func TestL2Finalization(gt *testing.T) { MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient()) + }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) heightToSubmit := sequencer.SyncStatus().UnsafeL2.Number @@ -223,7 +223,7 @@ func TestL2FinalizationWithSparseL1(gt *testing.T) { MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient()) + }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) batcher.ActSubmitAll(t) // include in L1 @@ -287,7 +287,7 @@ func TestGarbageBatch(gt *testing.T) { } } - batcher := NewL2Batcher(log, sd.RollupCfg, batcherCfg, sequencer.RollupClient(), miner.EthClient(), engine.EthClient()) + batcher := NewL2Batcher(log, sd.RollupCfg, batcherCfg, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) @@ -359,7 +359,7 @@ func TestExtendedTimeWithoutL1Batches(gt *testing.T) { MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient()) + }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) @@ -417,7 +417,7 @@ func TestBigL2Txs(gt *testing.T) { MinL1TxSize: 0, MaxL1TxSize: 40_000, // try a small batch size, to force the data to be split between more frames BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient()) + }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) @@ -470,7 +470,7 @@ func TestBigL2Txs(gt *testing.T) { sequencer.ActL2EndBlock(t) for batcher.l2BufferedBlock.Number < sequencer.SyncStatus().UnsafeL2.Number { // if we run out of space, close the channel and submit all the txs - if err := batcher.Buffer(t); errors.Is(err, derive.ErrTooManyRLPBytes) { + if err := batcher.Buffer(t); errors.Is(err, derive.ErrTooManyRLPBytes) || errors.Is(err, derive.CompressorFullErr) { log.Info("flushing filled channel to batch txs", "id", batcher.l2ChannelOut.ID()) batcher.ActL2ChannelClose(t) for batcher.l2ChannelOut != nil { diff --git a/op-e2e/actions/l2_proposer_test.go b/op-e2e/actions/l2_proposer_test.go index 5e1f51a33db5..d16d610978ed 100644 --- a/op-e2e/actions/l2_proposer_test.go +++ b/op-e2e/actions/l2_proposer_test.go @@ -26,7 +26,7 @@ func TestProposer(gt *testing.T) { MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient()) + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) proposer := NewL2Proposer(t, log, &ProposerCfg{ OutputOracleAddr: sd.DeploymentsL1.L2OutputOracleProxy, diff --git a/op-e2e/actions/l2_verifier.go b/op-e2e/actions/l2_verifier.go index 1340210d197e..6419a68ce669 100644 --- a/op-e2e/actions/l2_verifier.go +++ b/op-e2e/actions/l2_verifier.go @@ -135,6 +135,10 @@ func (s *L2Verifier) L2Safe() eth.L2BlockRef { return s.derivation.SafeL2Head() } +func (s *L2Verifier) L2PendingSafe() eth.L2BlockRef { + return s.derivation.PendingSafeL2Head() +} + func (s *L2Verifier) L2Unsafe() eth.L2BlockRef { return s.derivation.UnsafeL2Head() } @@ -153,6 +157,7 @@ func (s *L2Verifier) SyncStatus() *eth.SyncStatus { UnsafeL2: s.L2Unsafe(), SafeL2: s.L2Safe(), FinalizedL2: s.L2Finalized(), + PendingSafeL2: s.L2PendingSafe(), UnsafeL2SyncTarget: s.derivation.UnsafeL2SyncTarget(), EngineSyncTarget: s.EngineSyncTarget(), } diff --git a/op-e2e/actions/reorg_test.go b/op-e2e/actions/reorg_test.go index bf8cf8a92ba5..a50dacc17f8e 100644 --- a/op-e2e/actions/reorg_test.go +++ b/op-e2e/actions/reorg_test.go @@ -40,7 +40,7 @@ func setupReorgTestActors(t Testing, dp *e2eutils.DeployParams, sd *e2eutils.Set MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient()) + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) return sd, dp, miner, sequencer, seqEngine, verifier, verifEngine, batcher } @@ -189,8 +189,16 @@ func TestReorgFlipFlop(gt *testing.T) { verifier.ActL2PipelineFull(t) require.Equal(t, sd.RollupCfg.Genesis.L1, verifier.L2Safe().L1Origin, "expected to be back at genesis origin after losing A0 and A1") - require.NotZero(t, verifier.L2Safe().Number, "still preserving old L2 blocks that did not reference reorged L1 chain (assuming more than one L2 block per L1 block)") - require.Equal(t, verifier.L2Safe(), verifier.L2Unsafe(), "head is at safe block after L1 reorg") + if sd.RollupCfg.SpanBatchTime == nil { + // before span batch hard fork + require.NotZero(t, verifier.L2Safe().Number, "still preserving old L2 blocks that did not reference reorged L1 chain (assuming more than one L2 block per L1 block)") + require.Equal(t, verifier.L2Safe(), verifier.L2Unsafe(), "head is at safe block after L1 reorg") + } else { + // after span batch hard fork + require.Zero(t, verifier.L2Safe().Number, "safe head is at genesis block because span batch referenced reorged L1 chain is not accepted") + require.Equal(t, verifier.L2Unsafe().ID(), sequencer.L2Unsafe().ParentID(), "head is at the highest unsafe block that references canonical L1 chain(genesis block)") + batcher.l2BufferedBlock = eth.L2BlockRef{} // must reset batcher to resubmit blocks included in the last batch + } checkVerifEngine() // and sync the sequencer, then build some new L2 blocks, up to and including with L1 origin B2 @@ -210,6 +218,7 @@ func TestReorgFlipFlop(gt *testing.T) { verifier.ActL1HeadSignal(t) verifier.ActL2PipelineFull(t) require.Equal(t, verifier.L2Safe().L1Origin, blockB2.ID(), "B2 is the L1 origin of verifier now") + require.Equal(t, verifier.L2Unsafe(), sequencer.L2Unsafe(), "verifier unsafe head is reorged along sequencer") checkVerifEngine() // Flop back to chain A! @@ -585,7 +594,7 @@ func TestRestartOpGeth(gt *testing.T) { MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient()) + }, sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) // start sequencer.ActL2PipelineFull(t) @@ -674,7 +683,7 @@ func TestConflictingL2Blocks(gt *testing.T) { MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, altSequencer.RollupClient(), miner.EthClient(), altSeqEng.EthClient()) + }, altSequencer.RollupClient(), miner.EthClient(), altSeqEng.EthClient(), altSeqEng.EngineClient(t, sd.RollupCfg)) // And set up user Alice, using the alternative sequencer endpoint l2Cl := altSeqEng.EthClient() @@ -762,3 +771,108 @@ func TestConflictingL2Blocks(gt *testing.T) { require.Equal(t, verifier.L2Unsafe(), altSequencer.L2Unsafe(), "alt-sequencer gets back in harmony with verifier by reorging out its conflicting data") require.Equal(t, sequencer.L2Unsafe(), altSequencer.L2Unsafe(), "and gets back in harmony with original sequencer") } + +func TestSyncAfterReorg(gt *testing.T) { + t := NewDefaultTesting(gt) + testingParams := e2eutils.TestParams{ + MaxSequencerDrift: 60, + SequencerWindowSize: 4, + ChannelTimeout: 2, + L1BlockTime: 12, + } + sd, dp, miner, sequencer, seqEngine, verifier, _, batcher := setupReorgTest(t, &testingParams) + l2Client := seqEngine.EthClient() + log := testlog.Logger(t, log.LvlDebug) + addresses := e2eutils.CollectAddresses(sd, dp) + l2UserEnv := &BasicUserEnv[*L2Bindings]{ + EthCl: l2Client, + Signer: types.LatestSigner(sd.L2Cfg.Config), + AddressCorpora: addresses, + Bindings: NewL2Bindings(t, l2Client, seqEngine.GethClient()), + } + alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) + alice.L2.SetUserEnv(l2UserEnv) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // build empty L1 block: A0 + miner.ActL1SetFeeRecipient(common.Address{'A', 0}) + miner.ActEmptyBlock(t) + sequencer.ActL1HeadSignal(t) + for sequencer.derivation.UnsafeL2Head().L1Origin.Number < sequencer.l1State.L1Head().Number { + // build L2 blocks until the L1 origin is the current L1 head(A0) + sequencer.ActL2PipelineFull(t) + sequencer.ActL2StartBlock(t) + if sequencer.derivation.UnsafeL2Head().Number == 11 { + // include a user tx at L2 block #12 to make a state transition + alice.L2.ActResetTxOpts(t) + alice.L2.ActSetTxToAddr(&dp.Addresses.Bob)(t) + alice.L2.ActMakeTx(t) + // Include the tx in the block we're making + seqEngine.ActL2IncludeTx(alice.Address())(t) + } + sequencer.ActL2EndBlock(t) + } + // submit all new L2 blocks: #1 ~ #12 + batcher.ActSubmitAll(t) + + // build an L1 block included batch TX: A1 + miner.ActL1SetFeeRecipient(common.Address{'A', 1}) + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) + miner.ActL1EndBlock(t) + + for i := 2; i < 6; i++ { + // build L2 blocks until the L1 origin is the current L1 head + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + // submt all new L2 blocks + batcher.ActSubmitAll(t) + + // build an L1 block included batch TX: A2 ~ A5 + miner.ActL1SetFeeRecipient(common.Address{'A', byte(i)}) + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) + miner.ActL1EndBlock(t) + } + + sequencer.ActL1HeadSignal(t) + sequencer.ActL2PipelineFull(t) + // capture current L2 safe head + submittedSafeHead := sequencer.L2Safe().ID() + + // build L2 blocks until the L1 origin is the current L1 head(A5) + sequencer.ActBuildToL1Head(t) + batcher.ActSubmitAll(t) + + // build an L1 block included batch TX: A6 + miner.ActL1SetFeeRecipient(common.Address{'A', 6}) + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) + miner.ActL1EndBlock(t) + + sequencer.ActL1HeadSignal(t) + sequencer.ActL2PipelineFull(t) + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + + // reorg L1 + miner.ActL1RewindToParent(t) // undo A6 + miner.ActL1SetFeeRecipient(common.Address{'B', 6}) // build B6 + miner.ActEmptyBlock(t) + miner.ActL1SetFeeRecipient(common.Address{'B', 7}) // build B7 + miner.ActEmptyBlock(t) + + // sequencer and verifier detect L1 reorg + // derivation pipeline is reset + // safe head may be reset to block #11 + sequencer.ActL1HeadSignal(t) + sequencer.ActL2PipelineFull(t) + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + + // sequencer and verifier must derive all submitted batches and reach to the captured block + require.Equal(t, sequencer.L2Safe().ID(), submittedSafeHead) + require.Equal(t, verifier.L2Safe().ID(), submittedSafeHead) +} diff --git a/op-e2e/actions/span_batch_test.go b/op-e2e/actions/span_batch_test.go new file mode 100644 index 000000000000..65b20cf04306 --- /dev/null +++ b/op-e2e/actions/span_batch_test.go @@ -0,0 +1,365 @@ +package actions + +import ( + "crypto/ecdsa" + crand "crypto/rand" + "fmt" + "math/big" + "math/rand" + "testing" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" +) + +// TestDropSpanBatchBeforeHardfork tests behavior of op-node before SpanBatch hardfork. +// op-node must drop SpanBatch before SpanBatch hardfork. +func TestDropSpanBatchBeforeHardfork(gt *testing.T) { + t := NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) + SequencerWindowSize: 24, + ChannelTimeout: 20, + L1BlockTime: 12, + } + dp := e2eutils.MakeDeployParams(t, p) + // do not activate SpanBatch hardfork for verifier + dp.DeployConfig.L2GenesisSpanBatchTimeOffset = nil + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlError) + miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) + verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + + rollupSeqCl := sequencer.RollupClient() + dp2 := e2eutils.MakeDeployParams(t, p) + minTs := hexutil.Uint64(0) + // activate SpanBatch hardfork for batcher. so batcher will submit SpanBatches to L1. + dp2.DeployConfig.L2GenesisSpanBatchTimeOffset = &minTs + sd2 := e2eutils.Setup(t, dp2, defaultAlloc) + batcher := NewL2Batcher(log, sd2.RollupCfg, &BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + + // Alice makes a L2 tx + cl := seqEngine.EthClient() + n, err := cl.PendingNonceAt(t.Ctx(), dp.Addresses.Alice) + require.NoError(t, err) + signer := types.LatestSigner(sd.L2Cfg.Config) + tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + 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)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), + }) + require.NoError(gt, cl.SendTransaction(t.Ctx(), tx)) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // Make L2 block + sequencer.ActL2StartBlock(t) + seqEngine.ActL2IncludeTx(dp.Addresses.Alice)(t) + sequencer.ActL2EndBlock(t) + + // batch submit to L1. batcher should submit span batches. + batcher.ActL2BatchBuffer(t) + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) + + // confirm batch on L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + bl := miner.l1Chain.CurrentBlock() + log.Info("bl", "txs", len(miner.l1Chain.GetBlockByHash(bl.Hash()).Transactions())) + + // Now make enough L1 blocks that the verifier will have to derive a L2 block + // It will also eagerly derive the block from the batcher + for i := uint64(0); i < sd.RollupCfg.SeqWindowSize; i++ { + miner.ActL1StartBlock(12)(t) + miner.ActL1EndBlock(t) + } + + // try to sync verifier from L1 batch. but verifier should drop every span batch. + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + require.Equal(t, uint64(1), verifier.SyncStatus().SafeL2.L1Origin.Number) + + verifCl := verifEngine.EthClient() + for i := int64(1); i < int64(verifier.L2Safe().Number); i++ { + block, _ := verifCl.BlockByNumber(t.Ctx(), big.NewInt(i)) + require.NoError(t, err) + // because verifier drops every span batch, it should generate empty blocks. + // so every block has only L1 attribute deposit transaction. + require.Equal(t, block.Transactions().Len(), 1) + } + // check that the tx from alice is not included in verifier's chain + _, _, err = verifCl.TransactionByHash(t.Ctx(), tx.Hash()) + require.ErrorIs(t, err, ethereum.NotFound) +} + +// TestAcceptSingularBatchAfterHardfork tests behavior of op-node after SpanBatch hardfork. +// op-node must accept SingularBatch after SpanBatch hardfork. +func TestAcceptSingularBatchAfterHardfork(gt *testing.T) { + t := NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) + SequencerWindowSize: 24, + ChannelTimeout: 20, + L1BlockTime: 12, + } + minTs := hexutil.Uint64(0) + dp := e2eutils.MakeDeployParams(t, p) + + // activate SpanBatch hardfork for verifier. + dp.DeployConfig.L2GenesisSpanBatchTimeOffset = &minTs + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlError) + miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) + verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + + rollupSeqCl := sequencer.RollupClient() + dp2 := e2eutils.MakeDeployParams(t, p) + + // not activate SpanBatch hardfork for batcher + dp2.DeployConfig.L2GenesisSpanBatchTimeOffset = nil + sd2 := e2eutils.Setup(t, dp2, defaultAlloc) + batcher := NewL2Batcher(log, sd2.RollupCfg, &BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + + // Alice makes a L2 tx + cl := seqEngine.EthClient() + n, err := cl.PendingNonceAt(t.Ctx(), dp.Addresses.Alice) + require.NoError(t, err) + signer := types.LatestSigner(sd.L2Cfg.Config) + tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + 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)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), + }) + require.NoError(gt, cl.SendTransaction(t.Ctx(), tx)) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // Make L2 block + sequencer.ActL2StartBlock(t) + seqEngine.ActL2IncludeTx(dp.Addresses.Alice)(t) + sequencer.ActL2EndBlock(t) + + // batch submit to L1. batcher should submit singular batches. + batcher.ActL2BatchBuffer(t) + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) + + // confirm batch on L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + bl := miner.l1Chain.CurrentBlock() + log.Info("bl", "txs", len(miner.l1Chain.GetBlockByHash(bl.Hash()).Transactions())) + + // Now make enough L1 blocks that the verifier will have to derive a L2 block + // It will also eagerly derive the block from the batcher + for i := uint64(0); i < sd.RollupCfg.SeqWindowSize; i++ { + miner.ActL1StartBlock(12)(t) + miner.ActL1EndBlock(t) + } + + // sync verifier from L1 batch in otherwise empty sequence window + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + require.Equal(t, uint64(1), verifier.SyncStatus().SafeL2.L1Origin.Number) + + // check that the tx from alice made it into the L2 chain + verifCl := verifEngine.EthClient() + vTx, isPending, err := verifCl.TransactionByHash(t.Ctx(), tx.Hash()) + require.NoError(t, err) + require.False(t, isPending) + require.NotNil(t, vTx) +} + +// TestSpanBatchEmptyChain tests derivation of empty chain using SpanBatch. +func TestSpanBatchEmptyChain(gt *testing.T) { + t := NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, + SequencerWindowSize: 24, + ChannelTimeout: 20, + L1BlockTime: 12, + } + dp := e2eutils.MakeDeployParams(t, p) + minTs := hexutil.Uint64(0) + // Activate SpanBatch hardfork + dp.DeployConfig.L2GenesisSpanBatchTimeOffset = &minTs + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlError) + miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) + _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + + rollupSeqCl := sequencer.RollupClient() + batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + miner.ActEmptyBlock(t) + // Make 1200 empty L2 blocks (L1BlockTime / L2BlockTime * 100) + for i := 0; i < 100; i++ { + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + + if i%10 == 9 { + // batch submit to L1 + batcher.ActSubmitAll(t) + + // confirm batch on L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + } else { + miner.ActEmptyBlock(t) + } + } + sequencer.ActL1HeadSignal(t) + sequencer.ActL2PipelineFull(t) + + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + + require.Equal(t, sequencer.L2Unsafe(), sequencer.L2Safe()) + require.Equal(t, verifier.L2Unsafe(), verifier.L2Safe()) + require.Equal(t, sequencer.L2Safe(), verifier.L2Safe()) +} + +// TestSpanBatchLowThroughputChain tests derivation of low-throughput chain using SpanBatch. +func TestSpanBatchLowThroughputChain(gt *testing.T) { + t := NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, + SequencerWindowSize: 24, + ChannelTimeout: 20, + L1BlockTime: 12, + } + dp := e2eutils.MakeDeployParams(t, p) + minTs := hexutil.Uint64(0) + // Activate SpanBatch hardfork + dp.DeployConfig.L2GenesisSpanBatchTimeOffset = &minTs + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlError) + miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) + _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + + rollupSeqCl := sequencer.RollupClient() + batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + cl := seqEngine.EthClient() + + const numTestUsers = 5 + var privKeys [numTestUsers]*ecdsa.PrivateKey + var addrs [numTestUsers]common.Address + for i := 0; i < numTestUsers; i++ { + // Create a new test account + privateKey, err := dp.Secrets.Wallet.PrivateKey(accounts.Account{ + URL: accounts.URL{ + Path: fmt.Sprintf("m/44'/60'/0'/0/%d", 10+i), + }, + }) + privKeys[i] = privateKey + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + require.NoError(t, err) + addrs[i] = addr + } + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + miner.ActEmptyBlock(t) + totalTxCount := 0 + // Make 600 L2 blocks (L1BlockTime / L2BlockTime * 50) including 1~3 txs + for i := 0; i < 50; i++ { + sequencer.ActL1HeadSignal(t) + for sequencer.derivation.UnsafeL2Head().L1Origin.Number < sequencer.l1State.L1Head().Number { + sequencer.ActL2PipelineFull(t) + sequencer.ActL2StartBlock(t) + // fill the block with random number of L2 txs + for j := 0; j < rand.Intn(3); j++ { + userIdx := totalTxCount % numTestUsers + signer := types.LatestSigner(sd.L2Cfg.Config) + data := make([]byte, rand.Intn(100)) + _, err := crand.Read(data[:]) // fill with random bytes + require.NoError(t, err) + gas, err := core.IntrinsicGas(data, nil, false, true, true, false) + require.NoError(t, err) + baseFee := seqEngine.l2Chain.CurrentBlock().BaseFee + nonce, err := cl.PendingNonceAt(t.Ctx(), addrs[userIdx]) + require.NoError(t, err) + tx := types.MustSignNewTx(privKeys[userIdx], signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: nonce, + GasTipCap: big.NewInt(2 * params.GWei), + GasFeeCap: new(big.Int).Add(new(big.Int).Mul(baseFee, big.NewInt(2)), big.NewInt(2*params.GWei)), + Gas: gas, + To: &dp.Addresses.Bob, + Value: big.NewInt(0), + Data: data, + }) + require.NoError(gt, cl.SendTransaction(t.Ctx(), tx)) + seqEngine.ActL2IncludeTx(addrs[userIdx])(t) + totalTxCount += 1 + } + sequencer.ActL2EndBlock(t) + } + + if i%10 == 9 { + // batch submit to L1 + batcher.ActSubmitAll(t) + + // confirm batch on L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + } else { + miner.ActEmptyBlock(t) + } + } + sequencer.ActL1HeadSignal(t) + sequencer.ActL2PipelineFull(t) + + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + + require.Equal(t, sequencer.L2Unsafe(), sequencer.L2Safe()) + require.Equal(t, verifier.L2Unsafe(), verifier.L2Safe()) + require.Equal(t, sequencer.L2Safe(), verifier.L2Safe()) +} diff --git a/op-e2e/actions/sync_test.go b/op-e2e/actions/sync_test.go index 07321859579f..57f8564f7a98 100644 --- a/op-e2e/actions/sync_test.go +++ b/op-e2e/actions/sync_test.go @@ -2,15 +2,24 @@ package actions import ( "errors" + "math/big" "math/rand" "testing" + "github.com/ethereum-optimism/optimism/op-batcher/compressor" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/testutils" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/require" ) @@ -166,3 +175,232 @@ func TestEngineP2PSync(gt *testing.T) { require.Equal(t, sequencer.L2Unsafe().Hash, verifier.EngineSyncTarget().Hash) } } + +func TestInvalidPayloadInSpanBatch(gt *testing.T) { + t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate SpanBatch hardfork + dp.DeployConfig.L2GenesisSpanBatchTimeOffset = &minTs + dp.DeployConfig.L2BlockTime = 2 + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlInfo) + _, _, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + l2Cl := seqEng.EthClient() + rng := rand.New(rand.NewSource(1234)) + signer := types.LatestSigner(sd.L2Cfg.Config) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + c, e := compressor.NewRatioCompressor(compressor.Config{ + TargetFrameSize: 128_000, + TargetNumFrames: 1, + ApproxComprRatio: 1, + }) + require.NoError(t, e) + spanBatchBuilder := derive.NewSpanBatchBuilder(sd.RollupCfg.Genesis.L2Time, sd.RollupCfg.L2ChainID) + // Create new span batch channel + channelOut, err := derive.NewChannelOut(derive.SpanBatchType, c, spanBatchBuilder) + require.NoError(t, err) + + // Create block A1 ~ A12 for L1 block #0 ~ #2 + miner.ActEmptyBlock(t) + miner.ActEmptyBlock(t) + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1HeadUnsafe(t) + + for i := uint64(1); i <= sequencer.L2Unsafe().Number; i++ { + block, err := l2Cl.BlockByNumber(t.Ctx(), new(big.Int).SetUint64(i)) + require.NoError(t, err) + if i == 8 { + // Make block A8 as an invalid block + invalidTx := testutils.RandomTx(rng, big.NewInt(100), signer) + block = block.WithBody([]*types.Transaction{block.Transactions()[0], invalidTx}, []*types.Header{}) + } + // Add A1 ~ A12 into the channel + _, err = channelOut.AddBlock(block) + require.NoError(t, err) + } + + // Submit span batch(A1, ..., A7, invalid A8, A9, ..., A12) + batcher.l2ChannelOut = channelOut + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) + + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + miner.ActL1SafeNext(t) + miner.ActL1FinalizeNext(t) + + // After the verifier processed the span batch, only unsafe head should be advanced to A7. + // Safe head is not updated because the span batch is not fully processed. + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + require.Equal(t, verifier.L2Unsafe().Number, uint64(7)) + require.Equal(t, verifier.L2Safe().Number, uint64(0)) + + // Create new span batch channel + c, e = compressor.NewRatioCompressor(compressor.Config{ + TargetFrameSize: 128_000, + TargetNumFrames: 1, + ApproxComprRatio: 1, + }) + require.NoError(t, e) + spanBatchBuilder = derive.NewSpanBatchBuilder(sd.RollupCfg.Genesis.L2Time, sd.RollupCfg.L2ChainID) + channelOut, err = derive.NewChannelOut(derive.SpanBatchType, c, spanBatchBuilder) + require.NoError(t, err) + + for i := uint64(1); i <= sequencer.L2Unsafe().Number; i++ { + block, err := l2Cl.BlockByNumber(t.Ctx(), new(big.Int).SetUint64(i)) + require.NoError(t, err) + if i == 1 { + // Create valid TX + aliceNonce, err := seqEng.EthClient().PendingNonceAt(t.Ctx(), dp.Addresses.Alice) + require.NoError(t, err) + data := make([]byte, rand.Intn(100)) + gas, err := core.IntrinsicGas(data, nil, false, true, true, false) + require.NoError(t, err) + baseFee := seqEng.l2Chain.CurrentBlock().BaseFee + tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: aliceNonce, + GasTipCap: big.NewInt(2 * params.GWei), + GasFeeCap: new(big.Int).Add(new(big.Int).Mul(baseFee, big.NewInt(2)), big.NewInt(2*params.GWei)), + Gas: gas, + To: &dp.Addresses.Bob, + Value: big.NewInt(0), + Data: data, + }) + // Create valid new block B1 at the same height as A1 + block = block.WithBody([]*types.Transaction{block.Transactions()[0], tx}, []*types.Header{}) + } + // Add B1, A2 ~ A12 into the channel + _, err = channelOut.AddBlock(block) + require.NoError(t, err) + } + // Submit span batch(B1, A2, ... A12) + batcher.l2ChannelOut = channelOut + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) + + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + miner.ActL1SafeNext(t) + miner.ActL1FinalizeNext(t) + + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + + // verifier should advance its unsafe and safe head to the height of A12. + require.Equal(t, verifier.L2Unsafe().Number, uint64(12)) + require.Equal(t, verifier.L2Safe().Number, uint64(12)) +} + +func TestSpanBatchAtomicity_Consolidation(gt *testing.T) { + t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate SpanBatch hardfork + dp.DeployConfig.L2GenesisSpanBatchTimeOffset = &minTs + dp.DeployConfig.L2BlockTime = 2 + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlInfo) + _, _, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + + targetHeadNumber := uint64(6) // L1 block time / L2 block time + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // Create 6 blocks + miner.ActEmptyBlock(t) + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1HeadUnsafe(t) + require.Equal(t, sequencer.L2Unsafe().Number, targetHeadNumber) + + // Gossip unsafe blocks to the verifier + for i := uint64(1); i <= sequencer.L2Unsafe().Number; i++ { + seqHead, err := seqEngCl.PayloadByNumber(t.Ctx(), i) + require.NoError(t, err) + verifier.ActL2UnsafeGossipReceive(seqHead)(t) + } + verifier.ActL2PipelineFull(t) + + // Check if the verifier's unsafe sync is done + require.Equal(t, sequencer.L2Unsafe().Hash, verifier.L2Unsafe().Hash) + + // Build and submit a span batch with 6 blocks + batcher.ActSubmitAll(t) + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + + // Start verifier safe sync + verifier.ActL1HeadSignal(t) + verifier.l2PipelineIdle = false + for !verifier.l2PipelineIdle { + verifier.ActL2PipelineStep(t) + if verifier.L2PendingSafe().Number < targetHeadNumber { + // If the span batch is not fully processed, the safe head must not advance. + require.Equal(t, verifier.L2Safe().Number, uint64(0)) + } else { + // Once the span batch is fully processed, the safe head must advance to the end of span batch. + require.Equal(t, verifier.L2Safe().Number, targetHeadNumber) + require.Equal(t, verifier.L2Safe(), verifier.L2PendingSafe()) + } + // The unsafe head must not be changed + require.Equal(t, verifier.L2Unsafe(), sequencer.L2Unsafe()) + } +} + +func TestSpanBatchAtomicity_ForceAdvance(gt *testing.T) { + t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate SpanBatch hardfork + dp.DeployConfig.L2GenesisSpanBatchTimeOffset = &minTs + dp.DeployConfig.L2BlockTime = 2 + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlInfo) + _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + + targetHeadNumber := uint64(6) // L1 block time / L2 block time + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + require.Equal(t, verifier.L2Unsafe().Number, uint64(0)) + + // Create 6 blocks + miner.ActEmptyBlock(t) + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1HeadUnsafe(t) + require.Equal(t, sequencer.L2Unsafe().Number, targetHeadNumber) + + // Build and submit a span batch with 6 blocks + batcher.ActSubmitAll(t) + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + + // Start verifier safe sync + verifier.ActL1HeadSignal(t) + verifier.l2PipelineIdle = false + for !verifier.l2PipelineIdle { + verifier.ActL2PipelineStep(t) + if verifier.L2PendingSafe().Number < targetHeadNumber { + // If the span batch is not fully processed, the safe head must not advance. + require.Equal(t, verifier.L2Safe().Number, uint64(0)) + } else { + // Once the span batch is fully processed, the safe head must advance to the end of span batch. + require.Equal(t, verifier.L2Safe().Number, targetHeadNumber) + require.Equal(t, verifier.L2Safe(), verifier.L2PendingSafe()) + } + // The unsafe head and the pending safe head must be the same + require.Equal(t, verifier.L2Unsafe(), verifier.L2PendingSafe()) + } +} diff --git a/op-e2e/actions/system_config_test.go b/op-e2e/actions/system_config_test.go index 68fca336ad15..59cbc57729ba 100644 --- a/op-e2e/actions/system_config_test.go +++ b/op-e2e/actions/system_config_test.go @@ -39,14 +39,14 @@ func TestBatcherKeyRotation(gt *testing.T) { MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient()) + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) // a batcher with a new key batcherB := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Bob, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient()) + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) @@ -210,7 +210,7 @@ func TestGPOParamsChange(gt *testing.T) { MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient()) + }, sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) alice := NewBasicUser[any](log, dp.Secrets.Alice, rand.New(rand.NewSource(1234))) alice.SetUserEnv(&BasicUserEnv[any]{ @@ -339,7 +339,7 @@ func TestGasLimitChange(gt *testing.T) { MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient()) + }, sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) miner.ActEmptyBlock(t) diff --git a/op-e2e/actions/user_test.go b/op-e2e/actions/user_test.go index c63918cdaec1..5e0a88eb683c 100644 --- a/op-e2e/actions/user_test.go +++ b/op-e2e/actions/user_test.go @@ -60,7 +60,7 @@ func runCrossLayerUserTest(gt *testing.T, test regolithScheduledTest) { MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, - }, seq.RollupClient(), miner.EthClient(), seqEngine.EthClient()) + }, seq.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) proposer := NewL2Proposer(t, log, &ProposerCfg{ OutputOracleAddr: sd.DeploymentsL1.L2OutputOracleProxy, ProposerKey: dp.Secrets.Proposer, diff --git a/op-e2e/e2eutils/disputegame/game_helper.go b/op-e2e/e2eutils/disputegame/game_helper.go index 6ce31f2f9c76..5e8a1fcb1a00 100644 --- a/op-e2e/e2eutils/disputegame/game_helper.go +++ b/op-e2e/e2eutils/disputegame/game_helper.go @@ -8,7 +8,6 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-bindings/bindings" - "github.com/ethereum-optimism/optimism/op-challenger/game/fault" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -356,25 +355,6 @@ func (g *FaultGameHelper) ResolveClaim(ctx context.Context, claimIdx int64) { g.require.NoError(err, "ResolveClaim transaction was not OK") } -// ResolveAllClaims resolves all subgames -// This function does not resolve the game. That's the responsibility of challengers -func (g *FaultGameHelper) ResolveAllClaims(ctx context.Context) { - loader := fault.NewLoader(g.game) - claims, err := loader.FetchClaims(ctx) - g.require.NoError(err, "Failed to fetch claims") - subgames := make(map[int]bool) - for i := len(claims) - 1; i > 0; i-- { - subgames[claims[i].ParentContractIndex] = true - // Subgames containing only one node are implicitly resolved - // i.e. uncountered and claims at MAX_DEPTH - if !subgames[i] { - continue - } - g.ResolveClaim(ctx, int64(i)) - } - g.ResolveClaim(ctx, 0) -} - func (g *FaultGameHelper) gameData(ctx context.Context) string { opts := &bind.CallOpts{Context: ctx} maxDepth := int(g.MaxDepth(ctx)) diff --git a/op-e2e/e2eutils/wait/blocks.go b/op-e2e/e2eutils/wait/blocks.go index dd6ef178cd41..066b16df6884 100644 --- a/op-e2e/e2eutils/wait/blocks.go +++ b/op-e2e/e2eutils/wait/blocks.go @@ -6,6 +6,8 @@ import ( "math/big" "time" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum/go-ethereum/core/types" ) @@ -57,3 +59,12 @@ func ForNextBlock(ctx context.Context, client BlockCaller) error { } return ForBlock(ctx, client, current+1) } + +func ForProcessingFullBatch(ctx context.Context, rollupCl *sources.RollupClient) error { + _, err := AndGet(ctx, time.Second, func() (*eth.SyncStatus, error) { + return rollupCl.SyncStatus(ctx) + }, func(syncStatus *eth.SyncStatus) bool { + return syncStatus.PendingSafeL2 == syncStatus.SafeL2 + }) + return err +} diff --git a/op-e2e/faultproof_test.go b/op-e2e/faultproof_test.go index e6b2c755aeba..7857fbbee0f7 100644 --- a/op-e2e/faultproof_test.go +++ b/op-e2e/faultproof_test.go @@ -18,7 +18,7 @@ import ( ) func TestMultipleCannonGames(t *testing.T) { - InitParallel(t, UsesCannon) + InitParallel(t, UsesCannon, UseExecutor(0)) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -78,7 +78,7 @@ func TestMultipleCannonGames(t *testing.T) { } func TestMultipleGameTypes(t *testing.T) { - InitParallel(t, UsesCannon) + InitParallel(t, UsesCannon, UseExecutor(0)) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -113,7 +113,7 @@ func TestMultipleGameTypes(t *testing.T) { } func TestChallengerCompleteDisputeGame(t *testing.T) { - InitParallel(t) + InitParallel(t, UseExecutor(1)) tests := []struct { name string @@ -182,7 +182,7 @@ func TestChallengerCompleteDisputeGame(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { - InitParallel(t) + InitParallel(t, UseExecutor(1)) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -219,7 +219,7 @@ func TestChallengerCompleteDisputeGame(t *testing.T) { } func TestChallengerCompleteExhaustiveDisputeGame(t *testing.T) { - InitParallel(t) + InitParallel(t, UseExecutor(1)) testCase := func(t *testing.T, isRootCorrect bool) { ctx := context.Background() @@ -267,17 +267,17 @@ func TestChallengerCompleteExhaustiveDisputeGame(t *testing.T) { } t.Run("RootCorrect", func(t *testing.T) { - InitParallel(t) + InitParallel(t, UseExecutor(1)) testCase(t, true) }) t.Run("RootIncorrect", func(t *testing.T) { - InitParallel(t) + InitParallel(t, UseExecutor(1)) testCase(t, false) }) } func TestCannonDisputeGame(t *testing.T) { - InitParallel(t, UsesCannon) + InitParallel(t, UsesCannon, UseExecutor(1)) tests := []struct { name string @@ -290,7 +290,7 @@ func TestCannonDisputeGame(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { - InitParallel(t) + InitParallel(t, UseExecutor(1)) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -328,7 +328,7 @@ func TestCannonDisputeGame(t *testing.T) { } func TestCannonDefendStep(t *testing.T) { - InitParallel(t, UsesCannon) + InitParallel(t, UsesCannon, UseExecutor(1)) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -370,7 +370,7 @@ func TestCannonDefendStep(t *testing.T) { } func TestCannonProposedOutputRootInvalid(t *testing.T) { - InitParallel(t, UsesCannon) + InitParallel(t, UsesCannon, UseExecutor(0)) // honestStepsFail attempts to perform both an attack and defend step using the correct trace. honestStepsFail := func(ctx context.Context, game *disputegame.CannonGameHelper, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) { // Attack step should fail @@ -421,7 +421,7 @@ func TestCannonProposedOutputRootInvalid(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { - InitParallel(t) + InitParallel(t, UseExecutor(0)) ctx := context.Background() sys, l1Client, game, correctTrace := setupDisputeGameForInvalidOutputRoot(t, test.outputRoot) @@ -448,7 +448,7 @@ func TestCannonProposedOutputRootInvalid(t *testing.T) { } func TestCannonPoisonedPostState(t *testing.T) { - InitParallel(t, UsesCannon) + InitParallel(t, UsesCannon, UseExecutor(0)) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -558,8 +558,7 @@ func setupDisputeGameForInvalidOutputRoot(t *testing.T, outputRoot common.Hash) } func TestCannonChallengeWithCorrectRoot(t *testing.T) { - InitParallel(t, UsesCannon) - + InitParallel(t, UsesCannon, UseExecutor(0)) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) t.Cleanup(sys.Close) diff --git a/op-e2e/helper.go b/op-e2e/helper.go index 0b36458d4780..3c8d411b1292 100644 --- a/op-e2e/helper.go +++ b/op-e2e/helper.go @@ -2,23 +2,70 @@ package op_e2e import ( "os" + "strconv" "testing" ) var enableParallelTesting bool = os.Getenv("OP_E2E_DISABLE_PARALLEL") != "true" -func InitParallel(t *testing.T, opts ...func(t *testing.T)) { +type testopts struct { + executor uint64 +} + +func InitParallel(t *testing.T, args ...func(t *testing.T, opts *testopts)) { t.Helper() if enableParallelTesting { t.Parallel() } - for _, opt := range opts { - opt(t) + + opts := &testopts{} + for _, arg := range args { + arg(t, opts) } + checkExecutor(t, opts.executor) } -func UsesCannon(t *testing.T) { +func UsesCannon(t *testing.T, opts *testopts) { if os.Getenv("OP_E2E_CANNON_ENABLED") == "false" { t.Skip("Skipping cannon test") } } + +// UseExecutor allows manually splitting tests between circleci executors +// +// Tests default to run on the first executor but can be moved to the second with: +// InitParallel(t, UseExecutor(1)) +// Any tests assigned to an executor greater than the number available automatically use the last executor. +// Executor indexes start from 0 +func UseExecutor(assignedIdx uint64) func(t *testing.T, opts *testopts) { + return func(t *testing.T, opts *testopts) { + opts.executor = assignedIdx + } +} + +func checkExecutor(t *testing.T, assignedIdx uint64) { + envTotal := os.Getenv("CIRCLE_NODE_TOTAL") + envIdx := os.Getenv("CIRCLE_NODE_INDEX") + if envTotal == "" || envIdx == "" { + // Not using test splitting, so ignore assigned executor + t.Logf("Running test. Test splitting not in use.") + return + } + total, err := strconv.ParseUint(envTotal, 10, 0) + if err != nil { + t.Fatalf("Could not parse CIRCLE_NODE_TOTAL env var %v: %v", envTotal, err) + } + idx, err := strconv.ParseUint(envIdx, 10, 0) + if err != nil { + t.Fatalf("Could not parse CIRCLE_NODE_INDEX env var %v: %v", envIdx, err) + } + if assignedIdx >= total && idx == total-1 { + t.Logf("Running test. Current executor (%v) is the last executor and assigned executor (%v) >= total executors (%v).", idx, assignedIdx, total) + return + } + if idx == assignedIdx { + t.Logf("Running test. Assigned executor (%v) matches current executor (%v) of total (%v)", assignedIdx, idx, total) + return + } + t.Skipf("Skipping test. Assigned executor %v, current executor %v of total %v", assignedIdx, idx, total) +} diff --git a/op-e2e/setup.go b/op-e2e/setup.go index b3ca9b57f62e..4687f8709983 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -203,6 +203,9 @@ type SystemConfig struct { // Target L1 tx size for the batcher transactions BatcherTargetL1TxSizeBytes uint64 + // Max L1 tx size for the batcher transactions + BatcherMaxL1TxSizeBytes uint64 + // SupportL1TimeTravel determines if the L1 node supports quickly skipping forward in time SupportL1TimeTravel bool } @@ -680,17 +683,21 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste return nil, fmt.Errorf("unable to start l2 output submitter: %w", err) } - batchType := derive.SingularBatchType + var batchType uint = derive.SingularBatchType if os.Getenv("OP_E2E_USE_SPAN_BATCH") == "true" { batchType = derive.SpanBatchType } + batcherMaxL1TxSizeBytes := cfg.BatcherMaxL1TxSizeBytes + if batcherMaxL1TxSizeBytes == 0 { + batcherMaxL1TxSizeBytes = 240_000 + } batcherCLIConfig := &bss.CLIConfig{ L1EthRpc: sys.EthInstances["l1"].WSEndpoint(), L2EthRpc: sys.EthInstances["sequencer"].WSEndpoint(), RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), MaxPendingTransactions: 0, MaxChannelDuration: 1, - MaxL1TxSize: 240_000, + MaxL1TxSize: batcherMaxL1TxSizeBytes, CompressorConfig: compressor.CLIConfig{ TargetL1TxSizeBytes: cfg.BatcherTargetL1TxSizeBytes, TargetNumFrames: 1, @@ -704,7 +711,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste Format: oplog.FormatText, }, Stopped: sys.cfg.DisableBatcher, // Batch submitter may be enabled later - BatchType: uint(batchType), + BatchType: batchType, } // Batch Submitter batcher, err := bss.BatcherServiceFromCLIConfig(context.Background(), "0.0.1", batcherCLIConfig, sys.cfg.Loggers["batcher"]) diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go index 7ba9e012119c..6d9960320926 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -1272,6 +1272,7 @@ func TestStopStartBatcher(t *testing.T) { safeBlockInclusionDuration := time.Duration(6*cfg.DeployConfig.L1BlockTime) * time.Second _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) require.Nil(t, err, "Waiting for block on verifier") + require.NoError(t, wait.ForProcessingFullBatch(context.Background(), rollupClient)) // ensure the safe chain advances newSeqStatus, err := rollupClient.SyncStatus(context.Background()) @@ -1309,6 +1310,7 @@ func TestStopStartBatcher(t *testing.T) { // wait until the block the tx was first included in shows up in the safe chain on the verifier _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) require.Nil(t, err, "Waiting for block on verifier") + require.NoError(t, wait.ForProcessingFullBatch(context.Background(), rollupClient)) // ensure that the safe chain advances after restarting the batcher newSeqStatus, err = rollupClient.SyncStatus(context.Background()) @@ -1566,3 +1568,14 @@ func TestRequiredProtocolVersionChangeAndHalt(t *testing.T) { require.NoError(t, err) t.Log("verified that op-geth closed!") } + +func TestIncorrectBatcherConfiguration(t *testing.T) { + InitParallel(t) + + cfg := DefaultSystemConfig(t) + // make the batcher configuration invalid + cfg.BatcherMaxL1TxSizeBytes = 1 + + _, err := cfg.Start(t) + require.Error(t, err, "Expected error on invalid batcher configuration") +} diff --git a/op-node/chaincfg/chains.go b/op-node/chaincfg/chains.go index e864c93a94da..34ded749fad0 100644 --- a/op-node/chaincfg/chains.go +++ b/op-node/chaincfg/chains.go @@ -33,14 +33,7 @@ var L2ChainIDToNetworkDisplayName = func() map[string]string { }() // AvailableNetworks returns the selection of network configurations that is available by default. -// Other configurations that are part of the superchain-registry can be used with the --beta.network flag. func AvailableNetworks() []string { - return []string{"op-mainnet", "op-goerli", "op-sepolia"} -} - -// BetaAvailableNetworks returns all available network configurations in the superchain-registry. -// This set of configurations is experimental, and may change at any time. -func BetaAvailableNetworks() []string { var networks []string for _, cfg := range superchain.OPChains { networks = append(networks, cfg.Chain+"-"+cfg.Superchain) @@ -48,20 +41,6 @@ func BetaAvailableNetworks() []string { return networks } -func IsAvailableNetwork(name string, beta bool) bool { - name = handleLegacyName(name) - available := AvailableNetworks() - if beta { - available = BetaAvailableNetworks() - } - for _, v := range available { - if v == name { - return true - } - } - return false -} - func handleLegacyName(name string) string { switch name { case "goerli": @@ -91,7 +70,7 @@ func ChainByName(name string) *superchain.ChainConfig { func GetRollupConfig(name string) (*rollup.Config, error) { chainCfg := ChainByName(name) if chainCfg == nil { - return nil, fmt.Errorf("invalid network %s", name) + return nil, fmt.Errorf("invalid network: %q", name) } rollupCfg, err := rollup.LoadOPStackRollupConfig(chainCfg.ChainID) if err != nil { diff --git a/op-node/chaincfg/chains_test.go b/op-node/chaincfg/chains_test.go index da08e6db9113..98dbfa9ee1e3 100644 --- a/op-node/chaincfg/chains_test.go +++ b/op-node/chaincfg/chains_test.go @@ -27,8 +27,6 @@ func TestGetRollupConfig(t *testing.T) { } for name, expectedCfg := range configsByName { - require.True(t, IsAvailableNetwork(name, false)) - gotCfg, err := GetRollupConfig(name) require.NoError(t, err) @@ -95,6 +93,7 @@ var goerliCfg = rollup.Config{ DepositContractAddress: common.HexToAddress("0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383"), L1SystemConfigAddress: common.HexToAddress("0xAe851f927Ee40dE99aaBb7461C00f9622ab91d60"), RegolithTime: u64Ptr(1679079600), + CanyonTime: u64Ptr(1699981200), ProtocolVersionsAddress: common.HexToAddress("0x0C24F5098774aA366827D667494e9F889f7cFc08"), } @@ -126,6 +125,7 @@ var sepoliaCfg = rollup.Config{ DepositContractAddress: common.HexToAddress("0x16fc5058f25648194471939df75cf27a2fdc48bc"), L1SystemConfigAddress: common.HexToAddress("0x034edd2a225f7f429a63e0f1d2084b9e0a93b538"), RegolithTime: u64Ptr(0), + CanyonTime: u64Ptr(1699981200), ProtocolVersionsAddress: common.HexToAddress("0x79ADD5713B383DAa0a138d3C4780C7A1804a8090"), } diff --git a/op-node/cmd/batch_decoder/reassemble/reassemble.go b/op-node/cmd/batch_decoder/reassemble/reassemble.go index 8472ba8c03ca..adab7a9cdc8d 100644 --- a/op-node/cmd/batch_decoder/reassemble/reassemble.go +++ b/op-node/cmd/batch_decoder/reassemble/reassemble.go @@ -19,12 +19,12 @@ import ( ) type ChannelWithMetadata struct { - ID derive.ChannelID `json:"id"` - IsReady bool `json:"is_ready"` - InvalidFrames bool `json:"invalid_frames"` - InvalidBatches bool `json:"invalid_batches"` - Frames []FrameWithMetadata `json:"frames"` - Batches []derive.SingularBatch `json:"batches"` + ID derive.ChannelID `json:"id"` + IsReady bool `json:"is_ready"` + InvalidFrames bool `json:"invalid_frames"` + InvalidBatches bool `json:"invalid_batches"` + Frames []FrameWithMetadata `json:"frames"` + Batches []derive.BatchData `json:"batches"` } type FrameWithMetadata struct { @@ -104,7 +104,7 @@ func processFrames(cfg *rollup.Config, id derive.ChannelID, frames []FrameWithMe } } - var batches []derive.SingularBatch + var batches []derive.BatchData invalidBatches := false if ch.IsReady() { br, err := derive.BatchReader(ch.Reader()) @@ -114,11 +114,7 @@ func processFrames(cfg *rollup.Config, id derive.ChannelID, frames []FrameWithMe fmt.Printf("Error reading batch for channel %v. Err: %v\n", id.String(), err) invalidBatches = true } else { - if batch.BatchType != derive.SingularBatchType { - batches = append(batches, batch.SingularBatch) - } else { - fmt.Printf("batch-type %d is not supported", batch.BatchType) - } + batches = append(batches, *batch) } } } else { diff --git a/op-node/cmd/main.go b/op-node/cmd/main.go index 135db4059265..ed5377c64021 100644 --- a/op-node/cmd/main.go +++ b/op-node/cmd/main.go @@ -21,6 +21,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/cliapp" oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/metrics/doc" + "github.com/ethereum-optimism/optimism/op-service/opio" ) var ( @@ -58,7 +59,8 @@ func main() { }, } - err := app.Run(os.Args) + ctx := opio.WithInterruptBlocker(context.Background()) + err := app.RunContext(ctx, os.Args) if err != nil { log.Crit("Application failed", "message", err) } diff --git a/op-node/flags/flags.go b/op-node/flags/flags.go index 8976e39265f6..6c1b913a01fb 100644 --- a/op-node/flags/flags.go +++ b/op-node/flags/flags.go @@ -123,6 +123,7 @@ var ( Usage: "The L1 RethDB path, used to fetch receipts for L1 blocks. Only applicable when using the `reth_db` RPC kind with `l1.rpckind`.", EnvVars: prefixEnvVars("L1_RETHDB"), Required: false, + Hidden: true, } L1RPCRateLimit = &cli.Float64Flag{ Name: "l1.rpc-rate-limit", @@ -279,11 +280,10 @@ var ( Value: false, } BetaExtraNetworks = &cli.BoolFlag{ - Name: "beta.extra-networks", - Usage: fmt.Sprintf("Beta feature: enable selection of a predefined-network from the superchain-registry. "+ - "The superchain-registry is experimental, and the availability of configurations may change."+ - "Available networks: %s", strings.Join(chaincfg.BetaAvailableNetworks(), ", ")), + Name: "beta.extra-networks", + Usage: "Legacy flag, ignored, all superchain-registry networks are enabled by default.", EnvVars: prefixEnvVars("BETA_EXTRA_NETWORKS"), + Hidden: true, // hidden, this is deprecated, the flag is not used anymore. } RollupHalt = &cli.StringFlag{ Name: "rollup.halt", diff --git a/op-node/flags/p2p_flags.go b/op-node/flags/p2p_flags.go index 4f680eae7e8d..34577d831f5b 100644 --- a/op-node/flags/p2p_flags.go +++ b/op-node/flags/p2p_flags.go @@ -189,8 +189,9 @@ func P2PFlags(envPrefix string) []cli.Flag { EnvVars: p2pEnv(envPrefix, "BOOTNODES"), }, &cli.StringFlag{ - Name: StaticPeersName, - Usage: "Comma-separated multiaddr-format peer list. Static connections to make and maintain, these peers will be regarded as trusted.", + Name: StaticPeersName, + Usage: "Comma-separated multiaddr-format peer list. Static connections to make and maintain, these peers will be regarded as trusted. " + + "Addresses of the local peer are ignored. Duplicate/Alternative addresses for the same peer all apply, but only a single connection per peer is maintained.", Required: false, Value: "", EnvVars: p2pEnv(envPrefix, "STATIC"), diff --git a/op-node/node/server_test.go b/op-node/node/server_test.go index 744a5eb690d6..82da717a9f90 100644 --- a/op-node/node/server_test.go +++ b/op-node/node/server_test.go @@ -163,6 +163,7 @@ func randomSyncStatus(rng *rand.Rand) *eth.SyncStatus { UnsafeL2: testutils.RandomL2BlockRef(rng), SafeL2: testutils.RandomL2BlockRef(rng), FinalizedL2: testutils.RandomL2BlockRef(rng), + PendingSafeL2: testutils.RandomL2BlockRef(rng), UnsafeL2SyncTarget: testutils.RandomL2BlockRef(rng), EngineSyncTarget: testutils.RandomL2BlockRef(rng), } diff --git a/op-node/p2p/host.go b/op-node/p2p/host.go index 5396bed05d9c..6011617f5c78 100644 --- a/op-node/p2p/host.go +++ b/op-node/p2p/host.go @@ -229,13 +229,17 @@ func (conf *Config) Host(log log.Logger, reporter metrics.Reporter, metrics Host return nil, err } - staticPeers := make([]*peer.AddrInfo, len(conf.StaticPeers)) - for i, peerAddr := range conf.StaticPeers { + staticPeers := make([]*peer.AddrInfo, 0, len(conf.StaticPeers)) + for _, peerAddr := range conf.StaticPeers { addr, err := peer.AddrInfoFromP2pAddr(peerAddr) if err != nil { return nil, fmt.Errorf("bad peer address: %w", err) } - staticPeers[i] = addr + if addr.ID == h.ID() { + log.Info("Static-peer list contains address of local peer, ignoring the address.", "peer_id", addr.ID, "addrs", addr.Addrs) + continue + } + staticPeers = append(staticPeers, addr) } out := &extraHost{ diff --git a/op-node/p2p/host_test.go b/op-node/p2p/host_test.go index 1a44c25664b0..66454c70fe23 100644 --- a/op-node/p2p/host_test.go +++ b/op-node/p2p/host_test.go @@ -15,6 +15,7 @@ import ( "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" + ma "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/require" "golang.org/x/exp/slices" @@ -139,6 +140,13 @@ func TestP2PFull(t *testing.T) { confB.StaticPeers, err = peer.AddrInfoToP2pAddrs(&peer.AddrInfo{ID: hostA.ID(), Addrs: hostA.Addrs()}) require.NoError(t, err) + // Add address of host B itself, it shouldn't connect or cause issues. + idB, err := peer.IDFromPublicKey(confB.Priv.GetPublic()) + require.NoError(t, err) + altAddrB, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/12345/p2p/" + idB.String()) + require.NoError(t, err) + confB.StaticPeers = append(confB.StaticPeers, altAddrB) + logB := testlog.Logger(t, log.LvlError).New("host", "B") nodeB, err := NewNodeP2P(context.Background(), &rollup.Config{}, logB, &confB, &mockGossipIn{}, nil, runCfgB, metrics.NoopMetrics) @@ -146,6 +154,9 @@ func TestP2PFull(t *testing.T) { defer nodeB.Close() hostB := nodeB.Host() + require.True(t, nodeB.IsStatic(hostA.ID()), "node A must be static peer of node B") + require.False(t, nodeB.IsStatic(hostB.ID()), "node B must not be static peer of node B itself") + select { case <-time.After(time.Second): t.Fatal("failed to connect new host") diff --git a/op-node/p2p/node.go b/op-node/p2p/node.go index 7279f63e6a8c..9c4d3f4da082 100644 --- a/op-node/p2p/node.go +++ b/op-node/p2p/node.go @@ -142,7 +142,7 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l if err != nil { return fmt.Errorf("failed to join blocks gossip topic: %w", err) } - log.Info("started p2p host", "addrs", n.host.Addrs(), "peerID", n.host.ID().Pretty()) + log.Info("started p2p host", "addrs", n.host.Addrs(), "peerID", n.host.ID().String()) tcpPort, err := FindActiveTCPPort(n.host) if err != nil { diff --git a/op-node/rollup/derive/attributes_queue.go b/op-node/rollup/derive/attributes_queue.go index 023fbb3dccda..e923695a6cdf 100644 --- a/op-node/rollup/derive/attributes_queue.go +++ b/op-node/rollup/derive/attributes_queue.go @@ -28,11 +28,12 @@ type AttributesBuilder interface { } type AttributesQueue struct { - log log.Logger - config *rollup.Config - builder AttributesBuilder - prev *BatchQueue - batch *SingularBatch + log log.Logger + config *rollup.Config + builder AttributesBuilder + prev *BatchQueue + batch *SingularBatch + isLastInSpan bool } func NewAttributesQueue(log log.Logger, cfg *rollup.Config, builder AttributesBuilder, prev *BatchQueue) *AttributesQueue { @@ -48,23 +49,26 @@ func (aq *AttributesQueue) Origin() eth.L1BlockRef { return aq.prev.Origin() } -func (aq *AttributesQueue) NextAttributes(ctx context.Context, l2SafeHead eth.L2BlockRef) (*eth.PayloadAttributes, error) { +func (aq *AttributesQueue) NextAttributes(ctx context.Context, parent eth.L2BlockRef) (*AttributesWithParent, error) { // Get a batch if we need it if aq.batch == nil { - batch, err := aq.prev.NextBatch(ctx, l2SafeHead) + batch, isLastInSpan, err := aq.prev.NextBatch(ctx, parent) if err != nil { return nil, err } aq.batch = batch + aq.isLastInSpan = isLastInSpan } // Actually generate the next attributes - if attrs, err := aq.createNextAttributes(ctx, aq.batch, l2SafeHead); err != nil { + if attrs, err := aq.createNextAttributes(ctx, aq.batch, parent); err != nil { return nil, err } else { // Clear out the local state once we will succeed + attr := AttributesWithParent{attrs, parent, aq.isLastInSpan} aq.batch = nil - return attrs, nil + aq.isLastInSpan = false + return &attr, nil } } @@ -99,5 +103,6 @@ func (aq *AttributesQueue) createNextAttributes(ctx context.Context, batch *Sing func (aq *AttributesQueue) Reset(ctx context.Context, _ eth.L1BlockRef, _ eth.SystemConfig) error { aq.batch = nil + aq.isLastInSpan = false // overwritten later, but set for consistency return io.EOF } diff --git a/op-node/rollup/derive/batch.go b/op-node/rollup/derive/batch.go index 88b50bed641d..9f3563e79080 100644 --- a/op-node/rollup/derive/batch.go +++ b/op-node/rollup/derive/batch.go @@ -25,9 +25,9 @@ var encodeBufferPool = sync.Pool{ const ( // SingularBatchType is the first version of Batch format, representing a single L2 block. - SingularBatchType = iota + SingularBatchType = 0 // SpanBatchType is the Batch version used after SpanBatch hard fork, representing a span of L2 blocks. - SpanBatchType + SpanBatchType = 1 ) // Batch contains information to build one or multiple L2 blocks. @@ -39,12 +39,20 @@ type Batch interface { LogContext(log.Logger) log.Logger } -// BatchData is a composition type that contains raw data of each batch version. -// It has encoding & decoding methods to implement typed encoding. +// BatchData is used to represent the typed encoding & decoding. +// and wraps around a single interface InnerBatchData. +// Further fields such as cache can be added in the future, without embedding each type of InnerBatchData. +// Similar design with op-geth's types.Transaction struct. type BatchData struct { - BatchType int - SingularBatch - RawSpanBatch + inner InnerBatchData +} + +// InnerBatchData is the underlying data of a BatchData. +// This is implemented by SingularBatch and RawSpanBatch. +type InnerBatchData interface { + GetBatchType() int + encode(w io.Writer) error + decode(r *bytes.Reader) error } // EncodeRLP implements rlp.Encoder @@ -58,6 +66,10 @@ func (b *BatchData) EncodeRLP(w io.Writer) error { return rlp.Encode(w, buf.Bytes()) } +func (bd *BatchData) GetBatchType() uint8 { + return uint8(bd.inner.GetBatchType()) +} + // MarshalBinary returns the canonical encoding of the batch. func (b *BatchData) MarshalBinary() ([]byte, error) { var buf bytes.Buffer @@ -67,16 +79,10 @@ func (b *BatchData) MarshalBinary() ([]byte, error) { // encodeTyped encodes batch type and payload for each batch type. func (b *BatchData) encodeTyped(buf *bytes.Buffer) error { - switch b.BatchType { - case SingularBatchType: - buf.WriteByte(SingularBatchType) - return rlp.Encode(buf, &b.SingularBatch) - case SpanBatchType: - buf.WriteByte(SpanBatchType) - return b.RawSpanBatch.encode(buf) - default: - return fmt.Errorf("unrecognized batch type: %d", b.BatchType) + if err := buf.WriteByte(b.GetBatchType()); err != nil { + return err } + return b.inner.encode(buf) } // DecodeRLP implements rlp.Decoder @@ -99,35 +105,28 @@ func (b *BatchData) UnmarshalBinary(data []byte) error { return b.decodeTyped(data) } -// decodeTyped decodes batch type and payload for each batch type. +// decodeTyped decodes a typed batchData func (b *BatchData) decodeTyped(data []byte) error { if len(data) == 0 { - return fmt.Errorf("batch too short") + return errors.New("batch too short") } + var inner InnerBatchData switch data[0] { case SingularBatchType: - b.BatchType = SingularBatchType - return rlp.DecodeBytes(data[1:], &b.SingularBatch) + inner = new(SingularBatch) case SpanBatchType: - b.BatchType = int(data[0]) - return b.RawSpanBatch.decodeBytes(data[1:]) + inner = new(RawSpanBatch) default: return fmt.Errorf("unrecognized batch type: %d", data[0]) } -} - -// NewSingularBatchData creates new BatchData with SingularBatch -func NewSingularBatchData(singularBatch SingularBatch) *BatchData { - return &BatchData{ - BatchType: SingularBatchType, - SingularBatch: singularBatch, + if err := inner.decode(bytes.NewReader(data[1:])); err != nil { + return err } + b.inner = inner + return nil } -// NewSpanBatchData creates new BatchData with SpanBatch -func NewSpanBatchData(spanBatch RawSpanBatch) *BatchData { - return &BatchData{ - BatchType: SpanBatchType, - RawSpanBatch: spanBatch, - } +// NewBatchData creates a new BatchData +func NewBatchData(inner InnerBatchData) *BatchData { + return &BatchData{inner: inner} } diff --git a/op-node/rollup/derive/batch_queue.go b/op-node/rollup/derive/batch_queue.go index b12f08c54fbd..8e9dca29473d 100644 --- a/op-node/rollup/derive/batch_queue.go +++ b/op-node/rollup/derive/batch_queue.go @@ -45,6 +45,12 @@ type BatchQueue struct { prev NextBatchProvider origin eth.L1BlockRef + // l1Blocks contains consecutive eth.L1BlockRef sorted by time. + // Every L1 origin of unsafe L2 blocks must be eventually included in l1Blocks. + // Batch queue's job is to ensure below two rules: + // If every L2 block corresponding to single L1 block becomes safe, it will be popped from l1Blocks. + // If new L2 block's L1 origin is not included in l1Blocks, fetch and push to l1Blocks. + // length of l1Blocks never exceeds SequencerWindowSize l1Blocks []eth.L1BlockRef // batches in order of when we've first seen them @@ -72,40 +78,54 @@ func (bq *BatchQueue) Origin() eth.L1BlockRef { // popNextBatch pops the next batch from the current queued up span-batch nextSpan. // The queue must be non-empty, or the function will panic. -func (bq *BatchQueue) popNextBatch(safeL2Head eth.L2BlockRef) *SingularBatch { +func (bq *BatchQueue) popNextBatch(parent eth.L2BlockRef) *SingularBatch { if len(bq.nextSpan) == 0 { panic("popping non-existent span-batch, invalid state") } nextBatch := bq.nextSpan[0] bq.nextSpan = bq.nextSpan[1:] - // Must set ParentHash before return. we can use safeL2Head because the parentCheck is verified in CheckBatch(). - nextBatch.ParentHash = safeL2Head.Hash + // Must set ParentHash before return. we can use parent because the parentCheck is verified in CheckBatch(). + nextBatch.ParentHash = parent.Hash return nextBatch } -func (bq *BatchQueue) maybeAdvanceEpoch(nextBatch *SingularBatch) { - if len(bq.l1Blocks) == 0 { - return - } - if nextBatch.GetEpochNum() == rollup.Epoch(bq.l1Blocks[0].Number)+1 { - // Advance epoch if necessary - bq.l1Blocks = bq.l1Blocks[1:] +// NextBatch return next valid batch upon the given safe head. +// It also returns the boolean that indicates if the batch is the last block in the batch. +func (bq *BatchQueue) NextBatch(ctx context.Context, parent eth.L2BlockRef) (*SingularBatch, bool, error) { + if len(bq.nextSpan) > 0 { + // There are cached singular batches derived from the span batch. + // Check if the next cached batch matches the given parent block. + if bq.nextSpan[0].Timestamp == parent.Time+bq.config.BlockTime { + // Pop first one and return. + nextBatch := bq.popNextBatch(parent) + // len(bq.nextSpan) == 0 means it's the last batch of the span. + return nextBatch, len(bq.nextSpan) == 0, nil + } else { + // Given parent block does not match the next batch. It means the previously returned batch is invalid. + // Drop cached batches and find another batch. + bq.nextSpan = bq.nextSpan[:0] + } } -} -func (bq *BatchQueue) NextBatch(ctx context.Context, safeL2Head eth.L2BlockRef) (*SingularBatch, error) { - if len(bq.nextSpan) > 0 { - // If there are cached singular batches, pop first one and return. - nextBatch := bq.popNextBatch(safeL2Head) - bq.maybeAdvanceEpoch(nextBatch) - return nextBatch, nil + // If the epoch is advanced, update bq.l1Blocks + // Advancing epoch must be done after the pipeline successfully apply the entire span batch to the chain. + // Because the span batch can be reverted during processing the batch, then we must preserve existing l1Blocks + // to verify the epochs of the next candidate batch. + if len(bq.l1Blocks) > 0 && parent.L1Origin.Number > bq.l1Blocks[0].Number { + for i, l1Block := range bq.l1Blocks { + if parent.L1Origin.Number == l1Block.Number { + bq.l1Blocks = bq.l1Blocks[i:] + break + } + } + // If we can't find the origin of parent block, we have to advance bq.origin. } // Note: We use the origin that we will have to determine if it's behind. This is important // because it's the future origin that gets saved into the l1Blocks array. // We always update the origin of this stage if it is not the same so after the update code // runs, this is consistent. - originBehind := bq.prev.Origin().Number < safeL2Head.L1Origin.Number + originBehind := bq.prev.Origin().Number < parent.L1Origin.Number // Advance origin if needed // Note: The entire pipeline has the same origin @@ -128,29 +148,29 @@ func (bq *BatchQueue) NextBatch(ctx context.Context, safeL2Head eth.L2BlockRef) if batch, err := bq.prev.NextBatch(ctx); err == io.EOF { outOfData = true } else if err != nil { - return nil, err + return nil, false, err } else if !originBehind { - bq.AddBatch(ctx, batch, safeL2Head) + bq.AddBatch(ctx, batch, parent) } // Skip adding data unless we are up to date with the origin, but do fully // empty the previous stages if originBehind { if outOfData { - return nil, io.EOF + return nil, false, io.EOF } else { - return nil, NotEnoughData + return nil, false, NotEnoughData } } // Finally attempt to derive more batches - batch, err := bq.deriveNextBatch(ctx, outOfData, safeL2Head) + batch, err := bq.deriveNextBatch(ctx, outOfData, parent) if err == io.EOF && outOfData { - return nil, io.EOF + return nil, false, io.EOF } else if err == io.EOF { - return nil, NotEnoughData + return nil, false, NotEnoughData } else if err != nil { - return nil, err + return nil, false, err } var nextBatch *SingularBatch @@ -158,28 +178,29 @@ func (bq *BatchQueue) NextBatch(ctx context.Context, safeL2Head eth.L2BlockRef) case SingularBatchType: singularBatch, ok := batch.(*SingularBatch) if !ok { - return nil, NewCriticalError(errors.New("failed type assertion to SingularBatch")) + return nil, false, NewCriticalError(errors.New("failed type assertion to SingularBatch")) } nextBatch = singularBatch case SpanBatchType: spanBatch, ok := batch.(*SpanBatch) if !ok { - return nil, NewCriticalError(errors.New("failed type assertion to SpanBatch")) + return nil, false, NewCriticalError(errors.New("failed type assertion to SpanBatch")) } // If next batch is SpanBatch, convert it to SingularBatches. - singularBatches, err := spanBatch.GetSingularBatches(bq.l1Blocks, safeL2Head) + singularBatches, err := spanBatch.GetSingularBatches(bq.l1Blocks, parent) if err != nil { - return nil, NewCriticalError(err) + return nil, false, NewCriticalError(err) } bq.nextSpan = singularBatches // span-batches are non-empty, so the below pop is safe. - nextBatch = bq.popNextBatch(safeL2Head) + nextBatch = bq.popNextBatch(parent) default: - return nil, NewCriticalError(fmt.Errorf("unrecognized batch type: %d", batch.GetBatchType())) + return nil, false, NewCriticalError(fmt.Errorf("unrecognized batch type: %d", batch.GetBatchType())) } - bq.maybeAdvanceEpoch(nextBatch) - return nextBatch, nil + // If the nextBatch is derived from the span batch, len(bq.nextSpan) == 0 means it's the last batch of the span. + // For singular batches, len(bq.nextSpan) == 0 is always true. + return nextBatch, len(bq.nextSpan) == 0, nil } func (bq *BatchQueue) Reset(ctx context.Context, base eth.L1BlockRef, _ eth.SystemConfig) error { @@ -196,7 +217,7 @@ func (bq *BatchQueue) Reset(ctx context.Context, base eth.L1BlockRef, _ eth.Syst return io.EOF } -func (bq *BatchQueue) AddBatch(ctx context.Context, batch Batch, l2SafeHead eth.L2BlockRef) { +func (bq *BatchQueue) AddBatch(ctx context.Context, batch Batch, parent eth.L2BlockRef) { if len(bq.l1Blocks) == 0 { panic(fmt.Errorf("cannot add batch with timestamp %d, no origin was prepared", batch.GetTimestamp())) } @@ -204,7 +225,7 @@ func (bq *BatchQueue) AddBatch(ctx context.Context, batch Batch, l2SafeHead eth. L1InclusionBlock: bq.origin, Batch: batch, } - validity := CheckBatch(ctx, bq.config, bq.log, bq.l1Blocks, l2SafeHead, &data, bq.l2) + validity := CheckBatch(ctx, bq.config, bq.log, bq.l1Blocks, parent, &data, bq.l2) if validity == BatchDrop { return // if we do drop the batch, CheckBatch will log the drop reason with WARN level. } @@ -216,24 +237,24 @@ func (bq *BatchQueue) AddBatch(ctx context.Context, batch Batch, l2SafeHead eth. // following the validity rules imposed on consecutive batches, // based on currently available buffered batch and L1 origin information. // If no batch can be derived yet, then (nil, io.EOF) is returned. -func (bq *BatchQueue) deriveNextBatch(ctx context.Context, outOfData bool, l2SafeHead eth.L2BlockRef) (Batch, error) { +func (bq *BatchQueue) deriveNextBatch(ctx context.Context, outOfData bool, parent eth.L2BlockRef) (Batch, error) { if len(bq.l1Blocks) == 0 { return nil, NewCriticalError(errors.New("cannot derive next batch, no origin was prepared")) } epoch := bq.l1Blocks[0] - bq.log.Trace("Deriving the next batch", "epoch", epoch, "l2SafeHead", l2SafeHead, "outOfData", outOfData) + bq.log.Trace("Deriving the next batch", "epoch", epoch, "parent", parent, "outOfData", outOfData) // Note: epoch origin can now be one block ahead of the L2 Safe Head // This is in the case where we auto generate all batches in an epoch & advance the epoch // but don't advance the L2 Safe Head's epoch - if l2SafeHead.L1Origin != epoch.ID() && l2SafeHead.L1Origin.Number != epoch.Number-1 { - return nil, NewResetError(fmt.Errorf("buffered L1 chain epoch %s in batch queue does not match safe head origin %s", epoch, l2SafeHead.L1Origin)) + if parent.L1Origin != epoch.ID() && parent.L1Origin.Number != epoch.Number-1 { + return nil, NewResetError(fmt.Errorf("buffered L1 chain epoch %s in batch queue does not match safe head origin %s", epoch, parent.L1Origin)) } // Find the first-seen batch that matches all validity conditions. // We may not have sufficient information to proceed filtering, and then we stop. // There may be none: in that case we force-create an empty batch - nextTimestamp := l2SafeHead.Time + bq.config.BlockTime + nextTimestamp := parent.Time + bq.config.BlockTime var nextBatch *BatchWithL1InclusionBlock // Go over all batches, in order of inclusion, and find the first batch we can accept. @@ -241,15 +262,15 @@ func (bq *BatchQueue) deriveNextBatch(ctx context.Context, outOfData bool, l2Saf var remaining []*BatchWithL1InclusionBlock batchLoop: for i, batch := range bq.batches { - validity := CheckBatch(ctx, bq.config, bq.log.New("batch_index", i), bq.l1Blocks, l2SafeHead, batch, bq.l2) + validity := CheckBatch(ctx, bq.config, bq.log.New("batch_index", i), bq.l1Blocks, parent, batch, bq.l2) switch validity { case BatchFuture: remaining = append(remaining, batch) continue case BatchDrop: batch.Batch.LogContext(bq.log).Warn("Dropping batch", - "l2_safe_head", l2SafeHead.ID(), - "l2_safe_head_time", l2SafeHead.Time, + "parent", parent.ID(), + "parent_time", parent.Time, ) continue case BatchAccept: @@ -277,7 +298,7 @@ batchLoop: // i.e. if the sequence window expired, we create empty batches for the current epoch expiryEpoch := epoch.Number + bq.config.SeqWindowSize forceEmptyBatches := (expiryEpoch == bq.origin.Number && outOfData) || expiryEpoch < bq.origin.Number - firstOfEpoch := epoch.Number == l2SafeHead.L1Origin.Number+1 + firstOfEpoch := epoch.Number == parent.L1Origin.Number+1 bq.log.Trace("Potentially generating an empty batch", "expiryEpoch", expiryEpoch, "forceEmptyBatches", forceEmptyBatches, "nextTimestamp", nextTimestamp, @@ -300,7 +321,7 @@ batchLoop: if nextTimestamp < nextEpoch.Time || firstOfEpoch { bq.log.Info("Generating next batch", "epoch", epoch, "timestamp", nextTimestamp) return &SingularBatch{ - ParentHash: l2SafeHead.Hash, + ParentHash: parent.Hash, EpochNum: rollup.Epoch(epoch.Number), EpochHash: epoch.Hash, Timestamp: nextTimestamp, diff --git a/op-node/rollup/derive/batch_queue_test.go b/op-node/rollup/derive/batch_queue_test.go index 3580f78c40d6..fbd9ae1e86dc 100644 --- a/op-node/rollup/derive/batch_queue_test.go +++ b/op-node/rollup/derive/batch_queue_test.go @@ -197,7 +197,7 @@ func BatchQueueNewOrigin(t *testing.T, batchType int) { // Prev Origin: 0; Safehead Origin: 2; Internal Origin: 0 // Should return no data but keep the same origin - data, err := bq.NextBatch(context.Background(), safeHead) + data, _, err := bq.NextBatch(context.Background(), safeHead) require.Nil(t, data) require.Equal(t, io.EOF, err) require.Equal(t, []eth.L1BlockRef{l1[0]}, bq.l1Blocks) @@ -206,7 +206,7 @@ func BatchQueueNewOrigin(t *testing.T, batchType int) { // Prev Origin: 1; Safehead Origin: 2; Internal Origin: 0 // Should wipe l1blocks + advance internal origin input.origin = l1[1] - data, err = bq.NextBatch(context.Background(), safeHead) + data, _, err = bq.NextBatch(context.Background(), safeHead) require.Nil(t, data) require.Equal(t, io.EOF, err) require.Empty(t, bq.l1Blocks) @@ -215,7 +215,7 @@ func BatchQueueNewOrigin(t *testing.T, batchType int) { // Prev Origin: 2; Safehead Origin: 2; Internal Origin: 1 // Should add to l1Blocks + advance internal origin input.origin = l1[2] - data, err = bq.NextBatch(context.Background(), safeHead) + data, _, err = bq.NextBatch(context.Background(), safeHead) require.Nil(t, data) require.Equal(t, io.EOF, err) require.Equal(t, []eth.L1BlockRef{l1[2]}, bq.l1Blocks) @@ -286,7 +286,7 @@ func BatchQueueEager(t *testing.T, batchType int) { input.origin = l1[1] for i := 0; i < len(expectedOutputBatches); i++ { - b, e := bq.NextBatch(context.Background(), safeHead) + b, _, e := bq.NextBatch(context.Background(), safeHead) require.ErrorIs(t, e, expectedOutputErrors[i]) if b == nil { require.Nil(t, expectedOutputBatches[i]) @@ -363,7 +363,7 @@ func BatchQueueInvalidInternalAdvance(t *testing.T, batchType int) { // Load continuous batches for epoch 0 for i := 0; i < len(expectedOutputBatches); i++ { - b, e := bq.NextBatch(context.Background(), safeHead) + b, _, e := bq.NextBatch(context.Background(), safeHead) require.ErrorIs(t, e, expectedOutputErrors[i]) if b == nil { require.Nil(t, expectedOutputBatches[i]) @@ -378,20 +378,20 @@ func BatchQueueInvalidInternalAdvance(t *testing.T, batchType int) { // Advance to origin 1. No forced batches yet. input.origin = l1[1] - b, e := bq.NextBatch(context.Background(), safeHead) + b, _, e := bq.NextBatch(context.Background(), safeHead) require.ErrorIs(t, e, io.EOF) require.Nil(t, b) // Advance to origin 2. No forced batches yet because we are still on epoch 0 // & have batches for epoch 0. input.origin = l1[2] - b, e = bq.NextBatch(context.Background(), safeHead) + b, _, e = bq.NextBatch(context.Background(), safeHead) require.ErrorIs(t, e, io.EOF) require.Nil(t, b) // Advance to origin 3. Should generate one empty batch. input.origin = l1[3] - b, e = bq.NextBatch(context.Background(), safeHead) + b, _, e = bq.NextBatch(context.Background(), safeHead) require.Nil(t, e) require.NotNil(t, b) require.Equal(t, safeHead.Time+2, b.Timestamp) @@ -400,13 +400,13 @@ func BatchQueueInvalidInternalAdvance(t *testing.T, batchType int) { safeHead.Time += 2 safeHead.Hash = mockHash(b.Timestamp, 2) safeHead.L1Origin = b.Epoch() - b, e = bq.NextBatch(context.Background(), safeHead) + b, _, e = bq.NextBatch(context.Background(), safeHead) require.ErrorIs(t, e, io.EOF) require.Nil(t, b) // Advance to origin 4. Should generate one empty batch. input.origin = l1[4] - b, e = bq.NextBatch(context.Background(), safeHead) + b, _, e = bq.NextBatch(context.Background(), safeHead) require.Nil(t, e) require.NotNil(t, b) require.Equal(t, rollup.Epoch(2), b.EpochNum) @@ -415,7 +415,7 @@ func BatchQueueInvalidInternalAdvance(t *testing.T, batchType int) { safeHead.Time += 2 safeHead.Hash = mockHash(b.Timestamp, 2) safeHead.L1Origin = b.Epoch() - b, e = bq.NextBatch(context.Background(), safeHead) + b, _, e = bq.NextBatch(context.Background(), safeHead) require.ErrorIs(t, e, io.EOF) require.Nil(t, b) @@ -477,7 +477,7 @@ func BatchQueueMissing(t *testing.T, batchType int) { _ = bq.Reset(context.Background(), l1[0], eth.SystemConfig{}) for i := 0; i < len(expectedOutputBatches); i++ { - b, e := bq.NextBatch(context.Background(), safeHead) + b, _, e := bq.NextBatch(context.Background(), safeHead) require.ErrorIs(t, e, NotEnoughData) require.Nil(t, b) } @@ -485,7 +485,7 @@ func BatchQueueMissing(t *testing.T, batchType int) { // advance origin. Underlying stage still has no more inputBatches // This is not enough to auto advance yet input.origin = l1[1] - b, e := bq.NextBatch(context.Background(), safeHead) + b, _, e := bq.NextBatch(context.Background(), safeHead) require.ErrorIs(t, e, io.EOF) require.Nil(t, b) @@ -493,7 +493,7 @@ func BatchQueueMissing(t *testing.T, batchType int) { input.origin = l1[2] // Check for a generated batch at t = 12 - b, e = bq.NextBatch(context.Background(), safeHead) + b, _, e = bq.NextBatch(context.Background(), safeHead) require.Nil(t, e) require.Equal(t, b.Timestamp, uint64(12)) require.Empty(t, b.Transactions) @@ -503,7 +503,7 @@ func BatchQueueMissing(t *testing.T, batchType int) { safeHead.Hash = mockHash(b.Timestamp, 2) // Check for generated batch at t = 14 - b, e = bq.NextBatch(context.Background(), safeHead) + b, _, e = bq.NextBatch(context.Background(), safeHead) require.Nil(t, e) require.Equal(t, b.Timestamp, uint64(14)) require.Empty(t, b.Transactions) @@ -513,7 +513,7 @@ func BatchQueueMissing(t *testing.T, batchType int) { safeHead.Hash = mockHash(b.Timestamp, 2) // Check for the inputted batch at t = 16 - b, e = bq.NextBatch(context.Background(), safeHead) + b, _, e = bq.NextBatch(context.Background(), safeHead) require.Nil(t, e) require.Equal(t, b, expectedOutputBatches[0]) require.Equal(t, rollup.Epoch(0), b.EpochNum) @@ -527,9 +527,9 @@ func BatchQueueMissing(t *testing.T, batchType int) { // Check for the generated batch at t = 18. This batch advances the epoch // Note: We need one io.EOF returned from the bq that advances the internal L1 Blocks view // before the batch will be auto generated - _, e = bq.NextBatch(context.Background(), safeHead) + _, _, e = bq.NextBatch(context.Background(), safeHead) require.Equal(t, e, io.EOF) - b, e = bq.NextBatch(context.Background(), safeHead) + b, _, e = bq.NextBatch(context.Background(), safeHead) require.Nil(t, e) require.Equal(t, b.Timestamp, uint64(18)) require.Empty(t, b.Transactions) @@ -610,13 +610,12 @@ func BatchQueueAdvancedEpoch(t *testing.T, batchType int) { inputOriginNumber += 1 input.origin = l1[inputOriginNumber] } - b, e := bq.NextBatch(context.Background(), safeHead) + b, _, e := bq.NextBatch(context.Background(), safeHead) require.ErrorIs(t, e, expectedOutputErrors[i]) if b == nil { require.Nil(t, expectedOutput) } else { require.Equal(t, expectedOutput, b) - require.Equal(t, bq.l1Blocks[0].Number, uint64(b.EpochNum)) safeHead.Number += 1 safeHead.Time += cfg.BlockTime safeHead.Hash = mockHash(b.Timestamp, 2) @@ -706,7 +705,7 @@ func BatchQueueShuffle(t *testing.T, batchType int) { var e error for j := 0; j < len(expectedOutputBatches); j++ { // Multiple NextBatch() executions may be required because the order of input is shuffled - b, e = bq.NextBatch(context.Background(), safeHead) + b, _, e = bq.NextBatch(context.Background(), safeHead) if !errors.Is(e, NotEnoughData) { break } @@ -716,7 +715,6 @@ func BatchQueueShuffle(t *testing.T, batchType int) { require.Nil(t, expectedOutput) } else { require.Equal(t, expectedOutput, b) - require.Equal(t, bq.l1Blocks[0].Number, uint64(b.EpochNum)) safeHead.Number += 1 safeHead.Time += cfg.BlockTime safeHead.Hash = mockHash(b.Timestamp, 2) @@ -814,7 +812,7 @@ func TestBatchQueueOverlappingSpanBatch(t *testing.T) { input.origin = l1[1] for i := 0; i < len(expectedOutputBatches); i++ { - b, e := bq.NextBatch(context.Background(), safeHead) + b, _, e := bq.NextBatch(context.Background(), safeHead) require.ErrorIs(t, e, expectedOutputErrors[i]) if b == nil { require.Nil(t, expectedOutputBatches[i]) @@ -928,7 +926,7 @@ func TestBatchQueueComplex(t *testing.T) { var e error for j := 0; j < len(expectedOutputBatches); j++ { // Multiple NextBatch() executions may be required because the order of input is shuffled - b, e = bq.NextBatch(context.Background(), safeHead) + b, _, e = bq.NextBatch(context.Background(), safeHead) if !errors.Is(e, NotEnoughData) { break } @@ -938,7 +936,6 @@ func TestBatchQueueComplex(t *testing.T) { require.Nil(t, expectedOutput) } else { require.Equal(t, expectedOutput, b) - require.Equal(t, bq.l1Blocks[0].Number, uint64(b.EpochNum)) safeHead.Number += 1 safeHead.Time += cfg.BlockTime safeHead.Hash = mockHash(b.Timestamp, 2) @@ -948,3 +945,70 @@ func TestBatchQueueComplex(t *testing.T) { l2Client.Mock.AssertExpectations(t) } + +func TestBatchQueueResetSpan(t *testing.T) { + log := testlog.Logger(t, log.LvlCrit) + chainId := big.NewInt(1234) + l1 := L1Chain([]uint64{0, 4, 8}) + safeHead := eth.L2BlockRef{ + Hash: mockHash(0, 2), + Number: 0, + ParentHash: common.Hash{}, + Time: 0, + L1Origin: l1[0].ID(), + SequenceNumber: 0, + } + cfg := &rollup.Config{ + Genesis: rollup.Genesis{ + L2Time: 10, + }, + BlockTime: 2, + MaxSequencerDrift: 600, + SeqWindowSize: 30, + SpanBatchTime: getSpanBatchTime(SpanBatchType), + L2ChainID: chainId, + } + + singularBatches := []*SingularBatch{ + b(cfg.L2ChainID, 2, l1[0]), + b(cfg.L2ChainID, 4, l1[1]), + b(cfg.L2ChainID, 6, l1[1]), + b(cfg.L2ChainID, 8, l1[2]), + } + + input := &fakeBatchQueueInput{ + batches: []Batch{NewSpanBatch(singularBatches)}, + errors: []error{nil}, + origin: l1[2], + } + l2Client := testutils.MockL2Client{} + bq := NewBatchQueue(log, cfg, input, &l2Client) + bq.l1Blocks = l1 // Set enough l1 blocks to derive span batch + + // This NextBatch() will derive the span batch, return the first singular batch and save rest of batches in span. + nextBatch, _, err := bq.NextBatch(context.Background(), safeHead) + require.NoError(t, err) + require.Equal(t, nextBatch, singularBatches[0]) + require.Equal(t, len(bq.nextSpan), len(singularBatches)-1) + // batch queue's epoch should not be advanced until the entire span batch is returned + require.Equal(t, bq.l1Blocks[0], l1[0]) + + // This NextBatch() will return the second singular batch. + safeHead.Number += 1 + safeHead.Time += cfg.BlockTime + safeHead.Hash = mockHash(nextBatch.Timestamp, 2) + safeHead.L1Origin = nextBatch.Epoch() + nextBatch, _, err = bq.NextBatch(context.Background(), safeHead) + require.NoError(t, err) + require.Equal(t, nextBatch, singularBatches[1]) + require.Equal(t, len(bq.nextSpan), len(singularBatches)-2) + // batch queue's epoch should not be advanced until the entire span batch is returned + require.Equal(t, bq.l1Blocks[0], l1[0]) + + // Call NextBatch() with stale safeHead. It means the second batch failed to be processed. + // Batch queue should drop the entire span batch. + nextBatch, _, err = bq.NextBatch(context.Background(), safeHead) + require.Nil(t, nextBatch) + require.ErrorIs(t, err, io.EOF) + require.Equal(t, len(bq.nextSpan), 0) +} diff --git a/op-node/rollup/derive/batch_test.go b/op-node/rollup/derive/batch_test.go index b7646e7528d7..a5d438ebfec0 100644 --- a/op-node/rollup/derive/batch_test.go +++ b/op-node/rollup/derive/batch_test.go @@ -6,15 +6,16 @@ import ( "math/rand" "testing" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/testutils" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" + + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/testutils" ) func RandomRawSpanBatch(rng *rand.Rand, chainId *big.Int) *RawSpanBatch { @@ -52,8 +53,8 @@ func RandomRawSpanBatch(rng *rand.Rand, chainId *big.Int) *RawSpanBatch { spanBatchPrefix: spanBatchPrefix{ relTimestamp: uint64(rng.Uint32()), l1OriginNum: rng.Uint64(), - parentCheck: testutils.RandomData(rng, 20), - l1OriginCheck: testutils.RandomData(rng, 20), + parentCheck: [20]byte(testutils.RandomData(rng, 20)), + l1OriginCheck: [20]byte(testutils.RandomData(rng, 20)), }, spanBatchPayload: spanBatchPayload{ blockCount: blockCount, @@ -141,40 +142,42 @@ func TestBatchRoundTrip(t *testing.T) { chainID := new(big.Int).SetUint64(rng.Uint64()) batches := []*BatchData{ - { - SingularBatch: SingularBatch{ + NewBatchData( + &SingularBatch{ ParentHash: common.Hash{}, EpochNum: 0, Timestamp: 0, Transactions: []hexutil.Bytes{}, }, - }, - { - SingularBatch: SingularBatch{ + ), + NewBatchData( + &SingularBatch{ ParentHash: common.Hash{31: 0x42}, EpochNum: 1, Timestamp: 1647026951, Transactions: []hexutil.Bytes{[]byte{0, 0, 0}, []byte{0x76, 0xfd, 0x7c}}, }, - }, - NewSingularBatchData(*RandomSingularBatch(rng, 5, chainID)), - NewSingularBatchData(*RandomSingularBatch(rng, 7, chainID)), - NewSpanBatchData(*RandomRawSpanBatch(rng, chainID)), - NewSpanBatchData(*RandomRawSpanBatch(rng, chainID)), - NewSpanBatchData(*RandomRawSpanBatch(rng, chainID)), + ), + NewBatchData(RandomSingularBatch(rng, 5, chainID)), + NewBatchData(RandomSingularBatch(rng, 7, chainID)), + NewBatchData(RandomRawSpanBatch(rng, chainID)), + NewBatchData(RandomRawSpanBatch(rng, chainID)), + NewBatchData(RandomRawSpanBatch(rng, chainID)), } for i, batch := range batches { enc, err := batch.MarshalBinary() - assert.NoError(t, err) + require.NoError(t, err) var dec BatchData err = dec.UnmarshalBinary(enc) - assert.NoError(t, err) - if dec.BatchType == SpanBatchType { - _, err := dec.RawSpanBatch.derive(blockTime, genesisTimestamp, chainID) - assert.NoError(t, err) + require.NoError(t, err) + if dec.GetBatchType() == SpanBatchType { + rawSpanBatch, ok := dec.inner.(*RawSpanBatch) + require.True(t, ok) + _, err := rawSpanBatch.derive(blockTime, genesisTimestamp, chainID) + require.NoError(t, err) } - assert.Equal(t, batch, &dec, "Batch not equal test case %v", i) + require.Equal(t, batch, &dec, "Batch not equal test case %v", i) } } @@ -185,43 +188,45 @@ func TestBatchRoundTripRLP(t *testing.T) { chainID := new(big.Int).SetUint64(rng.Uint64()) batches := []*BatchData{ - { - SingularBatch: SingularBatch{ + NewBatchData( + &SingularBatch{ ParentHash: common.Hash{}, EpochNum: 0, Timestamp: 0, Transactions: []hexutil.Bytes{}, }, - }, - { - SingularBatch: SingularBatch{ + ), + NewBatchData( + &SingularBatch{ ParentHash: common.Hash{31: 0x42}, EpochNum: 1, Timestamp: 1647026951, Transactions: []hexutil.Bytes{[]byte{0, 0, 0}, []byte{0x76, 0xfd, 0x7c}}, }, - }, - NewSingularBatchData(*RandomSingularBatch(rng, 5, chainID)), - NewSingularBatchData(*RandomSingularBatch(rng, 7, chainID)), - NewSpanBatchData(*RandomRawSpanBatch(rng, chainID)), - NewSpanBatchData(*RandomRawSpanBatch(rng, chainID)), - NewSpanBatchData(*RandomRawSpanBatch(rng, chainID)), + ), + NewBatchData(RandomSingularBatch(rng, 5, chainID)), + NewBatchData(RandomSingularBatch(rng, 7, chainID)), + NewBatchData(RandomRawSpanBatch(rng, chainID)), + NewBatchData(RandomRawSpanBatch(rng, chainID)), + NewBatchData(RandomRawSpanBatch(rng, chainID)), } for i, batch := range batches { var buf bytes.Buffer err := batch.EncodeRLP(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() var dec BatchData r := bytes.NewReader(result) s := rlp.NewStream(r, 0) err = dec.DecodeRLP(s) - assert.NoError(t, err) - if dec.BatchType == SpanBatchType { - _, err := dec.RawSpanBatch.derive(blockTime, genesisTimestamp, chainID) - assert.NoError(t, err) + require.NoError(t, err) + if dec.GetBatchType() == SpanBatchType { + rawSpanBatch, ok := dec.inner.(*RawSpanBatch) + require.True(t, ok) + _, err := rawSpanBatch.derive(blockTime, genesisTimestamp, chainID) + require.NoError(t, err) } - assert.Equal(t, batch, &dec, "Batch not equal test case %v", i) + require.Equal(t, batch, &dec, "Batch not equal test case %v", i) } } diff --git a/op-node/rollup/derive/batch_tob_test.go b/op-node/rollup/derive/batch_tob_test.go index 6955fdcf5a42..5b62b4b5bb6f 100644 --- a/op-node/rollup/derive/batch_tob_test.go +++ b/op-node/rollup/derive/batch_tob_test.go @@ -17,13 +17,13 @@ func FuzzBatchRoundTrip(f *testing.F) { typeProvider := fuzz.NewFromGoFuzz(fuzzedData).NilChance(0).MaxDepth(10000).NumElements(0, 0x100).AllowUnexportedFields(true) fuzzerutils.AddFuzzerFunctions(typeProvider) + var singularBatch SingularBatch + typeProvider.Fuzz(&singularBatch) + // Create our batch data from fuzzed data var batchData BatchData - typeProvider.Fuzz(&batchData) - // force batchdata to only contain singular batch - batchData.BatchType = SingularBatchType - batchData.RawSpanBatch = RawSpanBatch{} + batchData.inner = &singularBatch // Encode our batch data enc, err := batchData.MarshalBinary() diff --git a/op-node/rollup/derive/batches.go b/op-node/rollup/derive/batches.go index e618fcc7433a..9cba08686f4c 100644 --- a/op-node/rollup/derive/batches.go +++ b/op-node/rollup/derive/batches.go @@ -47,10 +47,6 @@ func CheckBatch(ctx context.Context, cfg *rollup.Config, log log.Logger, l1Block log.Error("failed type assertion to SpanBatch") return BatchDrop } - if !cfg.IsSpanBatch(batch.Batch.GetTimestamp()) { - log.Warn("received SpanBatch before SpanBatch hard fork") - return BatchDrop - } return checkSpanBatch(ctx, cfg, log, l1Blocks, l2SafeHead, spanBatch, batch.L1InclusionBlock, l2Fetcher) default: log.Warn("Unrecognized batch type: %d", batch.Batch.GetBatchType()) @@ -181,6 +177,20 @@ func checkSpanBatch(ctx context.Context, cfg *rollup.Config, log log.Logger, l1B } epoch := l1Blocks[0] + startEpochNum := uint64(batch.GetStartEpochNum()) + batchOrigin := epoch + if startEpochNum == batchOrigin.Number+1 { + if len(l1Blocks) < 2 { + log.Info("eager batch wants to advance epoch, but could not without more L1 blocks", "current_epoch", epoch.ID()) + return BatchUndecided + } + batchOrigin = l1Blocks[1] + } + if !cfg.IsSpanBatch(batchOrigin.Time) { + log.Warn("received SpanBatch with L1 origin before SpanBatch hard fork") + return BatchDrop + } + nextTimestamp := l2SafeHead.Time + cfg.BlockTime if batch.GetTimestamp() > nextTimestamp { @@ -199,18 +209,18 @@ func checkSpanBatch(ctx context.Context, cfg *rollup.Config, log log.Logger, l1B if batch.GetTimestamp() < nextTimestamp { if batch.GetTimestamp() > l2SafeHead.Time { // batch timestamp cannot be between safe head and next timestamp - log.Warn("batch has misaligned timestamp") + log.Warn("batch has misaligned timestamp, block time is too short") return BatchDrop } if (l2SafeHead.Time-batch.GetTimestamp())%cfg.BlockTime != 0 { - log.Warn("batch has misaligned timestamp") + log.Warn("batch has misaligned timestamp, not overlapped exactly") return BatchDrop } parentNum = l2SafeHead.Number - (l2SafeHead.Time-batch.GetTimestamp())/cfg.BlockTime - 1 var err error parentBlock, err = l2Fetcher.L2BlockRefByNumber(ctx, parentNum) if err != nil { - log.Error("failed to fetch L2 block", "number", parentNum, "err", err) + log.Warn("failed to fetch L2 block", "number", parentNum, "err", err) // unable to validate the batch for now. retry later. return BatchUndecided } @@ -220,8 +230,6 @@ func checkSpanBatch(ctx context.Context, cfg *rollup.Config, log log.Logger, l1B return BatchDrop } - startEpochNum := uint64(batch.GetStartEpochNum()) - // Filter out batches that were included too late. if startEpochNum+cfg.SeqWindowSize < l1InclusionBlock.Number { log.Warn("batch was included too late, sequence window expired") @@ -236,6 +244,7 @@ func checkSpanBatch(ctx context.Context, cfg *rollup.Config, log log.Logger, l1B endEpochNum := batch.GetBlockEpochNum(batch.GetBlockCount() - 1) originChecked := false + // l1Blocks is supplied from batch queue and its length is limited to SequencerWindowSize. for _, l1Block := range l1Blocks { if l1Block.Number == endEpochNum { if !batch.CheckOriginHash(l1Block.Hash) { @@ -331,7 +340,7 @@ func checkSpanBatch(ctx context.Context, cfg *rollup.Config, log log.Logger, l1B safeBlockNum := parentNum + i + 1 safeBlockPayload, err := l2Fetcher.PayloadByNumber(ctx, safeBlockNum) if err != nil { - log.Error("failed to fetch L2 block payload", "number", parentNum, "err", err) + log.Warn("failed to fetch L2 block payload", "number", parentNum, "err", err) // unable to validate the batch for now. retry later. return BatchUndecided } diff --git a/op-node/rollup/derive/batches_test.go b/op-node/rollup/derive/batches_test.go index a3948fa1a27a..b122a61e0e79 100644 --- a/op-node/rollup/derive/batches_test.go +++ b/op-node/rollup/derive/batches_test.go @@ -1,10 +1,12 @@ package derive import ( + "bytes" "context" "errors" "math/big" "math/rand" + "strings" "testing" "github.com/stretchr/testify/require" @@ -20,27 +22,31 @@ import ( ) type ValidBatchTestCase struct { - Name string - L1Blocks []eth.L1BlockRef - L2SafeHead eth.L2BlockRef - Batch BatchWithL1InclusionBlock - Expected BatchValidity + Name string + L1Blocks []eth.L1BlockRef + L2SafeHead eth.L2BlockRef + Batch BatchWithL1InclusionBlock + Expected BatchValidity + ExpectedLog string // log message that must be included + NotExpectedLog string // log message that must not be included + SpanBatchTime *uint64 } -type SpanBatchHardForkTestCase struct { - Name string - L1Blocks []eth.L1BlockRef - L2SafeHead eth.L2BlockRef - Batch BatchWithL1InclusionBlock - Expected BatchValidity - SpanBatchTime uint64 +type TestLogHandler struct { + handler log.Handler + logs *bytes.Buffer +} + +func (th *TestLogHandler) Log(r *log.Record) error { + th.logs.WriteString(r.Msg + "\n") + return th.handler.Log(r) } var HashA = common.Hash{0x0a} var HashB = common.Hash{0x0b} -func TestValidSingularBatch(t *testing.T) { - conf := rollup.Config{ +func TestValidBatch(t *testing.T) { + defaultConf := rollup.Config{ Genesis: rollup.Genesis{ L2Time: 31, // a genesis time that itself does not align to make it more interesting }, @@ -48,9 +54,17 @@ func TestValidSingularBatch(t *testing.T) { SeqWindowSize: 4, MaxSequencerDrift: 6, // other config fields are ignored and can be left empty. + SpanBatchTime: nil, } rng := rand.New(rand.NewSource(1234)) + + minTs := uint64(0) + chainId := new(big.Int).SetUint64(rng.Uint64()) + signer := types.NewLondonSigner(chainId) + randTx := testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer) + randTxData, _ := randTx.MarshalBinary() + l1A := testutils.RandomBlockRef(rng) l1B := eth.L1BlockRef{ Hash: testutils.RandomHash(rng), @@ -96,7 +110,7 @@ func TestValidSingularBatch(t *testing.T) { Hash: testutils.RandomHash(rng), Number: l2A0.Number + 1, ParentHash: l2A0.Hash, - Time: l2A0.Time + conf.BlockTime, + Time: l2A0.Time + defaultConf.BlockTime, L1Origin: l1A.ID(), SequenceNumber: 1, } @@ -105,7 +119,7 @@ func TestValidSingularBatch(t *testing.T) { Hash: testutils.RandomHash(rng), Number: l2A1.Number + 1, ParentHash: l2A1.Hash, - Time: l2A1.Time + conf.BlockTime, + Time: l2A1.Time + defaultConf.BlockTime, L1Origin: l1A.ID(), SequenceNumber: 2, } @@ -114,7 +128,7 @@ func TestValidSingularBatch(t *testing.T) { Hash: testutils.RandomHash(rng), Number: l2A2.Number + 1, ParentHash: l2A2.Hash, - Time: l2A2.Time + conf.BlockTime, + Time: l2A2.Time + defaultConf.BlockTime, L1Origin: l1A.ID(), SequenceNumber: 3, } @@ -123,11 +137,29 @@ func TestValidSingularBatch(t *testing.T) { Hash: testutils.RandomHash(rng), Number: l2A3.Number + 1, ParentHash: l2A3.Hash, - Time: l2A3.Time + conf.BlockTime, // 8 seconds larger than l1A0, 1 larger than origin + Time: l2A3.Time + defaultConf.BlockTime, // 8 seconds larger than l1A0, 1 larger than origin L1Origin: l1B.ID(), SequenceNumber: 0, } + l2B1 := eth.L2BlockRef{ + Hash: testutils.RandomHash(rng), + Number: l2B0.Number + 1, + ParentHash: l2B0.Hash, + Time: l2B0.Time + defaultConf.BlockTime, + L1Origin: l1B.ID(), + SequenceNumber: 1, + } + + l2B2 := eth.L2BlockRef{ + Hash: testutils.RandomHash(rng), + Number: l2B1.Number + 1, + ParentHash: l2B1.Hash, + Time: l2B1.Time + defaultConf.BlockTime, + L1Origin: l1B.ID(), + SequenceNumber: 2, + } + l1X := eth.L1BlockRef{ Hash: testutils.RandomHash(rng), Number: 42, @@ -150,7 +182,7 @@ func TestValidSingularBatch(t *testing.T) { Hash: testutils.RandomHash(rng), Number: 1000, ParentHash: testutils.RandomHash(rng), - Time: 10_000 + 12 + 6 - 1, // add one block, and you get ahead of next l1 block by more than the drift + Time: 10_000 + 24 + 6 - 1, // add one block, and you get ahead of next l1 block by more than the drift L1Origin: l1X.ID(), SequenceNumber: 0, } @@ -158,16 +190,24 @@ func TestValidSingularBatch(t *testing.T) { Hash: testutils.RandomHash(rng), Number: l2X0.Number + 1, ParentHash: l2X0.Hash, - Time: l2X0.Time + conf.BlockTime, // exceeds sequencer time drift, forced to be empty block + Time: l2X0.Time + defaultConf.BlockTime, // exceeds sequencer time drift, forced to be empty block L1Origin: l1Y.ID(), SequenceNumber: 0, } + l2Z0 := eth.L2BlockRef{ + Hash: testutils.RandomHash(rng), + Number: l2Y0.Number + 1, + ParentHash: l2Y0.Hash, + Time: l2Y0.Time + defaultConf.BlockTime, // exceeds sequencer time drift, forced to be empty block + L1Origin: l1Z.ID(), + SequenceNumber: 0, + } l2A4 := eth.L2BlockRef{ Hash: testutils.RandomHash(rng), Number: l2A3.Number + 1, ParentHash: l2A3.Hash, - Time: l2A3.Time + conf.BlockTime, // 4*2 = 8, higher than seq time drift + Time: l2A3.Time + defaultConf.BlockTime, // 4*2 = 8, higher than seq time drift L1Origin: l1A.ID(), SequenceNumber: 4, } @@ -179,7 +219,7 @@ func TestValidSingularBatch(t *testing.T) { Time: l2A4.Time + 1, // too late for l2A4 to adopt yet } - testCases := []ValidBatchTestCase{ + singularBatchTestCases := []ValidBatchTestCase{ { Name: "missing L1 info", L1Blocks: []eth.L1BlockRef{}, @@ -286,7 +326,7 @@ func TestValidSingularBatch(t *testing.T) { ParentHash: l2B0.Hash, // build on top of safe head to continue EpochNum: rollup.Epoch(l2A3.L1Origin.Number), // epoch A is no longer valid EpochHash: l2A3.L1Origin.Hash, - Timestamp: l2B0.Time + conf.BlockTime, // pass the timestamp check to get too epoch check + Timestamp: l2B0.Time + defaultConf.BlockTime, // pass the timestamp check to get too epoch check Transactions: nil, }, }, @@ -520,173 +560,14 @@ func TestValidSingularBatch(t *testing.T) { ParentHash: l2A2.Hash, EpochNum: rollup.Epoch(l2B0.L1Origin.Number), EpochHash: l2B0.L1Origin.Hash, - Timestamp: l2A2.Time + conf.BlockTime, + Timestamp: l2A2.Time + defaultConf.BlockTime, Transactions: nil, }, }, Expected: BatchDrop, }, } - - // Log level can be increased for debugging purposes - logger := testlog.Logger(t, log.LvlError) - - for _, testCase := range testCases { - t.Run(testCase.Name, func(t *testing.T) { - ctx := context.Background() - validity := CheckBatch(ctx, &conf, logger, testCase.L1Blocks, testCase.L2SafeHead, &testCase.Batch, nil) - require.Equal(t, testCase.Expected, validity, "batch check must return expected validity level") - }) - } -} - -func TestValidSpanBatch(t *testing.T) { - minTs := uint64(0) - conf := rollup.Config{ - Genesis: rollup.Genesis{ - L2Time: 31, // a genesis time that itself does not align to make it more interesting - }, - BlockTime: 2, - SeqWindowSize: 4, - MaxSequencerDrift: 6, - SpanBatchTime: &minTs, - // other config fields are ignored and can be left empty. - } - - rng := rand.New(rand.NewSource(1234)) - chainId := new(big.Int).SetUint64(rng.Uint64()) - signer := types.NewLondonSigner(chainId) - randTx := testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer) - randTxData, _ := randTx.MarshalBinary() - l1A := testutils.RandomBlockRef(rng) - l1B := eth.L1BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l1A.Number + 1, - ParentHash: l1A.Hash, - Time: l1A.Time + 7, - } - l1C := eth.L1BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l1B.Number + 1, - ParentHash: l1B.Hash, - Time: l1B.Time + 7, - } - l1D := eth.L1BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l1C.Number + 1, - ParentHash: l1C.Hash, - Time: l1C.Time + 7, - } - l1E := eth.L1BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l1D.Number + 1, - ParentHash: l1D.Hash, - Time: l1D.Time + 7, - } - l1F := eth.L1BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l1E.Number + 1, - ParentHash: l1E.Hash, - Time: l1E.Time + 7, - } - - l2A0 := eth.L2BlockRef{ - Hash: testutils.RandomHash(rng), - Number: 100, - ParentHash: testutils.RandomHash(rng), - Time: l1A.Time, - L1Origin: l1A.ID(), - SequenceNumber: 0, - } - - l2A1 := eth.L2BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l2A0.Number + 1, - ParentHash: l2A0.Hash, - Time: l2A0.Time + conf.BlockTime, - L1Origin: l1A.ID(), - SequenceNumber: 1, - } - - l2A2 := eth.L2BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l2A1.Number + 1, - ParentHash: l2A1.Hash, - Time: l2A1.Time + conf.BlockTime, - L1Origin: l1A.ID(), - SequenceNumber: 2, - } - - l2A3 := eth.L2BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l2A2.Number + 1, - ParentHash: l2A2.Hash, - Time: l2A2.Time + conf.BlockTime, - L1Origin: l1A.ID(), - SequenceNumber: 3, - } - - l2B0 := eth.L2BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l2A3.Number + 1, - ParentHash: l2A3.Hash, - Time: l2A3.Time + conf.BlockTime, // 8 seconds larger than l1A0, 1 larger than origin - L1Origin: l1B.ID(), - SequenceNumber: 0, - } - - l1X := eth.L1BlockRef{ - Hash: testutils.RandomHash(rng), - Number: 42, - ParentHash: testutils.RandomHash(rng), - Time: 10_000, - } - l1Y := eth.L1BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l1X.Number + 1, - ParentHash: l1X.Hash, - Time: l1X.Time + 12, - } - l1Z := eth.L1BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l1Y.Number + 1, - ParentHash: l1Y.Hash, - Time: l1Y.Time + 12, - } - l2X0 := eth.L2BlockRef{ - Hash: testutils.RandomHash(rng), - Number: 1000, - ParentHash: testutils.RandomHash(rng), - Time: 10_000 + 12 + 6 - 1, // add one block, and you get ahead of next l1 block by more than the drift - L1Origin: l1X.ID(), - SequenceNumber: 0, - } - l2Y0 := eth.L2BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l2X0.Number + 1, - ParentHash: l2X0.Hash, - Time: l2X0.Time + conf.BlockTime, // exceeds sequencer time drift, forced to be empty block - L1Origin: l1Y.ID(), - SequenceNumber: 0, - } - - l2A4 := eth.L2BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l2A3.Number + 1, - ParentHash: l2A3.Hash, - Time: l2A3.Time + conf.BlockTime, // 4*2 = 8, higher than seq time drift - L1Origin: l1A.ID(), - SequenceNumber: 4, - } - - l1BLate := eth.L1BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l1A.Number + 1, - ParentHash: l1A.Hash, - Time: l2A4.Time + 1, // too late for l2A4 to adopt yet - } - - testCases := []ValidBatchTestCase{ + spanBatchTestCases := []ValidBatchTestCase{ { Name: "missing L1 info", L1Blocks: []eth.L1BlockRef{}, @@ -703,7 +584,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchUndecided, + Expected: BatchUndecided, + ExpectedLog: "missing L1 block input, cannot proceed with batch checking", + SpanBatchTime: &minTs, }, { Name: "future timestamp", @@ -721,25 +604,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchFuture, - }, - { - Name: "old timestamp", - L1Blocks: []eth.L1BlockRef{l1A, l1B, l1C}, - L2SafeHead: l2A0, - Batch: BatchWithL1InclusionBlock{ - L1InclusionBlock: l1B, - Batch: NewSpanBatch([]*SingularBatch{ - { - ParentHash: l2A1.ParentHash, - EpochNum: rollup.Epoch(l2A1.L1Origin.Number), - EpochHash: l2A1.L1Origin.Hash, - Timestamp: l2A0.Time, // repeating the same time - Transactions: nil, - }, - }), - }, - Expected: BatchDrop, + Expected: BatchFuture, + ExpectedLog: "received out-of-order batch for future processing after next batch", + SpanBatchTime: &minTs, }, { Name: "misaligned timestamp", @@ -757,7 +624,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "span batch has no new blocks after safe head", + SpanBatchTime: &minTs, }, { Name: "invalid parent block hash", @@ -775,7 +644,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "ignoring batch with mismatching parent hash", + SpanBatchTime: &minTs, }, { Name: "sequence window expired", @@ -793,7 +664,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "batch was included too late, sequence window expired", + SpanBatchTime: &minTs, }, { Name: "epoch too old, but good parent hash and timestamp", // repeat of now outdated l2A3 data @@ -806,18 +679,20 @@ func TestValidSpanBatch(t *testing.T) { ParentHash: l2B0.Hash, // build on top of safe head to continue EpochNum: rollup.Epoch(l2A3.L1Origin.Number), // epoch A is no longer valid EpochHash: l2A3.L1Origin.Hash, - Timestamp: l2B0.Time + conf.BlockTime, // pass the timestamp check to get too epoch check + Timestamp: l2B0.Time + defaultConf.BlockTime, // pass the timestamp check to get too epoch check Transactions: nil, }, { EpochNum: rollup.Epoch(l1B.Number), EpochHash: l1B.Hash, // pass the l1 origin check - Timestamp: l2B0.Time + conf.BlockTime*2, + Timestamp: l2B0.Time + defaultConf.BlockTime*2, Transactions: nil, }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "dropped batch, epoch is too old", + SpanBatchTime: &minTs, }, { Name: "insufficient L1 info for eager derivation", @@ -835,7 +710,36 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchUndecided, + Expected: BatchUndecided, + ExpectedLog: "eager batch wants to advance epoch, but could not without more L1 blocks", + SpanBatchTime: &minTs, + }, + { + Name: "insufficient L1 info for eager derivation - long span", + L1Blocks: []eth.L1BlockRef{l1A}, // don't know about l1B yet + L2SafeHead: l2A2, + Batch: BatchWithL1InclusionBlock{ + L1InclusionBlock: l1C, + Batch: NewSpanBatch([]*SingularBatch{ + { + ParentHash: l2A3.ParentHash, + EpochNum: rollup.Epoch(l2A3.L1Origin.Number), + EpochHash: l2A3.L1Origin.Hash, + Timestamp: l2A3.Time, + Transactions: nil, + }, + { + ParentHash: l2B0.ParentHash, + EpochNum: rollup.Epoch(l2B0.L1Origin.Number), + EpochHash: l2B0.L1Origin.Hash, + Timestamp: l2B0.Time, + Transactions: nil, + }, + }), + }, + Expected: BatchUndecided, + ExpectedLog: "need more l1 blocks to check entire origins of span batch", + SpanBatchTime: &minTs, }, { Name: "epoch too new", @@ -853,7 +757,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "batch is for future epoch too far ahead, while it has the next timestamp, so it must be invalid", + SpanBatchTime: &minTs, }, { Name: "epoch hash wrong", @@ -871,7 +777,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "batch is for different L1 chain, epoch hash does not match", + SpanBatchTime: &minTs, }, { Name: "epoch hash wrong - long span", @@ -896,7 +804,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "batch is for different L1 chain, epoch hash does not match", + SpanBatchTime: &minTs, }, { Name: "sequencer time drift on same epoch with non-empty txs", @@ -914,7 +824,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "batch exceeded sequencer time drift, sequencer must adopt new L1 origin to include transactions again", + SpanBatchTime: &minTs, }, { Name: "sequencer time drift on same epoch with non-empty txs - long span", @@ -939,7 +851,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "batch exceeded sequencer time drift, sequencer must adopt new L1 origin to include transactions again", + SpanBatchTime: &minTs, }, { Name: "sequencer time drift on changing epoch with non-empty txs", @@ -957,7 +871,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "batch exceeded sequencer time drift, sequencer must adopt new L1 origin to include transactions again", + SpanBatchTime: &minTs, }, { Name: "sequencer time drift on same epoch with empty txs and late next epoch", @@ -975,7 +891,8 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchAccept, // accepted because empty & preserving L2 time invariant + Expected: BatchAccept, // accepted because empty & preserving L2 time invariant + SpanBatchTime: &minTs, }, { Name: "sequencer time drift on changing epoch with empty txs", @@ -991,9 +908,18 @@ func TestValidSpanBatch(t *testing.T) { Timestamp: l2Y0.Time, // valid, but more than 6 ahead of l1Y.Time Transactions: nil, }, + { + ParentHash: l2Z0.ParentHash, + EpochNum: rollup.Epoch(l2Z0.L1Origin.Number), + EpochHash: l2Z0.L1Origin.Hash, + Timestamp: l2Z0.Time, // valid, but more than 6 ahead of l1Y.Time + Transactions: nil, + }, }), }, - Expected: BatchAccept, // accepted because empty & still advancing epoch + Expected: BatchAccept, // accepted because empty & still advancing epoch + SpanBatchTime: &minTs, + NotExpectedLog: "continuing with empty batch before late L1 block to preserve L2 time invariant", }, { Name: "sequencer time drift on same epoch with empty txs and no next epoch in sight yet", @@ -1011,7 +937,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchUndecided, // we have to wait till the next epoch is in sight to check the time + Expected: BatchUndecided, // we have to wait till the next epoch is in sight to check the time + ExpectedLog: "without the next L1 origin we cannot determine yet if this empty batch that exceeds the time drift is still valid", + SpanBatchTime: &minTs, }, { Name: "sequencer time drift on same epoch with empty txs and no next epoch in sight yet - long span", @@ -1036,7 +964,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchUndecided, // we have to wait till the next epoch is in sight to check the time + Expected: BatchUndecided, // we have to wait till the next epoch is in sight to check the time + ExpectedLog: "without the next L1 origin we cannot determine yet if this empty batch that exceeds the time drift is still valid", + SpanBatchTime: &minTs, }, { Name: "sequencer time drift on same epoch with empty txs and but in-sight epoch that invalidates it", @@ -1054,7 +984,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, // dropped because it could have advanced the epoch to B + Expected: BatchDrop, // dropped because it could have advanced the epoch to B + ExpectedLog: "batch exceeded sequencer time drift without adopting next origin, and next L1 origin would have been valid", + SpanBatchTime: &minTs, }, { Name: "sequencer time drift on same epoch with empty txs and but in-sight epoch that invalidates it - long span", @@ -1079,7 +1011,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, // dropped because it could have advanced the epoch to B + Expected: BatchDrop, // dropped because it could have advanced the epoch to B + ExpectedLog: "batch exceeded sequencer time drift without adopting next origin, and next L1 origin would have been valid", + SpanBatchTime: &minTs, }, { Name: "empty tx included", @@ -1099,7 +1033,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "transaction data must not be empty, but found empty tx", + SpanBatchTime: &minTs, }, { Name: "deposit tx included", @@ -1119,7 +1055,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "sequencers may not embed any deposits into batch data, but found tx that has one", + SpanBatchTime: &minTs, }, { Name: "valid batch same epoch", @@ -1137,7 +1075,8 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchAccept, + Expected: BatchAccept, + SpanBatchTime: &minTs, }, { Name: "valid batch changing epoch", @@ -1155,7 +1094,8 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchAccept, + Expected: BatchAccept, + SpanBatchTime: &minTs, }, { Name: "batch with L2 time before L1 time", @@ -1168,12 +1108,14 @@ func TestValidSpanBatch(t *testing.T) { ParentHash: l2A2.Hash, EpochNum: rollup.Epoch(l2B0.L1Origin.Number), EpochHash: l2B0.L1Origin.Hash, - Timestamp: l2A2.Time + conf.BlockTime, + Timestamp: l2A2.Time + defaultConf.BlockTime, Transactions: nil, }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "block timestamp is less than L1 origin timestamp", + SpanBatchTime: &minTs, }, { Name: "batch with L2 time before L1 time - long span", @@ -1193,12 +1135,14 @@ func TestValidSpanBatch(t *testing.T) { ParentHash: l2A2.Hash, EpochNum: rollup.Epoch(l2B0.L1Origin.Number), EpochHash: l2B0.L1Origin.Hash, - Timestamp: l2A2.Time + conf.BlockTime, + Timestamp: l2A2.Time + defaultConf.BlockTime, Transactions: nil, }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "block timestamp is less than L1 origin timestamp", + SpanBatchTime: &minTs, }, { Name: "valid overlapping batch", @@ -1223,7 +1167,8 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchAccept, + Expected: BatchAccept, + SpanBatchTime: &minTs, }, { Name: "longer overlapping batch", @@ -1255,7 +1200,8 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchAccept, + Expected: BatchAccept, + SpanBatchTime: &minTs, }, { Name: "fully overlapping batch", @@ -1280,7 +1226,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "span batch has no new blocks after safe head", + SpanBatchTime: &minTs, }, { Name: "overlapping batch with invalid parent hash", @@ -1305,7 +1253,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "ignoring batch with mismatching parent hash", + SpanBatchTime: &minTs, }, { Name: "overlapping batch with invalid origin number", @@ -1330,7 +1280,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "overlapped block's L1 origin number does not match", + SpanBatchTime: &minTs, }, { Name: "overlapping batch with invalid tx", @@ -1355,7 +1307,9 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchDrop, + Expected: BatchDrop, + ExpectedLog: "overlapped block's tx count does not match", + SpanBatchTime: &minTs, }, { Name: "overlapping batch l2 fetcher error", @@ -1387,89 +1341,91 @@ func TestValidSpanBatch(t *testing.T) { }, }), }, - Expected: BatchUndecided, + Expected: BatchUndecided, + ExpectedLog: "failed to fetch L2 block", + SpanBatchTime: &minTs, }, - } - - // Log level can be increased for debugging purposes - logger := testlog.Logger(t, log.LvlError) - - l2Client := testutils.MockL2Client{} - var nilErr error - // will be return error for block #99 (parent of l2A0) - tempErr := errors.New("temp error") - l2Client.Mock.On("L2BlockRefByNumber", l2A0.Number-1).Times(9999).Return(eth.L2BlockRef{}, &tempErr) - l2Client.Mock.On("PayloadByNumber", l2A0.Number-1).Times(9999).Return(nil, &tempErr) - - // make payloads for L2 blocks and set as expected return value of MockL2Client - for _, l2Block := range []eth.L2BlockRef{l2A0, l2A1, l2A2, l2A3, l2A4, l2B0} { - l2Client.ExpectL2BlockRefByNumber(l2Block.Number, l2Block, nil) - txData := l1InfoDepositTx(t, l2Block.L1Origin.Number) - payload := eth.ExecutionPayload{ - ParentHash: l2Block.ParentHash, - BlockNumber: hexutil.Uint64(l2Block.Number), - Timestamp: hexutil.Uint64(l2Block.Time), - BlockHash: l2Block.Hash, - Transactions: []hexutil.Bytes{txData}, - } - l2Client.Mock.On("L2BlockRefByNumber", l2Block.Number).Times(9999).Return(l2Block, &nilErr) - l2Client.Mock.On("PayloadByNumber", l2Block.Number).Times(9999).Return(&payload, &nilErr) - } - - for _, testCase := range testCases { - t.Run(testCase.Name, func(t *testing.T) { - ctx := context.Background() - validity := CheckBatch(ctx, &conf, logger, testCase.L1Blocks, testCase.L2SafeHead, &testCase.Batch, &l2Client) - require.Equal(t, testCase.Expected, validity, "batch check must return expected validity level") - }) - } -} - -func TestSpanBatchHardFork(t *testing.T) { - minTs := uint64(0) - conf := rollup.Config{ - Genesis: rollup.Genesis{ - L2Time: 31, // a genesis time that itself does not align to make it more interesting + { + Name: "short block time", + L1Blocks: []eth.L1BlockRef{l1A, l1B}, + L2SafeHead: l2A0, + Batch: BatchWithL1InclusionBlock{ + L1InclusionBlock: l1B, + Batch: NewSpanBatch([]*SingularBatch{ + { + ParentHash: l2A0.Hash, + EpochNum: rollup.Epoch(l2A1.L1Origin.Number), + EpochHash: l2A1.L1Origin.Hash, + Timestamp: l2A0.Time + 1, + Transactions: nil, + }, + { + ParentHash: l2A1.Hash, + EpochNum: rollup.Epoch(l2A2.L1Origin.Number), + EpochHash: l2A2.L1Origin.Hash, + Timestamp: l2A1.Time + 1, + Transactions: nil, + }, + }), + }, + Expected: BatchDrop, + ExpectedLog: "batch has misaligned timestamp, block time is too short", + SpanBatchTime: &minTs, + }, + { + Name: "misaligned batch", + L1Blocks: []eth.L1BlockRef{l1A, l1B}, + L2SafeHead: l2A0, + Batch: BatchWithL1InclusionBlock{ + L1InclusionBlock: l1B, + Batch: NewSpanBatch([]*SingularBatch{ + { + ParentHash: l2A0.Hash, + EpochNum: rollup.Epoch(l2A1.L1Origin.Number), + EpochHash: l2A1.L1Origin.Hash, + Timestamp: l2A0.Time - 1, + Transactions: nil, + }, + { + ParentHash: l2A1.Hash, + EpochNum: rollup.Epoch(l2A2.L1Origin.Number), + EpochHash: l2A2.L1Origin.Hash, + Timestamp: l2A1.Time, + Transactions: nil, + }, + }), + }, + Expected: BatchDrop, + ExpectedLog: "batch has misaligned timestamp, not overlapped exactly", + SpanBatchTime: &minTs, + }, + { + Name: "failed to fetch overlapping block payload", + L1Blocks: []eth.L1BlockRef{l1A, l1B}, + L2SafeHead: l2A3, + Batch: BatchWithL1InclusionBlock{ + L1InclusionBlock: l1B, + Batch: NewSpanBatch([]*SingularBatch{ + { + ParentHash: l2A2.Hash, + EpochNum: rollup.Epoch(l2A3.L1Origin.Number), + EpochHash: l2A3.L1Origin.Hash, + Timestamp: l2A3.Time, + Transactions: nil, + }, + { + ParentHash: l2A3.Hash, + EpochNum: rollup.Epoch(l2B0.L1Origin.Number), + EpochHash: l2B0.L1Origin.Hash, + Timestamp: l2B0.Time, + Transactions: nil, + }, + }), + }, + Expected: BatchUndecided, + ExpectedLog: "failed to fetch L2 block payload", + SpanBatchTime: &minTs, }, - BlockTime: 2, - SeqWindowSize: 4, - MaxSequencerDrift: 6, - SpanBatchTime: &minTs, - // other config fields are ignored and can be left empty. - } - - rng := rand.New(rand.NewSource(1234)) - chainId := new(big.Int).SetUint64(rng.Uint64()) - signer := types.NewLondonSigner(chainId) - randTx := testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer) - randTxData, _ := randTx.MarshalBinary() - l1A := testutils.RandomBlockRef(rng) - l1B := eth.L1BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l1A.Number + 1, - ParentHash: l1A.Hash, - Time: l1A.Time + 7, - } - - l2A0 := eth.L2BlockRef{ - Hash: testutils.RandomHash(rng), - Number: 100, - ParentHash: testutils.RandomHash(rng), - Time: l1A.Time, - L1Origin: l1A.ID(), - SequenceNumber: 0, - } - - l2A1 := eth.L2BlockRef{ - Hash: testutils.RandomHash(rng), - Number: l2A0.Number + 1, - ParentHash: l2A0.Hash, - Time: l2A0.Time + conf.BlockTime, - L1Origin: l1A.ID(), - SequenceNumber: 1, - } - - testCases := []SpanBatchHardForkTestCase{ { Name: "singular batch before hard fork", L1Blocks: []eth.L1BlockRef{l1A, l1B}, @@ -1484,7 +1440,7 @@ func TestSpanBatchHardFork(t *testing.T) { Transactions: []hexutil.Bytes{randTxData}, }, }, - SpanBatchTime: l2A1.Time + 2, + SpanBatchTime: &l1B.Time, Expected: BatchAccept, }, { @@ -1503,8 +1459,9 @@ func TestSpanBatchHardFork(t *testing.T) { }, }), }, - SpanBatchTime: l2A1.Time + 2, + SpanBatchTime: &l1B.Time, Expected: BatchDrop, + ExpectedLog: "received SpanBatch with L1 origin before SpanBatch hard fork", }, { Name: "singular batch after hard fork", @@ -1520,7 +1477,7 @@ func TestSpanBatchHardFork(t *testing.T) { Transactions: []hexutil.Bytes{randTxData}, }, }, - SpanBatchTime: l2A1.Time - 2, + SpanBatchTime: &l1A.Time, Expected: BatchAccept, }, { @@ -1539,21 +1496,167 @@ func TestSpanBatchHardFork(t *testing.T) { }, }), }, - SpanBatchTime: l2A1.Time - 2, + SpanBatchTime: &l1A.Time, Expected: BatchAccept, }, } // Log level can be increased for debugging purposes - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LvlError) + + // Create a test log handler to check expected logs + var logBuf bytes.Buffer + handler := TestLogHandler{handler: logger.GetHandler(), logs: &logBuf} + logger.SetHandler(&handler) + + l2Client := testutils.MockL2Client{} + var nilErr error + tempErr := errors.New("temp error") + // will return an error for block #99 (parent of l2A0) + l2Client.Mock.On("L2BlockRefByNumber", l2A0.Number-1).Return(eth.L2BlockRef{}, &tempErr) + // will return an error for l2A3 + l2Client.Mock.On("PayloadByNumber", l2A3.Number).Return(ð.ExecutionPayload{}, &tempErr) + + // make payloads for L2 blocks and set as expected return value of MockL2Client + for _, l2Block := range []eth.L2BlockRef{l2A0, l2A1, l2A2, l2B0} { + l2Client.ExpectL2BlockRefByNumber(l2Block.Number, l2Block, nil) + txData := l1InfoDepositTx(t, l2Block.L1Origin.Number) + payload := eth.ExecutionPayload{ + ParentHash: l2Block.ParentHash, + BlockNumber: hexutil.Uint64(l2Block.Number), + Timestamp: hexutil.Uint64(l2Block.Time), + BlockHash: l2Block.Hash, + Transactions: []hexutil.Bytes{txData}, + } + l2Client.Mock.On("L2BlockRefByNumber", l2Block.Number).Return(l2Block, &nilErr) + l2Client.Mock.On("PayloadByNumber", l2Block.Number).Return(&payload, &nilErr) + } - for _, testCase := range testCases { - t.Run(testCase.Name, func(t *testing.T) { - rcfg := conf - rcfg.SpanBatchTime = &testCase.SpanBatchTime - ctx := context.Background() - validity := CheckBatch(ctx, &rcfg, logger, testCase.L1Blocks, testCase.L2SafeHead, &testCase.Batch, nil) - require.Equal(t, testCase.Expected, validity, "batch check must return expected validity level") + runTestCase := func(t *testing.T, testCase ValidBatchTestCase) { + ctx := context.Background() + rcfg := defaultConf + if testCase.SpanBatchTime != nil { + rcfg.SpanBatchTime = testCase.SpanBatchTime + } + validity := CheckBatch(ctx, &rcfg, logger, testCase.L1Blocks, testCase.L2SafeHead, &testCase.Batch, &l2Client) + require.Equal(t, testCase.Expected, validity, "batch check must return expected validity level") + if testCase.ExpectedLog != "" { + // Check if ExpectedLog is contained in the log buffer + if !strings.Contains(logBuf.String(), testCase.ExpectedLog) { + t.Errorf("Expected log message was not found in the buffer: %s", testCase.ExpectedLog) + } + } + if testCase.NotExpectedLog != "" { + // Check if NotExpectedLog is contained in the log buffer + if strings.Contains(logBuf.String(), testCase.NotExpectedLog) { + t.Errorf("Not expected log message was found in the buffer: %s", testCase.NotExpectedLog) + } + } + logBuf.Reset() + } + + // Run singular batch test cases + for _, testCase := range singularBatchTestCases { + t.Run("singular_"+testCase.Name, func(t *testing.T) { + runTestCase(t, testCase) + }) + } + + // Run span batch test cases + for _, testCase := range spanBatchTestCases { + t.Run("span_"+testCase.Name, func(t *testing.T) { + runTestCase(t, testCase) }) } + + // ====== Test different TX for overlapping batches ====== + l2Client.ExpectL2BlockRefByNumber(l2B1.Number, l2B1, nil) + txData := l1InfoDepositTx(t, l2B1.L1Origin.Number) + randTx = testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer) + randTxData, _ = randTx.MarshalBinary() + payload := eth.ExecutionPayload{ + ParentHash: l2B0.Hash, + BlockNumber: hexutil.Uint64(l2B1.Number), + Timestamp: hexutil.Uint64(l2B1.Time), + BlockHash: l2B1.Hash, + Transactions: []hexutil.Bytes{txData, randTxData}, + } + l2Client.Mock.On("PayloadByNumber", l2B1.Number).Return(&payload, &nilErr).Once() + + randTx = testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer) + randTxData, _ = randTx.MarshalBinary() + differentTxtestCase := ValidBatchTestCase{ + Name: "different_tx_overlapping_batch", + L1Blocks: []eth.L1BlockRef{l1B}, + L2SafeHead: l2B1, + Batch: BatchWithL1InclusionBlock{ + L1InclusionBlock: l1B, + Batch: NewSpanBatch([]*SingularBatch{ + { + ParentHash: l2B0.Hash, + EpochNum: rollup.Epoch(l2B1.L1Origin.Number), + EpochHash: l2B1.L1Origin.Hash, + Timestamp: l2B1.Time, + Transactions: []hexutil.Bytes{randTxData}, // Random generated TX that does not match overlapping block + }, + { + ParentHash: l2B1.Hash, + EpochNum: rollup.Epoch(l2B2.L1Origin.Number), + EpochHash: l2B2.L1Origin.Hash, + Timestamp: l2B2.Time, + Transactions: nil, + }, + }), + }, + Expected: BatchDrop, + ExpectedLog: "overlapped block's transaction does not match", + SpanBatchTime: &minTs, + } + + t.Run(differentTxtestCase.Name, func(t *testing.T) { + runTestCase(t, differentTxtestCase) + }) + + // ====== Test invalid TX for overlapping batches ====== + payload = eth.ExecutionPayload{ + ParentHash: l2B0.Hash, + BlockNumber: hexutil.Uint64(l2B1.Number), + Timestamp: hexutil.Uint64(l2B1.Time), + BlockHash: l2B1.Hash, + // First TX is not a deposit TX. it will make error when extracting L2BlockRef from the payload + Transactions: []hexutil.Bytes{randTxData}, + } + l2Client.Mock.On("PayloadByNumber", l2B1.Number).Return(&payload, &nilErr).Once() + + invalidTxTestCase := ValidBatchTestCase{ + Name: "invalid_tx_overlapping_batch", + L1Blocks: []eth.L1BlockRef{l1B}, + L2SafeHead: l2B1, + Batch: BatchWithL1InclusionBlock{ + L1InclusionBlock: l1B, + Batch: NewSpanBatch([]*SingularBatch{ + { + ParentHash: l2B0.Hash, + EpochNum: rollup.Epoch(l2B1.L1Origin.Number), + EpochHash: l2B1.L1Origin.Hash, + Timestamp: l2B1.Time, + Transactions: []hexutil.Bytes{randTxData}, + }, + { + ParentHash: l2B1.Hash, + EpochNum: rollup.Epoch(l2B2.L1Origin.Number), + EpochHash: l2B2.L1Origin.Hash, + Timestamp: l2B2.Time, + Transactions: nil, + }, + }), + }, + Expected: BatchDrop, + ExpectedLog: "failed to extract L2BlockRef from execution payload", + SpanBatchTime: &minTs, + } + + t.Run(invalidTxTestCase.Name, func(t *testing.T) { + runTestCase(t, invalidTxTestCase) + }) } diff --git a/op-node/rollup/derive/channel_in_reader.go b/op-node/rollup/derive/channel_in_reader.go index 1553bd9a6656..374b676ccf0e 100644 --- a/op-node/rollup/derive/channel_in_reader.go +++ b/op-node/rollup/derive/channel_in_reader.go @@ -3,6 +3,7 @@ package derive import ( "bytes" "context" + "errors" "fmt" "io" @@ -89,22 +90,33 @@ func (cr *ChannelInReader) NextBatch(ctx context.Context) (Batch, error) { cr.NextChannel() return nil, NotEnoughData } - switch batchData.BatchType { + switch batchData.GetBatchType() { case SingularBatchType: - return &batchData.SingularBatch, nil + singularBatch, ok := batchData.inner.(*SingularBatch) + if !ok { + return nil, NewCriticalError(errors.New("failed type assertion to SingularBatch")) + } + return singularBatch, nil case SpanBatchType: if origin := cr.Origin(); !cr.cfg.IsSpanBatch(origin.Time) { + // Check hard fork activation with the L1 inclusion block time instead of the L1 origin block time. + // Therefore, even if the batch passed this rule, it can be dropped in the batch queue. + // This is just for early dropping invalid batches as soon as possible. return nil, NewTemporaryError(fmt.Errorf("cannot accept span batch in L1 block %s at time %d", origin, origin.Time)) } + rawSpanBatch, ok := batchData.inner.(*RawSpanBatch) + if !ok { + return nil, NewCriticalError(errors.New("failed type assertion to SpanBatch")) + } // If the batch type is Span batch, derive block inputs from RawSpanBatch. - spanBatch, err := batchData.RawSpanBatch.derive(cr.cfg.BlockTime, cr.cfg.Genesis.L2Time, cr.cfg.L2ChainID) + spanBatch, err := rawSpanBatch.derive(cr.cfg.BlockTime, cr.cfg.Genesis.L2Time, cr.cfg.L2ChainID) if err != nil { return nil, err } return spanBatch, nil default: // error is bubbled up to user, but pipeline can skip the batch and continue after. - return nil, NewTemporaryError(fmt.Errorf("unrecognized batch type: %w", err)) + return nil, NewTemporaryError(fmt.Errorf("unrecognized batch type: %d", batchData.GetBatchType())) } } diff --git a/op-node/rollup/derive/channel_out.go b/op-node/rollup/derive/channel_out.go index 5eb559678f6a..e932b9524ba7 100644 --- a/op-node/rollup/derive/channel_out.go +++ b/op-node/rollup/derive/channel_out.go @@ -145,7 +145,7 @@ func (co *SingularChannelOut) AddSingularBatch(batch *SingularBatch, _ uint64) ( // We encode to a temporary buffer to determine the encoded length to // ensure that the total size of all RLP elements is less than or equal to MAX_RLP_BYTES_PER_CHANNEL var buf bytes.Buffer - if err := rlp.Encode(&buf, NewSingularBatchData(*batch)); err != nil { + if err := rlp.Encode(&buf, NewBatchData(batch)); err != nil { return 0, err } if co.rlpLength+buf.Len() > MaxRLPBytesPerChannel { diff --git a/op-node/rollup/derive/engine_queue.go b/op-node/rollup/derive/engine_queue.go index b8cd3ae5917f..8073849aa7c3 100644 --- a/op-node/rollup/derive/engine_queue.go +++ b/op-node/rollup/derive/engine_queue.go @@ -17,14 +17,15 @@ import ( "github.com/ethereum-optimism/optimism/op-service/eth" ) -type attributesWithParent struct { - attributes *eth.PayloadAttributes - parent eth.L2BlockRef +type AttributesWithParent struct { + attributes *eth.PayloadAttributes + parent eth.L2BlockRef + isLastInSpan bool } type NextAttributesProvider interface { Origin() eth.L1BlockRef - NextAttributes(context.Context, eth.L2BlockRef) (*eth.PayloadAttributes, error) + NextAttributes(context.Context, eth.L2BlockRef) (*AttributesWithParent, error) } type Engine interface { @@ -103,6 +104,10 @@ type EngineQueue struct { safeHead eth.L2BlockRef unsafeHead eth.L2BlockRef + // L2 block processed from the batch, but not consolidated to the safe block yet. + // Consolidation will be pending until the entire batch is processed successfully, to guarantee the span batch atomicity. + pendingSafeHead eth.L2BlockRef + // Target L2 block the engine is currently syncing to. // If the engine p2p sync is enabled, it can be different with unsafeHead. Otherwise, it must be same with unsafeHead. engineSyncTarget eth.L2BlockRef @@ -124,7 +129,7 @@ type EngineQueue struct { triedFinalizeAt eth.L1BlockRef // The queued-up attributes - safeAttributes *attributesWithParent + safeAttributes *AttributesWithParent unsafePayloads *PayloadsQueue // queue of unsafe payloads, ordered by ascending block number, may have gaps and duplicates // Tracks which L2 blocks where last derived from which L1 block. At most finalityLookback large. @@ -235,6 +240,10 @@ func (eq *EngineQueue) SafeL2Head() eth.L2BlockRef { return eq.safeHead } +func (eq *EngineQueue) PendingSafeL2Head() eth.L2BlockRef { + return eq.pendingSafeHead +} + func (eq *EngineQueue) EngineSyncTarget() eth.L2BlockRef { return eq.engineSyncTarget } @@ -275,16 +284,14 @@ func (eq *EngineQueue) Step(ctx context.Context) error { if err := eq.tryFinalizePastL2Blocks(ctx); err != nil { return err } - if next, err := eq.prev.NextAttributes(ctx, eq.safeHead); err == io.EOF { + if next, err := eq.prev.NextAttributes(ctx, eq.pendingSafeHead); err == io.EOF { outOfData = true } else if err != nil { return err } else { - eq.safeAttributes = &attributesWithParent{ - attributes: next, - parent: eq.safeHead, - } - eq.log.Debug("Adding next safe attributes", "safe_head", eq.safeHead, "next", next) + eq.safeAttributes = next + eq.log.Debug("Adding next safe attributes", "safe_head", eq.safeHead, + "pending_safe_head", eq.pendingSafeHead, "next", next) return NotEnoughData } @@ -411,6 +418,7 @@ func (eq *EngineQueue) logSyncProgress(reason string) { "reason", reason, "l2_finalized", eq.finalized, "l2_safe", eq.safeHead, + "l2_safe_pending", eq.pendingSafeHead, "l2_unsafe", eq.unsafeHead, "l2_engineSyncTarget", eq.engineSyncTarget, "l2_time", eq.unsafeHead.Time, @@ -552,29 +560,30 @@ func (eq *EngineQueue) tryNextSafeAttributes(ctx context.Context) error { return nil } // validate the safe attributes before processing them. The engine may have completed processing them through other means. - if eq.safeHead != eq.safeAttributes.parent { - // Previously the attribute's parent was the safe head. If the safe head advances so safe head's parent is the same as the + if eq.pendingSafeHead != eq.safeAttributes.parent { + // Previously the attribute's parent was the pending safe head. If the pending safe head advances so pending safe head's parent is the same as the // attribute's parent then we need to cancel the attributes. - if eq.safeHead.ParentHash == eq.safeAttributes.parent.Hash { + if eq.pendingSafeHead.ParentHash == eq.safeAttributes.parent.Hash { eq.log.Warn("queued safe attributes are stale, safehead progressed", - "safe_head", eq.safeHead, "safe_head_parent", eq.safeHead.ParentID(), "attributes_parent", eq.safeAttributes.parent) + "pending_safe_head", eq.pendingSafeHead, "pending_safe_head_parent", eq.pendingSafeHead.ParentID(), + "attributes_parent", eq.safeAttributes.parent) eq.safeAttributes = nil return nil } // If something other than a simple advance occurred, perform a full reset - return NewResetError(fmt.Errorf("safe head changed to %s with parent %s, conflicting with queued safe attributes on top of %s", - eq.safeHead, eq.safeHead.ParentID(), eq.safeAttributes.parent)) + return NewResetError(fmt.Errorf("pending safe head changed to %s with parent %s, conflicting with queued safe attributes on top of %s", + eq.pendingSafeHead, eq.pendingSafeHead.ParentID(), eq.safeAttributes.parent)) } - if eq.safeHead.Number < eq.unsafeHead.Number { + if eq.pendingSafeHead.Number < eq.unsafeHead.Number { return eq.consolidateNextSafeAttributes(ctx) - } else if eq.safeHead.Number == eq.unsafeHead.Number { + } else if eq.pendingSafeHead.Number == eq.unsafeHead.Number { return eq.forceNextSafeAttributes(ctx) } else { - // For some reason the unsafe head is behind the safe head. Log it, and correct it. - eq.log.Error("invalid sync state, unsafe head is behind safe head", "unsafe", eq.unsafeHead, "safe", eq.safeHead) - eq.unsafeHead = eq.safeHead - eq.engineSyncTarget = eq.safeHead + // For some reason the unsafe head is behind the pending safe head. Log it, and correct it. + eq.log.Error("invalid sync state, unsafe head is behind pending safe head", "unsafe", eq.unsafeHead, "pending_safe", eq.pendingSafeHead) + eq.unsafeHead = eq.pendingSafeHead + eq.engineSyncTarget = eq.pendingSafeHead eq.metrics.RecordL2Ref("l2_unsafe", eq.unsafeHead) eq.metrics.RecordL2Ref("l2_engineSyncTarget", eq.unsafeHead) return nil @@ -588,7 +597,7 @@ func (eq *EngineQueue) consolidateNextSafeAttributes(ctx context.Context) error ctx, cancel := context.WithTimeout(ctx, time.Second*10) defer cancel() - payload, err := eq.engine.PayloadByNumber(ctx, eq.safeHead.Number+1) + payload, err := eq.engine.PayloadByNumber(ctx, eq.pendingSafeHead.Number+1) if err != nil { if errors.Is(err, ethereum.NotFound) { // engine may have restarted, or inconsistent safe head. We need to reset @@ -596,8 +605,8 @@ func (eq *EngineQueue) consolidateNextSafeAttributes(ctx context.Context) error } return NewTemporaryError(fmt.Errorf("failed to get existing unsafe payload to compare against derived attributes from L1: %w", err)) } - if err := AttributesMatchBlock(eq.safeAttributes.attributes, eq.safeHead.Hash, payload, eq.log); err != nil { - eq.log.Warn("L2 reorg: existing unsafe block does not match derived attributes from L1", "err", err, "unsafe", eq.unsafeHead, "safe", eq.safeHead) + if err := AttributesMatchBlock(eq.safeAttributes.attributes, eq.pendingSafeHead.Hash, payload, eq.log); err != nil { + eq.log.Warn("L2 reorg: existing unsafe block does not match derived attributes from L1", "err", err, "unsafe", eq.unsafeHead, "pending_safe", eq.pendingSafeHead, "safe", eq.safeHead) // geth cannot wind back a chain without reorging to a new, previously non-canonical, block return eq.forceNextSafeAttributes(ctx) } @@ -605,12 +614,15 @@ func (eq *EngineQueue) consolidateNextSafeAttributes(ctx context.Context) error if err != nil { return NewResetError(fmt.Errorf("failed to decode L2 block ref from payload: %w", err)) } - eq.safeHead = ref - eq.needForkchoiceUpdate = true - eq.metrics.RecordL2Ref("l2_safe", ref) + eq.pendingSafeHead = ref + if eq.safeAttributes.isLastInSpan { + eq.safeHead = ref + eq.needForkchoiceUpdate = true + eq.metrics.RecordL2Ref("l2_safe", ref) + eq.postProcessSafeL2() + } // unsafe head stays the same, we did not reorg the chain. eq.safeAttributes = nil - eq.postProcessSafeL2() eq.logSyncProgress("reconciled with L1") return nil @@ -622,7 +634,7 @@ func (eq *EngineQueue) forceNextSafeAttributes(ctx context.Context) error { return nil } attrs := eq.safeAttributes.attributes - errType, err := eq.StartPayload(ctx, eq.safeHead, attrs, true) + errType, err := eq.StartPayload(ctx, eq.pendingSafeHead, attrs, true) if err == nil { _, errType, err = eq.ConfirmPayload(ctx) } @@ -648,11 +660,13 @@ func (eq *EngineQueue) forceNextSafeAttributes(ctx context.Context) error { // block is somehow invalid, there is nothing we can do to recover & we should exit. // TODO: Can this be triggered by an empty batch with invalid data (like parent hash or gas limit?) if len(attrs.Transactions) == depositCount { - eq.log.Error("deposit only block was invalid", "parent", eq.safeHead, "err", err) + eq.log.Error("deposit only block was invalid", "parent", eq.safeAttributes.parent, "err", err) return NewCriticalError(fmt.Errorf("failed to process block with only deposit transactions: %w", err)) } // drop the payload without inserting it eq.safeAttributes = nil + // Revert the pending safe head to the safe head. + eq.pendingSafeHead = eq.safeHead // suppress the error b/c we want to retry with the next batch from the batch queue // If there is no valid batch the node will eventually force a deposit only block. If // the deposit only block fails, this will return the critical error above. @@ -703,7 +717,9 @@ func (eq *EngineQueue) ConfirmPayload(ctx context.Context) (out *eth.ExecutionPa SafeBlockHash: eq.safeHead.Hash, FinalizedBlockHash: eq.finalized.Hash, } - payload, errTyp, err := ConfirmPayload(ctx, eq.log, eq.engine, fc, eq.buildingID, eq.buildingSafe) + // Update the safe head if the payload is built with the last attributes in the batch. + updateSafe := eq.buildingSafe && eq.safeAttributes != nil && eq.safeAttributes.isLastInSpan + payload, errTyp, err := ConfirmPayload(ctx, eq.log, eq.engine, fc, eq.buildingID, updateSafe) if err != nil { return nil, errTyp, fmt.Errorf("failed to complete building on top of L2 chain %s, id: %s, error (%d): %w", eq.buildingOnto, eq.buildingID, errTyp, err) } @@ -718,9 +734,12 @@ func (eq *EngineQueue) ConfirmPayload(ctx context.Context) (out *eth.ExecutionPa eq.metrics.RecordL2Ref("l2_engineSyncTarget", ref) if eq.buildingSafe { - eq.safeHead = ref - eq.postProcessSafeL2() - eq.metrics.RecordL2Ref("l2_safe", ref) + eq.pendingSafeHead = ref + if updateSafe { + eq.safeHead = ref + eq.postProcessSafeL2() + eq.metrics.RecordL2Ref("l2_safe", ref) + } } eq.resetBuildingState() return payload, BlockInsertOK, nil @@ -798,6 +817,7 @@ func (eq *EngineQueue) Reset(ctx context.Context, _ eth.L1BlockRef, _ eth.System eq.unsafeHead = unsafe eq.engineSyncTarget = unsafe eq.safeHead = safe + eq.pendingSafeHead = safe eq.safeAttributes = nil eq.finalized = finalized eq.resetBuildingState() diff --git a/op-node/rollup/derive/engine_queue_test.go b/op-node/rollup/derive/engine_queue_test.go index 654b4fe23c25..e9fbd91b7768 100644 --- a/op-node/rollup/derive/engine_queue_test.go +++ b/op-node/rollup/derive/engine_queue_test.go @@ -23,19 +23,20 @@ import ( ) type fakeAttributesQueue struct { - origin eth.L1BlockRef - attrs *eth.PayloadAttributes + origin eth.L1BlockRef + attrs *eth.PayloadAttributes + islastInSpan bool } func (f *fakeAttributesQueue) Origin() eth.L1BlockRef { return f.origin } -func (f *fakeAttributesQueue) NextAttributes(_ context.Context, _ eth.L2BlockRef) (*eth.PayloadAttributes, error) { +func (f *fakeAttributesQueue) NextAttributes(_ context.Context, safeHead eth.L2BlockRef) (*AttributesWithParent, error) { if f.attrs == nil { return nil, io.EOF } - return f.attrs, nil + return &AttributesWithParent{f.attrs, safeHead, f.islastInSpan}, nil } var _ NextAttributesProvider = (*fakeAttributesQueue)(nil) @@ -909,7 +910,7 @@ func TestBlockBuildingRace(t *testing.T) { GasLimit: &gasLimit, } - prev := &fakeAttributesQueue{origin: refA, attrs: attrs} + prev := &fakeAttributesQueue{origin: refA, attrs: attrs, islastInSpan: true} eq := NewEngineQueue(logger, cfg, eng, metrics, prev, l1F, &sync.Config{}) require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF) @@ -1078,7 +1079,7 @@ func TestResetLoop(t *testing.T) { l1F.ExpectL1BlockRefByHash(refA.Hash, refA, nil) l1F.ExpectL1BlockRefByHash(refA.Hash, refA, nil) - prev := &fakeAttributesQueue{origin: refA, attrs: attrs} + prev := &fakeAttributesQueue{origin: refA, attrs: attrs, islastInSpan: true} eq := NewEngineQueue(logger, cfg, eng, metrics.NoopMetrics, prev, l1F, &sync.Config{}) eq.unsafeHead = refA2 diff --git a/op-node/rollup/derive/params.go b/op-node/rollup/derive/params.go index 469899c3aae5..bba78cc2dfee 100644 --- a/op-node/rollup/derive/params.go +++ b/op-node/rollup/derive/params.go @@ -19,10 +19,10 @@ func frameSize(frame Frame) uint64 { const DerivationVersion0 = 0 -// MaxSpanBatchFieldSize is the maximum amount of bytes that will be read from -// a span batch to decode span batch field. This value cannot be larger than +// MaxSpanBatchSize is the maximum amount of bytes that will be needed +// to decode every span batch field. This value cannot be larger than // MaxRLPBytesPerChannel because single batch cannot be larger than channel size. -const MaxSpanBatchFieldSize = 10_000_000 +const MaxSpanBatchSize = MaxRLPBytesPerChannel // MaxChannelBankSize is the amount of memory space, in number of bytes, // till the bank is pruned by removing channels, diff --git a/op-node/rollup/derive/pipeline.go b/op-node/rollup/derive/pipeline.go index d054939f151d..643dc312cce9 100644 --- a/op-node/rollup/derive/pipeline.go +++ b/op-node/rollup/derive/pipeline.go @@ -51,6 +51,7 @@ type EngineQueueStage interface { Finalized() eth.L2BlockRef UnsafeL2Head() eth.L2BlockRef SafeL2Head() eth.L2BlockRef + PendingSafeL2Head() eth.L2BlockRef EngineSyncTarget() eth.L2BlockRef Origin() eth.L1BlockRef SystemConfig() eth.SystemConfig @@ -148,6 +149,10 @@ func (dp *DerivationPipeline) SafeL2Head() eth.L2BlockRef { return dp.eng.SafeL2Head() } +func (dp *DerivationPipeline) PendingSafeL2Head() eth.L2BlockRef { + return dp.eng.PendingSafeL2Head() +} + // UnsafeL2Head returns the head of the L2 chain that we are deriving for, this may be past what we derived from L1 func (dp *DerivationPipeline) UnsafeL2Head() eth.L2BlockRef { return dp.eng.UnsafeL2Head() diff --git a/op-node/rollup/derive/singular_batch.go b/op-node/rollup/derive/singular_batch.go index 3d37325cd35d..6354dc46ee53 100644 --- a/op-node/rollup/derive/singular_batch.go +++ b/op-node/rollup/derive/singular_batch.go @@ -1,11 +1,15 @@ package derive import ( + "bytes" + "io" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" ) // Batch format @@ -51,3 +55,13 @@ func (b *SingularBatch) LogContext(log log.Logger) log.Logger { func (b *SingularBatch) Epoch() eth.BlockID { return eth.BlockID{Hash: b.EpochHash, Number: uint64(b.EpochNum)} } + +// encode writes the byte encoding of SingularBatch to Writer stream +func (b *SingularBatch) encode(w io.Writer) error { + return rlp.Encode(w, b) +} + +// decode reads the byte encoding of SingularBatch from Reader stream +func (b *SingularBatch) decode(r *bytes.Reader) error { + return rlp.Decode(r, b) +} diff --git a/op-node/rollup/derive/singular_batch_test.go b/op-node/rollup/derive/singular_batch_test.go index bd8d2a562d6f..d6922c86d667 100644 --- a/op-node/rollup/derive/singular_batch_test.go +++ b/op-node/rollup/derive/singular_batch_test.go @@ -5,7 +5,7 @@ import ( "math/rand" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestSingularBatchForBatchInterface(t *testing.T) { @@ -15,7 +15,7 @@ func TestSingularBatchForBatchInterface(t *testing.T) { singularBatch := RandomSingularBatch(rng, txCount, chainID) - assert.Equal(t, SingularBatchType, singularBatch.GetBatchType()) - assert.Equal(t, singularBatch.Timestamp, singularBatch.GetTimestamp()) - assert.Equal(t, singularBatch.EpochNum, singularBatch.GetEpochNum()) + require.Equal(t, SingularBatchType, singularBatch.GetBatchType()) + require.Equal(t, singularBatch.Timestamp, singularBatch.GetTimestamp()) + require.Equal(t, singularBatch.EpochNum, singularBatch.GetEpochNum()) } diff --git a/op-node/rollup/derive/span_batch.go b/op-node/rollup/derive/span_batch.go index 770eb58b7008..e71dd05a5b18 100644 --- a/op-node/rollup/derive/span_batch.go +++ b/op-node/rollup/derive/span_batch.go @@ -9,12 +9,14 @@ import ( "math/big" "sort" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" + + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-service/eth" ) // Batch format @@ -25,15 +27,15 @@ import ( // payload := block_count ++ origin_bits ++ block_tx_counts ++ txs // txs := contract_creation_bits ++ y_parity_bits ++ tx_sigs ++ tx_tos ++ tx_datas ++ tx_nonces ++ tx_gases -var ErrTooBigSpanBatchFieldSize = errors.New("batch would cause field bytes to go over limit") +var ErrTooBigSpanBatchSize = errors.New("span batch size limit reached") var ErrEmptySpanBatch = errors.New("span-batch must not be empty") type spanBatchPrefix struct { - relTimestamp uint64 // Relative timestamp of the first block - l1OriginNum uint64 // L1 origin number - parentCheck []byte // First 20 bytes of the first block's parent hash - l1OriginCheck []byte // First 20 bytes of the last block's L1 origin hash + relTimestamp uint64 // Relative timestamp of the first block + l1OriginNum uint64 // L1 origin number + parentCheck [20]byte // First 20 bytes of the first block's parent hash + l1OriginCheck [20]byte // First 20 bytes of the last block's L1 origin hash } type spanBatchPayload struct { @@ -49,6 +51,11 @@ type RawSpanBatch struct { spanBatchPayload } +// GetBatchType returns its batch type (batch_version) +func (b *RawSpanBatch) GetBatchType() int { + return SpanBatchType +} + // decodeOriginBits parses data into bp.originBits // originBits is bitlist right-padded to a multiple of 8 bits func (bp *spanBatchPayload) decodeOriginBits(r *bytes.Reader) error { @@ -57,8 +64,8 @@ func (bp *spanBatchPayload) decodeOriginBits(r *bytes.Reader) error { originBitBufferLen++ } // avoid out of memory before allocation - if originBitBufferLen > MaxSpanBatchFieldSize { - return ErrTooBigSpanBatchFieldSize + if originBitBufferLen > MaxSpanBatchSize { + return ErrTooBigSpanBatchSize } originBitBuffer := make([]byte, originBitBufferLen) _, err := io.ReadFull(r, originBitBuffer) @@ -103,8 +110,7 @@ func (bp *spanBatchPrefix) decodeL1OriginNum(r *bytes.Reader) error { // decodeParentCheck parses data into bp.parentCheck func (bp *spanBatchPrefix) decodeParentCheck(r *bytes.Reader) error { - bp.parentCheck = make([]byte, 20) - _, err := io.ReadFull(r, bp.parentCheck) + _, err := io.ReadFull(r, bp.parentCheck[:]) if err != nil { return fmt.Errorf("failed to read parent check: %w", err) } @@ -113,8 +119,7 @@ func (bp *spanBatchPrefix) decodeParentCheck(r *bytes.Reader) error { // decodeL1OriginCheck parses data into bp.decodeL1OriginCheck func (bp *spanBatchPrefix) decodeL1OriginCheck(r *bytes.Reader) error { - bp.l1OriginCheck = make([]byte, 20) - _, err := io.ReadFull(r, bp.l1OriginCheck) + _, err := io.ReadFull(r, bp.l1OriginCheck[:]) if err != nil { return fmt.Errorf("failed to read l1 origin check: %w", err) } @@ -144,10 +149,14 @@ func (bp *spanBatchPayload) decodeBlockCount(r *bytes.Reader) error { if err != nil { return fmt.Errorf("failed to read block count: %w", err) } - bp.blockCount = blockCount + // number of L2 block in span batch cannot be greater than MaxSpanBatchSize + if blockCount > MaxSpanBatchSize { + return ErrTooBigSpanBatchSize + } if blockCount == 0 { return ErrEmptySpanBatch } + bp.blockCount = blockCount return nil } @@ -160,6 +169,11 @@ func (bp *spanBatchPayload) decodeBlockTxCounts(r *bytes.Reader) error { if err != nil { return fmt.Errorf("failed to read block tx count: %w", err) } + // number of txs in single L2 block cannot be greater than MaxSpanBatchSize + // every tx will take at least single byte + if blockTxCount > MaxSpanBatchSize { + return ErrTooBigSpanBatchSize + } blockTxCounts = append(blockTxCounts, blockTxCount) } bp.blockTxCounts = blockTxCounts @@ -176,7 +190,15 @@ func (bp *spanBatchPayload) decodeTxs(r *bytes.Reader) error { } totalBlockTxCount := uint64(0) for i := 0; i < len(bp.blockTxCounts); i++ { - totalBlockTxCount += bp.blockTxCounts[i] + total, overflow := math.SafeAdd(totalBlockTxCount, bp.blockTxCounts[i]) + if overflow { + return ErrTooBigSpanBatchSize + } + totalBlockTxCount = total + } + // total number of txs in span batch cannot be greater than MaxSpanBatchSize + if totalBlockTxCount > MaxSpanBatchSize { + return ErrTooBigSpanBatchSize } bp.txs.totalBlockTxCount = totalBlockTxCount if err := bp.txs.decode(r); err != nil { @@ -202,9 +224,11 @@ func (bp *spanBatchPayload) decodePayload(r *bytes.Reader) error { return nil } -// decodeBytes parses data into b from data -func (b *RawSpanBatch) decodeBytes(data []byte) error { - r := bytes.NewReader(data) +// decode reads the byte encoding of SpanBatch from Reader stream +func (b *RawSpanBatch) decode(r *bytes.Reader) error { + if r.Len() > MaxSpanBatchSize { + return ErrTooBigSpanBatchSize + } if err := b.decodePrefix(r); err != nil { return err } @@ -236,7 +260,7 @@ func (bp *spanBatchPrefix) encodeL1OriginNum(w io.Writer) error { // encodeParentCheck encodes bp.parentCheck func (bp *spanBatchPrefix) encodeParentCheck(w io.Writer) error { - if _, err := w.Write(bp.parentCheck); err != nil { + if _, err := w.Write(bp.parentCheck[:]); err != nil { return fmt.Errorf("cannot write parent check: %w", err) } return nil @@ -244,7 +268,7 @@ func (bp *spanBatchPrefix) encodeParentCheck(w io.Writer) error { // encodeL1OriginCheck encodes bp.l1OriginCheck func (bp *spanBatchPrefix) encodeL1OriginCheck(w io.Writer) error { - if _, err := w.Write(bp.l1OriginCheck); err != nil { + if _, err := w.Write(bp.l1OriginCheck[:]); err != nil { return fmt.Errorf("cannot write l1 origin check: %w", err) } return nil @@ -353,17 +377,6 @@ func (b *RawSpanBatch) encode(w io.Writer) error { return nil } -// encodeBytes returns the byte encoding of SpanBatch -func (b *RawSpanBatch) encodeBytes() ([]byte, error) { - buf := encodeBufferPool.Get().(*bytes.Buffer) - defer encodeBufferPool.Put(buf) - buf.Reset() - if err := b.encode(buf); err != nil { - return []byte{}, err - } - return buf.Bytes(), nil -} - // derive converts RawSpanBatch into SpanBatch, which has a list of spanBatchElement. // We need chain config constants to derive values for making payload attributes. func (b *RawSpanBatch) derive(blockTime, genesisTimestamp uint64, chainID *big.Int) (*SpanBatch, error) { @@ -424,8 +437,8 @@ func singularBatchToElement(singularBatch *SingularBatch) *spanBatchElement { // SpanBatch is an implementation of Batch interface, // containing the input to build a span of L2 blocks in derived form (spanBatchElement) type SpanBatch struct { - parentCheck []byte // First 20 bytes of the first block's parent hash - l1OriginCheck []byte // First 20 bytes of the last block's L1 origin hash + parentCheck [20]byte // First 20 bytes of the first block's parent hash + l1OriginCheck [20]byte // First 20 bytes of the last block's L1 origin hash batches []*spanBatchElement // List of block input in derived form } @@ -446,8 +459,8 @@ func (b *SpanBatch) LogContext(log log.Logger) log.Logger { } return log.New( "batch_timestamp", b.batches[0].Timestamp, - "parent_check", hexutil.Encode(b.parentCheck), - "origin_check", hexutil.Encode(b.l1OriginCheck), + "parent_check", hexutil.Encode(b.parentCheck[:]), + "origin_check", hexutil.Encode(b.l1OriginCheck[:]), "start_epoch_number", b.GetStartEpochNum(), "end_epoch_number", b.GetBlockEpochNum(len(b.batches)-1), "block_count", len(b.batches), @@ -461,12 +474,12 @@ func (b *SpanBatch) GetStartEpochNum() rollup.Epoch { // CheckOriginHash checks if the l1OriginCheck matches the first 20 bytes of given hash, probably L1 block hash from the current canonical L1 chain. func (b *SpanBatch) CheckOriginHash(hash common.Hash) bool { - return bytes.Equal(b.l1OriginCheck, hash.Bytes()[:20]) + return bytes.Equal(b.l1OriginCheck[:], hash.Bytes()[:20]) } // CheckParentHash checks if the parentCheck matches the first 20 bytes of given hash, probably the current L2 safe head. func (b *SpanBatch) CheckParentHash(hash common.Hash) bool { - return bytes.Equal(b.parentCheck, hash.Bytes()[:20]) + return bytes.Equal(b.parentCheck[:], hash.Bytes()[:20]) } // GetBlockEpochNum returns the epoch number(L1 origin block number) of the block at the given index in the span. @@ -493,10 +506,10 @@ func (b *SpanBatch) GetBlockCount() int { // updates l1OriginCheck or parentCheck if needed. func (b *SpanBatch) AppendSingularBatch(singularBatch *SingularBatch) { if len(b.batches) == 0 { - b.parentCheck = singularBatch.ParentHash.Bytes()[:20] + copy(b.parentCheck[:], singularBatch.ParentHash.Bytes()[:20]) } b.batches = append(b.batches, singularBatchToElement(singularBatch)) - b.l1OriginCheck = singularBatch.EpochHash.Bytes()[:20] + copy(b.l1OriginCheck[:], singularBatch.EpochHash.Bytes()[:20]) } // ToRawSpanBatch merges SingularBatch List and initialize single RawSpanBatch @@ -514,10 +527,8 @@ func (b *SpanBatch) ToRawSpanBatch(originChangedBit uint, genesisTimestamp uint6 span_end := b.batches[len(b.batches)-1] raw.relTimestamp = span_start.Timestamp - genesisTimestamp raw.l1OriginNum = uint64(span_end.EpochNum) - raw.parentCheck = make([]byte, 20) - copy(raw.parentCheck, b.parentCheck) - raw.l1OriginCheck = make([]byte, 20) - copy(raw.l1OriginCheck, b.l1OriginCheck) + raw.parentCheck = b.parentCheck + raw.l1OriginCheck = b.l1OriginCheck // spanBatchPayload raw.blockCount = uint64(len(b.batches)) raw.originBits = new(big.Int) @@ -581,17 +592,16 @@ func (b *SpanBatch) GetSingularBatches(l1Origins []eth.L1BlockRef, l2SafeHead et // NewSpanBatch converts given singularBatches into spanBatchElements, and creates a new SpanBatch. func NewSpanBatch(singularBatches []*SingularBatch) *SpanBatch { + spanBatch := &SpanBatch{} if len(singularBatches) == 0 { - return &SpanBatch{} - } - spanBatch := SpanBatch{ - parentCheck: singularBatches[0].ParentHash.Bytes()[:20], - l1OriginCheck: singularBatches[len(singularBatches)-1].EpochHash.Bytes()[:20], + return spanBatch } + copy(spanBatch.parentCheck[:], singularBatches[0].ParentHash.Bytes()[:20]) + copy(spanBatch.l1OriginCheck[:], singularBatches[len(singularBatches)-1].EpochHash.Bytes()[:20]) for _, singularBatch := range singularBatches { spanBatch.batches = append(spanBatch.batches, singularBatchToElement(singularBatch)) } - return &spanBatch + return spanBatch } // SpanBatchBuilder is a utility type to build a SpanBatch by adding a SingularBatch one by one. @@ -661,13 +671,13 @@ func ReadTxData(r *bytes.Reader) ([]byte, int, error) { } } // avoid out of memory before allocation - s := rlp.NewStream(r, MaxSpanBatchFieldSize) + s := rlp.NewStream(r, MaxSpanBatchSize) var txPayload []byte kind, _, err := s.Kind() switch { case err != nil: if errors.Is(err, rlp.ErrValueTooLarge) { - return nil, 0, ErrTooBigSpanBatchFieldSize + return nil, 0, ErrTooBigSpanBatchSize } return nil, 0, fmt.Errorf("failed to read tx RLP prefix: %w", err) case kind == rlp.List: diff --git a/op-node/rollup/derive/span_batch_test.go b/op-node/rollup/derive/span_batch_test.go index a4929467ac35..eaa03a8a53d7 100644 --- a/op-node/rollup/derive/span_batch_test.go +++ b/op-node/rollup/derive/span_batch_test.go @@ -2,6 +2,7 @@ package derive import ( "bytes" + "math" "math/big" "math/rand" "testing" @@ -29,11 +30,11 @@ func TestSpanBatchForBatchInterface(t *testing.T) { spanBatch := NewSpanBatch(singularBatches) // check interface method implementations except logging - assert.Equal(t, SpanBatchType, spanBatch.GetBatchType()) - assert.Equal(t, singularBatches[0].Timestamp, spanBatch.GetTimestamp()) - assert.Equal(t, singularBatches[0].EpochNum, spanBatch.GetStartEpochNum()) - assert.True(t, spanBatch.CheckOriginHash(singularBatches[blockCount-1].EpochHash)) - assert.True(t, spanBatch.CheckParentHash(singularBatches[0].ParentHash)) + require.Equal(t, SpanBatchType, spanBatch.GetBatchType()) + require.Equal(t, singularBatches[0].Timestamp, spanBatch.GetTimestamp()) + require.Equal(t, singularBatches[0].EpochNum, spanBatch.GetStartEpochNum()) + require.True(t, spanBatch.CheckOriginHash(singularBatches[blockCount-1].EpochHash)) + require.True(t, spanBatch.CheckParentHash(singularBatches[0].ParentHash)) } func TestEmptySpanBatch(t *testing.T) { @@ -46,8 +47,8 @@ func TestEmptySpanBatch(t *testing.T) { spanBatchPrefix: spanBatchPrefix{ relTimestamp: uint64(rng.Uint32()), l1OriginNum: rng.Uint64(), - parentCheck: testutils.RandomData(rng, 20), - l1OriginCheck: testutils.RandomData(rng, 20), + parentCheck: *(*[20]byte)(testutils.RandomData(rng, 20)), + l1OriginCheck: *(*[20]byte)(testutils.RandomData(rng, 20)), }, spanBatchPayload: spanBatchPayload{ blockCount: 0, @@ -79,23 +80,23 @@ func TestSpanBatchOriginBits(t *testing.T) { var buf bytes.Buffer err := rawSpanBatch.encodeOriginBits(&buf) - assert.NoError(t, err) + require.NoError(t, err) // originBit field is fixed length: single bit originBitBufferLen := blockCount / 8 if blockCount%8 != 0 { originBitBufferLen++ } - assert.Equal(t, buf.Len(), int(originBitBufferLen)) + require.Equal(t, buf.Len(), int(originBitBufferLen)) result := buf.Bytes() var sb RawSpanBatch sb.blockCount = blockCount r := bytes.NewReader(result) err = sb.decodeOriginBits(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, rawSpanBatch.originBits, sb.originBits) + require.Equal(t, rawSpanBatch.originBits, sb.originBits) } func TestSpanBatchPrefix(t *testing.T) { @@ -108,15 +109,15 @@ func TestSpanBatchPrefix(t *testing.T) { var buf bytes.Buffer err := rawSpanBatch.encodePrefix(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() r := bytes.NewReader(result) var sb RawSpanBatch err = sb.decodePrefix(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, rawSpanBatch, &sb) + require.Equal(t, rawSpanBatch, &sb) } func TestSpanBatchRelTimestamp(t *testing.T) { @@ -127,15 +128,15 @@ func TestSpanBatchRelTimestamp(t *testing.T) { var buf bytes.Buffer err := rawSpanBatch.encodeRelTimestamp(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() r := bytes.NewReader(result) var sb RawSpanBatch err = sb.decodeRelTimestamp(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, rawSpanBatch.relTimestamp, sb.relTimestamp) + require.Equal(t, rawSpanBatch.relTimestamp, sb.relTimestamp) } func TestSpanBatchL1OriginNum(t *testing.T) { @@ -146,15 +147,15 @@ func TestSpanBatchL1OriginNum(t *testing.T) { var buf bytes.Buffer err := rawSpanBatch.encodeL1OriginNum(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() r := bytes.NewReader(result) var sb RawSpanBatch err = sb.decodeL1OriginNum(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, rawSpanBatch.l1OriginNum, sb.l1OriginNum) + require.Equal(t, rawSpanBatch.l1OriginNum, sb.l1OriginNum) } func TestSpanBatchParentCheck(t *testing.T) { @@ -165,18 +166,18 @@ func TestSpanBatchParentCheck(t *testing.T) { var buf bytes.Buffer err := rawSpanBatch.encodeParentCheck(&buf) - assert.NoError(t, err) + require.NoError(t, err) // parent check field is fixed length: 20 bytes - assert.Equal(t, buf.Len(), 20) + require.Equal(t, buf.Len(), 20) result := buf.Bytes() r := bytes.NewReader(result) var sb RawSpanBatch err = sb.decodeParentCheck(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, rawSpanBatch.parentCheck, sb.parentCheck) + require.Equal(t, rawSpanBatch.parentCheck, sb.parentCheck) } func TestSpanBatchL1OriginCheck(t *testing.T) { @@ -187,18 +188,18 @@ func TestSpanBatchL1OriginCheck(t *testing.T) { var buf bytes.Buffer err := rawSpanBatch.encodeL1OriginCheck(&buf) - assert.NoError(t, err) + require.NoError(t, err) // l1 origin check field is fixed length: 20 bytes - assert.Equal(t, buf.Len(), 20) + require.Equal(t, buf.Len(), 20) result := buf.Bytes() r := bytes.NewReader(result) var sb RawSpanBatch err = sb.decodeL1OriginCheck(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, rawSpanBatch.l1OriginCheck, sb.l1OriginCheck) + require.Equal(t, rawSpanBatch.l1OriginCheck, sb.l1OriginCheck) } func TestSpanBatchPayload(t *testing.T) { @@ -209,18 +210,18 @@ func TestSpanBatchPayload(t *testing.T) { var buf bytes.Buffer err := rawSpanBatch.encodePayload(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() r := bytes.NewReader(result) var sb RawSpanBatch err = sb.decodePayload(r) - assert.NoError(t, err) + require.NoError(t, err) sb.txs.recoverV(chainID) - assert.Equal(t, rawSpanBatch.spanBatchPayload, sb.spanBatchPayload) + require.Equal(t, rawSpanBatch.spanBatchPayload, sb.spanBatchPayload) } func TestSpanBatchBlockCount(t *testing.T) { @@ -231,16 +232,16 @@ func TestSpanBatchBlockCount(t *testing.T) { var buf bytes.Buffer err := rawSpanBatch.encodeBlockCount(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() r := bytes.NewReader(result) var sb RawSpanBatch err = sb.decodeBlockCount(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, rawSpanBatch.blockCount, sb.blockCount) + require.Equal(t, rawSpanBatch.blockCount, sb.blockCount) } func TestSpanBatchBlockTxCounts(t *testing.T) { @@ -251,7 +252,7 @@ func TestSpanBatchBlockTxCounts(t *testing.T) { var buf bytes.Buffer err := rawSpanBatch.encodeBlockTxCounts(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() r := bytes.NewReader(result) @@ -259,9 +260,9 @@ func TestSpanBatchBlockTxCounts(t *testing.T) { sb.blockCount = rawSpanBatch.blockCount err = sb.decodeBlockTxCounts(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, rawSpanBatch.blockTxCounts, sb.blockTxCounts) + require.Equal(t, rawSpanBatch.blockTxCounts, sb.blockTxCounts) } func TestSpanBatchTxs(t *testing.T) { @@ -272,7 +273,7 @@ func TestSpanBatchTxs(t *testing.T) { var buf bytes.Buffer err := rawSpanBatch.encodeTxs(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() r := bytes.NewReader(result) @@ -280,11 +281,11 @@ func TestSpanBatchTxs(t *testing.T) { sb.blockTxCounts = rawSpanBatch.blockTxCounts err = sb.decodeTxs(r) - assert.NoError(t, err) + require.NoError(t, err) sb.txs.recoverV(chainID) - assert.Equal(t, rawSpanBatch.txs, sb.txs) + require.Equal(t, rawSpanBatch.txs, sb.txs) } func TestSpanBatchRoundTrip(t *testing.T) { @@ -293,16 +294,17 @@ func TestSpanBatchRoundTrip(t *testing.T) { rawSpanBatch := RandomRawSpanBatch(rng, chainID) - result, err := rawSpanBatch.encodeBytes() - assert.NoError(t, err) + var result bytes.Buffer + err := rawSpanBatch.encode(&result) + require.NoError(t, err) var sb RawSpanBatch - err = sb.decodeBytes(result) - assert.NoError(t, err) + err = sb.decode(bytes.NewReader(result.Bytes())) + require.NoError(t, err) sb.txs.recoverV(chainID) - assert.Equal(t, rawSpanBatch, &sb) + require.Equal(t, rawSpanBatch, &sb) } func TestSpanBatchDerive(t *testing.T) { @@ -320,24 +322,24 @@ func TestSpanBatchDerive(t *testing.T) { spanBatch := NewSpanBatch(singularBatches) originChangedBit := uint(originChangedBit) rawSpanBatch, err := spanBatch.ToRawSpanBatch(originChangedBit, genesisTimeStamp, chainID) - assert.NoError(t, err) + require.NoError(t, err) spanBatchDerived, err := rawSpanBatch.derive(l2BlockTime, genesisTimeStamp, chainID) - assert.NoError(t, err) + require.NoError(t, err) blockCount := len(singularBatches) - assert.Equal(t, safeL2Head.Hash.Bytes()[:20], spanBatchDerived.parentCheck) - assert.Equal(t, singularBatches[blockCount-1].Epoch().Hash.Bytes()[:20], spanBatchDerived.l1OriginCheck) - assert.Equal(t, len(singularBatches), int(rawSpanBatch.blockCount)) + require.Equal(t, safeL2Head.Hash.Bytes()[:20], spanBatchDerived.parentCheck[:]) + require.Equal(t, singularBatches[blockCount-1].Epoch().Hash.Bytes()[:20], spanBatchDerived.l1OriginCheck[:]) + require.Equal(t, len(singularBatches), int(rawSpanBatch.blockCount)) for i := 1; i < len(singularBatches); i++ { - assert.Equal(t, spanBatchDerived.batches[i].Timestamp, spanBatchDerived.batches[i-1].Timestamp+l2BlockTime) + require.Equal(t, spanBatchDerived.batches[i].Timestamp, spanBatchDerived.batches[i-1].Timestamp+l2BlockTime) } for i := 0; i < len(singularBatches); i++ { - assert.Equal(t, singularBatches[i].EpochNum, spanBatchDerived.batches[i].EpochNum) - assert.Equal(t, singularBatches[i].Timestamp, spanBatchDerived.batches[i].Timestamp) - assert.Equal(t, singularBatches[i].Transactions, spanBatchDerived.batches[i].Transactions) + require.Equal(t, singularBatches[i].EpochNum, spanBatchDerived.batches[i].EpochNum) + require.Equal(t, singularBatches[i].Timestamp, spanBatchDerived.batches[i].Timestamp) + require.Equal(t, singularBatches[i].Transactions, spanBatchDerived.batches[i].Transactions) } } } @@ -358,7 +360,7 @@ func TestSpanBatchAppend(t *testing.T) { // initialize with two singular batches spanBatch2 := NewSpanBatch(singularBatches[:L]) - assert.Equal(t, spanBatch, spanBatch2) + require.Equal(t, spanBatch, spanBatch2) } func TestSpanBatchMerge(t *testing.T) { @@ -374,32 +376,32 @@ func TestSpanBatchMerge(t *testing.T) { spanBatch := NewSpanBatch(singularBatches) originChangedBit := uint(originChangedBit) rawSpanBatch, err := spanBatch.ToRawSpanBatch(originChangedBit, genesisTimeStamp, chainID) - assert.NoError(t, err) + require.NoError(t, err) // check span batch prefix - assert.Equal(t, rawSpanBatch.relTimestamp, singularBatches[0].Timestamp-genesisTimeStamp, "invalid relative timestamp") - assert.Equal(t, rollup.Epoch(rawSpanBatch.l1OriginNum), singularBatches[blockCount-1].EpochNum) - assert.Equal(t, rawSpanBatch.parentCheck, singularBatches[0].ParentHash.Bytes()[:20], "invalid parent check") - assert.Equal(t, rawSpanBatch.l1OriginCheck, singularBatches[blockCount-1].EpochHash.Bytes()[:20], "invalid l1 origin check") + require.Equal(t, rawSpanBatch.relTimestamp, singularBatches[0].Timestamp-genesisTimeStamp, "invalid relative timestamp") + require.Equal(t, rollup.Epoch(rawSpanBatch.l1OriginNum), singularBatches[blockCount-1].EpochNum) + require.Equal(t, rawSpanBatch.parentCheck[:], singularBatches[0].ParentHash.Bytes()[:20], "invalid parent check") + require.Equal(t, rawSpanBatch.l1OriginCheck[:], singularBatches[blockCount-1].EpochHash.Bytes()[:20], "invalid l1 origin check") // check span batch payload - assert.Equal(t, int(rawSpanBatch.blockCount), len(singularBatches)) - assert.Equal(t, rawSpanBatch.originBits.Bit(0), originChangedBit) + require.Equal(t, int(rawSpanBatch.blockCount), len(singularBatches)) + require.Equal(t, rawSpanBatch.originBits.Bit(0), originChangedBit) for i := 1; i < blockCount; i++ { if rawSpanBatch.originBits.Bit(i) == 1 { - assert.Equal(t, singularBatches[i].EpochNum, singularBatches[i-1].EpochNum+1) + require.Equal(t, singularBatches[i].EpochNum, singularBatches[i-1].EpochNum+1) } else { - assert.Equal(t, singularBatches[i].EpochNum, singularBatches[i-1].EpochNum) + require.Equal(t, singularBatches[i].EpochNum, singularBatches[i-1].EpochNum) } } for i := 0; i < len(singularBatches); i++ { txCount := len(singularBatches[i].Transactions) - assert.Equal(t, txCount, int(rawSpanBatch.blockTxCounts[i])) + require.Equal(t, txCount, int(rawSpanBatch.blockTxCounts[i])) } // check invariants endEpochNum := rawSpanBatch.l1OriginNum - assert.Equal(t, endEpochNum, uint64(singularBatches[blockCount-1].EpochNum)) + require.Equal(t, endEpochNum, uint64(singularBatches[blockCount-1].EpochNum)) // we do not check txs field because it has to be derived to be compared } @@ -419,12 +421,12 @@ func TestSpanBatchToSingularBatch(t *testing.T) { spanBatch := NewSpanBatch(singularBatches) originChangedBit := uint(originChangedBit) rawSpanBatch, err := spanBatch.ToRawSpanBatch(originChangedBit, genesisTimeStamp, chainID) - assert.NoError(t, err) + require.NoError(t, err) l1Origins := mockL1Origin(rng, rawSpanBatch, singularBatches) singularBatches2, err := spanBatch.GetSingularBatches(l1Origins, safeL2Head) - assert.NoError(t, err) + require.NoError(t, err) // GetSingularBatches does not fill in parent hash of singular batches // empty out parent hash for comparison @@ -433,52 +435,54 @@ func TestSpanBatchToSingularBatch(t *testing.T) { } // check parent hash is empty for i := 0; i < len(singularBatches2); i++ { - assert.Equal(t, singularBatches2[i].ParentHash, common.Hash{}) + require.Equal(t, singularBatches2[i].ParentHash, common.Hash{}) } - assert.Equal(t, singularBatches, singularBatches2) + require.Equal(t, singularBatches, singularBatches2) } } func TestSpanBatchReadTxData(t *testing.T) { - rng := rand.New(rand.NewSource(0x109550)) - chainID := new(big.Int).SetUint64(rng.Uint64()) - - txCount := 64 - - signer := types.NewLondonSigner(chainID) - var rawTxs [][]byte - var txs []*types.Transaction - m := make(map[byte]int) - for i := 0; i < txCount; i++ { - tx := testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer) - m[tx.Type()] += 1 - rawTx, err := tx.MarshalBinary() - assert.NoError(t, err) - rawTxs = append(rawTxs, rawTx) - txs = append(txs, tx) + cases := []spanBatchTxTest{ + {"legacy tx", 32, testutils.RandomLegacyTx}, + {"access list tx", 32, testutils.RandomAccessListTx}, + {"dynamic fee tx", 32, testutils.RandomDynamicFeeTx}, } - for i := 0; i < txCount; i++ { - r := bytes.NewReader(rawTxs[i]) - _, txType, err := ReadTxData(r) - assert.NoError(t, err) - assert.Equal(t, int(txs[i].Type()), txType) + for i, testCase := range cases { + t.Run(testCase.name, func(t *testing.T) { + rng := rand.New(rand.NewSource(int64(0x109550 + i))) + chainID := new(big.Int).SetUint64(rng.Uint64()) + signer := types.NewLondonSigner(chainID) + + var rawTxs [][]byte + var txs []*types.Transaction + for txIdx := 0; txIdx < testCase.trials; txIdx++ { + tx := testCase.mkTx(rng, signer) + rawTx, err := tx.MarshalBinary() + require.NoError(t, err) + rawTxs = append(rawTxs, rawTx) + txs = append(txs, tx) + } + + for txIdx := 0; txIdx < testCase.trials; txIdx++ { + r := bytes.NewReader(rawTxs[i]) + _, txType, err := ReadTxData(r) + require.NoError(t, err) + assert.Equal(t, int(txs[i].Type()), txType) + } + }) } - // make sure every tx type is tested - assert.Positive(t, m[types.LegacyTxType]) - assert.Positive(t, m[types.AccessListTxType]) - assert.Positive(t, m[types.DynamicFeeTxType]) } func TestSpanBatchReadTxDataInvalid(t *testing.T) { dummy, err := rlp.EncodeToBytes("dummy") - assert.NoError(t, err) + require.NoError(t, err) // test non list rlp decoding r := bytes.NewReader(dummy) _, _, err = ReadTxData(r) - assert.ErrorContains(t, err, "tx RLP prefix type must be list") + require.ErrorContains(t, err, "tx RLP prefix type must be list") } func TestSpanBatchBuilder(t *testing.T) { @@ -499,28 +503,28 @@ func TestSpanBatchBuilder(t *testing.T) { } spanBatchBuilder := NewSpanBatchBuilder(genesisTimeStamp, chainID) - assert.Equal(t, 0, spanBatchBuilder.GetBlockCount()) + require.Equal(t, 0, spanBatchBuilder.GetBlockCount()) for i := 0; i < len(singularBatches); i++ { spanBatchBuilder.AppendSingularBatch(singularBatches[i], seqNum) - assert.Equal(t, i+1, spanBatchBuilder.GetBlockCount()) - assert.Equal(t, singularBatches[0].ParentHash.Bytes()[:20], spanBatchBuilder.spanBatch.parentCheck) - assert.Equal(t, singularBatches[i].EpochHash.Bytes()[:20], spanBatchBuilder.spanBatch.l1OriginCheck) + require.Equal(t, i+1, spanBatchBuilder.GetBlockCount()) + require.Equal(t, singularBatches[0].ParentHash.Bytes()[:20], spanBatchBuilder.spanBatch.parentCheck[:]) + require.Equal(t, singularBatches[i].EpochHash.Bytes()[:20], spanBatchBuilder.spanBatch.l1OriginCheck[:]) } rawSpanBatch, err := spanBatchBuilder.GetRawSpanBatch() - assert.NoError(t, err) + require.NoError(t, err) // compare with rawSpanBatch not using spanBatchBuilder spanBatch := NewSpanBatch(singularBatches) originChangedBit := uint(originChangedBit) rawSpanBatch2, err := spanBatch.ToRawSpanBatch(originChangedBit, genesisTimeStamp, chainID) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, rawSpanBatch2, rawSpanBatch) + require.Equal(t, rawSpanBatch2, rawSpanBatch) spanBatchBuilder.Reset() - assert.Equal(t, 0, spanBatchBuilder.GetBlockCount()) + require.Equal(t, 0, spanBatchBuilder.GetBlockCount()) } } @@ -528,23 +532,82 @@ func TestSpanBatchMaxTxData(t *testing.T) { rng := rand.New(rand.NewSource(0x177288)) invalidTx := types.NewTx(&types.DynamicFeeTx{ - Data: testutils.RandomData(rng, MaxSpanBatchFieldSize+1), + Data: testutils.RandomData(rng, MaxSpanBatchSize+1), }) txEncoded, err := invalidTx.MarshalBinary() - assert.NoError(t, err) + require.NoError(t, err) r := bytes.NewReader(txEncoded) _, _, err = ReadTxData(r) - assert.ErrorIs(t, err, ErrTooBigSpanBatchFieldSize) + require.ErrorIs(t, err, ErrTooBigSpanBatchSize) } func TestSpanBatchMaxOriginBitsLength(t *testing.T) { var sb RawSpanBatch - sb.blockCount = 0xFFFFFFFFFFFFFFFF + sb.blockCount = math.MaxUint64 r := bytes.NewReader([]byte{}) err := sb.decodeOriginBits(r) - assert.ErrorIs(t, err, ErrTooBigSpanBatchFieldSize) + require.ErrorIs(t, err, ErrTooBigSpanBatchSize) +} + +func TestSpanBatchMaxBlockCount(t *testing.T) { + rng := rand.New(rand.NewSource(0x77556691)) + chainID := big.NewInt(rng.Int63n(1000)) + + rawSpanBatch := RandomRawSpanBatch(rng, chainID) + rawSpanBatch.blockCount = math.MaxUint64 + + var buf bytes.Buffer + err := rawSpanBatch.encodeBlockCount(&buf) + require.NoError(t, err) + + result := buf.Bytes() + r := bytes.NewReader(result) + var sb RawSpanBatch + err = sb.decodeBlockCount(r) + require.ErrorIs(t, err, ErrTooBigSpanBatchSize) +} + +func TestSpanBatchMaxBlockTxCount(t *testing.T) { + rng := rand.New(rand.NewSource(0x77556692)) + chainID := big.NewInt(rng.Int63n(1000)) + + rawSpanBatch := RandomRawSpanBatch(rng, chainID) + rawSpanBatch.blockTxCounts[0] = math.MaxUint64 + + var buf bytes.Buffer + err := rawSpanBatch.encodeBlockTxCounts(&buf) + require.NoError(t, err) + + result := buf.Bytes() + r := bytes.NewReader(result) + var sb RawSpanBatch + sb.blockCount = rawSpanBatch.blockCount + err = sb.decodeBlockTxCounts(r) + require.ErrorIs(t, err, ErrTooBigSpanBatchSize) +} + +func TestSpanBatchTotalBlockTxCountNotOverflow(t *testing.T) { + rng := rand.New(rand.NewSource(0x77556693)) + chainID := big.NewInt(rng.Int63n(1000)) + + rawSpanBatch := RandomRawSpanBatch(rng, chainID) + rawSpanBatch.blockTxCounts[0] = MaxSpanBatchSize - 1 + rawSpanBatch.blockTxCounts[1] = MaxSpanBatchSize - 1 + // we are sure that totalBlockTxCount will overflow on uint64 + + var buf bytes.Buffer + err := rawSpanBatch.encodeBlockTxCounts(&buf) + require.NoError(t, err) + + result := buf.Bytes() + r := bytes.NewReader(result) + var sb RawSpanBatch + sb.blockTxCounts = rawSpanBatch.blockTxCounts + err = sb.decodeTxs(r) + + require.ErrorIs(t, err, ErrTooBigSpanBatchSize) } diff --git a/op-node/rollup/derive/span_batch_tx.go b/op-node/rollup/derive/span_batch_tx.go index c35a95fbc3a6..12628097a3f5 100644 --- a/op-node/rollup/derive/span_batch_tx.go +++ b/op-node/rollup/derive/span_batch_tx.go @@ -4,7 +4,6 @@ import ( "bytes" "errors" "fmt" - "io" "math/big" "github.com/ethereum/go-ethereum/common" @@ -70,21 +69,6 @@ func (tx *spanBatchTx) MarshalBinary() ([]byte, error) { return buf.Bytes(), err } -// EncodeRLP implements rlp.Encoder -func (tx *spanBatchTx) EncodeRLP(w io.Writer) error { - if tx.Type() == types.LegacyTxType { - return rlp.Encode(w, tx.inner) - } - // It's an EIP-2718 typed TX envelope. - buf := encodeBufferPool.Get().(*bytes.Buffer) - defer encodeBufferPool.Put(buf) - buf.Reset() - if err := tx.encodeTyped(buf); err != nil { - return err - } - return rlp.Encode(w, buf.Bytes()) -} - // setDecoded sets the inner transaction after decoding. func (tx *spanBatchTx) setDecoded(inner spanBatchTxData, size uint64) { tx.inner = inner @@ -115,36 +99,6 @@ func (tx *spanBatchTx) decodeTyped(b []byte) (spanBatchTxData, error) { } } -// DecodeRLP implements rlp.Decoder -func (tx *spanBatchTx) DecodeRLP(s *rlp.Stream) error { - kind, size, err := s.Kind() - switch { - case err != nil: - return err - case kind == rlp.List: - // It's a legacy transaction. - var inner spanBatchLegacyTxData - err = s.Decode(&inner) - if err != nil { - return fmt.Errorf("failed to decode spanBatchLegacyTxData: %w", err) - } - tx.setDecoded(&inner, rlp.ListSize(size)) - return nil - default: - // It's an EIP-2718 typed TX envelope. - var b []byte - if b, err = s.Bytes(); err != nil { - return err - } - inner, err := tx.decodeTyped(b) - if err != nil { - return err - } - tx.setDecoded(inner, uint64(len(b))) - return nil - } -} - // UnmarshalBinary decodes the canonical encoding of transactions. // It supports legacy RLP transactions and EIP2718 typed transactions. func (tx *spanBatchTx) UnmarshalBinary(b []byte) error { diff --git a/op-node/rollup/derive/span_batch_tx_test.go b/op-node/rollup/derive/span_batch_tx_test.go index d995e9fb015a..dd50cb6bbbfa 100644 --- a/op-node/rollup/derive/span_batch_tx_test.go +++ b/op-node/rollup/derive/span_batch_tx_test.go @@ -1,103 +1,87 @@ package derive import ( - "bytes" "math/big" "math/rand" "testing" "github.com/ethereum-optimism/optimism/op-service/testutils" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +type spanBatchTxTest struct { + name string + trials int + mkTx func(rng *rand.Rand, signer types.Signer) *types.Transaction +} + func TestSpanBatchTxConvert(t *testing.T) { - rng := rand.New(rand.NewSource(0x1331)) - chainID := big.NewInt(rng.Int63n(1000)) - signer := types.NewLondonSigner(chainID) - - m := make(map[byte]int) - for i := 0; i < 32; i++ { - tx := testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer) - m[tx.Type()] += 1 - v, r, s := tx.RawSignatureValues() - sbtx, err := newSpanBatchTx(*tx) - assert.NoError(t, err) - - tx2, err := sbtx.convertToFullTx(tx.Nonce(), tx.Gas(), tx.To(), chainID, v, r, s) - assert.NoError(t, err) - - // compare after marshal because we only need inner field of transaction - txEncoded, err := tx.MarshalBinary() - assert.NoError(t, err) - tx2Encoded, err := tx2.MarshalBinary() - assert.NoError(t, err) - - assert.Equal(t, txEncoded, tx2Encoded) + cases := []spanBatchTxTest{ + {"legacy tx", 32, testutils.RandomLegacyTx}, + {"access list tx", 32, testutils.RandomAccessListTx}, + {"dynamic fee tx", 32, testutils.RandomDynamicFeeTx}, } - // make sure every tx type is tested - assert.Positive(t, m[types.LegacyTxType]) - assert.Positive(t, m[types.AccessListTxType]) - assert.Positive(t, m[types.DynamicFeeTxType]) -} -func TestSpanBatchTxRoundTrip(t *testing.T) { - rng := rand.New(rand.NewSource(0x1332)) - chainID := big.NewInt(rng.Int63n(1000)) - signer := types.NewLondonSigner(chainID) + for i, testCase := range cases { + t.Run(testCase.name, func(t *testing.T) { + rng := rand.New(rand.NewSource(int64(0x1331 + i))) + chainID := big.NewInt(rng.Int63n(1000)) + signer := types.NewLondonSigner(chainID) - m := make(map[byte]int) - for i := 0; i < 32; i++ { - tx := testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer) - m[tx.Type()] += 1 - sbtx, err := newSpanBatchTx(*tx) - assert.NoError(t, err) + for txIdx := 0; txIdx < testCase.trials; txIdx++ { + tx := testCase.mkTx(rng, signer) - sbtxEncoded, err := sbtx.MarshalBinary() - assert.NoError(t, err) + v, r, s := tx.RawSignatureValues() + sbtx, err := newSpanBatchTx(*tx) + require.NoError(t, err) - var sbtx2 spanBatchTx - err = sbtx2.UnmarshalBinary(sbtxEncoded) - assert.NoError(t, err) + tx2, err := sbtx.convertToFullTx(tx.Nonce(), tx.Gas(), tx.To(), chainID, v, r, s) + require.NoError(t, err) - assert.Equal(t, sbtx, &sbtx2) + // compare after marshal because we only need inner field of transaction + txEncoded, err := tx.MarshalBinary() + require.NoError(t, err) + tx2Encoded, err := tx2.MarshalBinary() + require.NoError(t, err) + + assert.Equal(t, txEncoded, tx2Encoded) + } + }) } - // make sure every tx type is tested - assert.Positive(t, m[types.LegacyTxType]) - assert.Positive(t, m[types.AccessListTxType]) - assert.Positive(t, m[types.DynamicFeeTxType]) } -func TestSpanBatchTxRoundTripRLP(t *testing.T) { - rng := rand.New(rand.NewSource(0x1333)) - chainID := big.NewInt(rng.Int63n(1000)) - signer := types.NewLondonSigner(chainID) - - m := make(map[byte]int) - for i := 0; i < 32; i++ { - tx := testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer) - m[tx.Type()] += 1 - sbtx, err := newSpanBatchTx(*tx) - assert.NoError(t, err) - - var buf bytes.Buffer - err = sbtx.EncodeRLP(&buf) - assert.NoError(t, err) - - result := buf.Bytes() - var sbtx2 spanBatchTx - r := bytes.NewReader(result) - rlpReader := rlp.NewStream(r, 0) - err = sbtx2.DecodeRLP(rlpReader) - assert.NoError(t, err) - - assert.Equal(t, sbtx, &sbtx2) +func TestSpanBatchTxRoundTrip(t *testing.T) { + cases := []spanBatchTxTest{ + {"legacy tx", 32, testutils.RandomLegacyTx}, + {"access list tx", 32, testutils.RandomAccessListTx}, + {"dynamic fee tx", 32, testutils.RandomDynamicFeeTx}, + } + + for i, testCase := range cases { + t.Run(testCase.name, func(t *testing.T) { + rng := rand.New(rand.NewSource(int64(0x1332 + i))) + chainID := big.NewInt(rng.Int63n(1000)) + signer := types.NewLondonSigner(chainID) + + for txIdx := 0; txIdx < testCase.trials; txIdx++ { + tx := testCase.mkTx(rng, signer) + + sbtx, err := newSpanBatchTx(*tx) + require.NoError(t, err) + + sbtxEncoded, err := sbtx.MarshalBinary() + require.NoError(t, err) + + var sbtx2 spanBatchTx + err = sbtx2.UnmarshalBinary(sbtxEncoded) + require.NoError(t, err) + + assert.Equal(t, sbtx, &sbtx2) + } + }) } - // make sure every tx type is tested - assert.Positive(t, m[types.LegacyTxType]) - assert.Positive(t, m[types.AccessListTxType]) - assert.Positive(t, m[types.DynamicFeeTxType]) } type spanBatchDummyTxData struct{} @@ -107,44 +91,44 @@ func TestSpanBatchTxInvalidTxType(t *testing.T) { // span batch never contain deposit tx depositTx := types.NewTx(&types.DepositTx{}) _, err := newSpanBatchTx(*depositTx) - assert.ErrorContains(t, err, "invalid tx type") + require.ErrorContains(t, err, "invalid tx type") var sbtx spanBatchTx sbtx.inner = &spanBatchDummyTxData{} _, err = sbtx.convertToFullTx(0, 0, nil, nil, nil, nil, nil) - assert.ErrorContains(t, err, "invalid tx type") + require.ErrorContains(t, err, "invalid tx type") } func TestSpanBatchTxDecodeInvalid(t *testing.T) { var sbtx spanBatchTx _, err := sbtx.decodeTyped([]byte{}) - assert.EqualError(t, err, "typed transaction too short") + require.EqualError(t, err, "typed transaction too short") tx := types.NewTx(&types.LegacyTx{}) txEncoded, err := tx.MarshalBinary() - assert.NoError(t, err) + require.NoError(t, err) // legacy tx is not typed tx _, err = sbtx.decodeTyped(txEncoded) - assert.EqualError(t, err, types.ErrTxTypeNotSupported.Error()) + require.EqualError(t, err, types.ErrTxTypeNotSupported.Error()) tx2 := types.NewTx(&types.AccessListTx{}) tx2Encoded, err := tx2.MarshalBinary() - assert.NoError(t, err) + require.NoError(t, err) tx2Encoded[0] = types.DynamicFeeTxType _, err = sbtx.decodeTyped(tx2Encoded) - assert.ErrorContains(t, err, "failed to decode spanBatchDynamicFeeTxData") + require.ErrorContains(t, err, "failed to decode spanBatchDynamicFeeTxData") tx3 := types.NewTx(&types.DynamicFeeTx{}) tx3Encoded, err := tx3.MarshalBinary() - assert.NoError(t, err) + require.NoError(t, err) tx3Encoded[0] = types.AccessListTxType _, err = sbtx.decodeTyped(tx3Encoded) - assert.ErrorContains(t, err, "failed to decode spanBatchAccessListTxData") + require.ErrorContains(t, err, "failed to decode spanBatchAccessListTxData") invalidLegacyTxDecoded := []byte{0xFF, 0xFF} err = sbtx.UnmarshalBinary(invalidLegacyTxDecoded) - assert.ErrorContains(t, err, "failed to decode spanBatchLegacyTxData") + require.ErrorContains(t, err, "failed to decode spanBatchLegacyTxData") } diff --git a/op-node/rollup/derive/span_batch_txs.go b/op-node/rollup/derive/span_batch_txs.go index 17dd13262346..4f2fe19b58ed 100644 --- a/op-node/rollup/derive/span_batch_txs.go +++ b/op-node/rollup/derive/span_batch_txs.go @@ -67,8 +67,8 @@ func (btx *spanBatchTxs) decodeContractCreationBits(r *bytes.Reader) error { contractCreationBitBufferLen++ } // avoid out of memory before allocation - if contractCreationBitBufferLen > MaxSpanBatchFieldSize { - return ErrTooBigSpanBatchFieldSize + if contractCreationBitBufferLen > MaxSpanBatchSize { + return ErrTooBigSpanBatchSize } contractCreationBitBuffer := make([]byte, contractCreationBitBufferLen) _, err := io.ReadFull(r, contractCreationBitBuffer) @@ -190,8 +190,8 @@ func (btx *spanBatchTxs) decodeYParityBits(r *bytes.Reader) error { yParityBitBufferLen++ } // avoid out of memory before allocation - if yParityBitBufferLen > MaxSpanBatchFieldSize { - return ErrTooBigSpanBatchFieldSize + if yParityBitBufferLen > MaxSpanBatchSize { + return ErrTooBigSpanBatchSize } yParityBitBuffer := make([]byte, yParityBitBufferLen) _, err := io.ReadFull(r, yParityBitBuffer) diff --git a/op-node/rollup/derive/span_batch_txs_test.go b/op-node/rollup/derive/span_batch_txs_test.go index f393c8df70f4..1fda8b5ffbf3 100644 --- a/op-node/rollup/derive/span_batch_txs_test.go +++ b/op-node/rollup/derive/span_batch_txs_test.go @@ -6,10 +6,12 @@ import ( "math/rand" "testing" - "github.com/ethereum-optimism/optimism/op-service/testutils" - "github.com/ethereum/go-ethereum/core/types" "github.com/holiman/uint256" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/core/types" + + "github.com/ethereum-optimism/optimism/op-service/testutils" ) func TestSpanBatchTxsContractCreationBits(t *testing.T) { @@ -26,23 +28,23 @@ func TestSpanBatchTxsContractCreationBits(t *testing.T) { var buf bytes.Buffer err := sbt.encodeContractCreationBits(&buf) - assert.NoError(t, err) + require.NoError(t, err) // contractCreationBit field is fixed length: single bit contractCreationBitBufferLen := totalBlockTxCount / 8 if totalBlockTxCount%8 != 0 { contractCreationBitBufferLen++ } - assert.Equal(t, buf.Len(), int(contractCreationBitBufferLen)) + require.Equal(t, buf.Len(), int(contractCreationBitBufferLen)) result := buf.Bytes() sbt.contractCreationBits = nil r := bytes.NewReader(result) err = sbt.decodeContractCreationBits(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, contractCreationBits, sbt.contractCreationBits) + require.Equal(t, contractCreationBits, sbt.contractCreationBits) } func TestSpanBatchTxsContractCreationCount(t *testing.T) { @@ -61,16 +63,16 @@ func TestSpanBatchTxsContractCreationCount(t *testing.T) { var buf bytes.Buffer err := sbt.encodeContractCreationBits(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() sbt.contractCreationBits = nil r := bytes.NewReader(result) err = sbt.decodeContractCreationBits(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, contractCreationCount, sbt.contractCreationCount()) + require.Equal(t, contractCreationCount, sbt.contractCreationCount()) } func TestSpanBatchTxsYParityBits(t *testing.T) { @@ -87,23 +89,23 @@ func TestSpanBatchTxsYParityBits(t *testing.T) { var buf bytes.Buffer err := sbt.encodeYParityBits(&buf) - assert.NoError(t, err) + require.NoError(t, err) // yParityBit field is fixed length: single bit yParityBitBufferLen := totalBlockTxCount / 8 if totalBlockTxCount%8 != 0 { yParityBitBufferLen++ } - assert.Equal(t, buf.Len(), int(yParityBitBufferLen)) + require.Equal(t, buf.Len(), int(yParityBitBufferLen)) result := buf.Bytes() sbt.yParityBits = nil r := bytes.NewReader(result) err = sbt.decodeYParityBits(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, yParityBits, sbt.yParityBits) + require.Equal(t, yParityBits, sbt.yParityBits) } func TestSpanBatchTxsTxSigs(t *testing.T) { @@ -120,22 +122,22 @@ func TestSpanBatchTxsTxSigs(t *testing.T) { var buf bytes.Buffer err := sbt.encodeTxSigsRS(&buf) - assert.NoError(t, err) + require.NoError(t, err) // txSig field is fixed length: 32 byte + 32 byte = 64 byte - assert.Equal(t, buf.Len(), 64*int(totalBlockTxCount)) + require.Equal(t, buf.Len(), 64*int(totalBlockTxCount)) result := buf.Bytes() sbt.txSigs = nil r := bytes.NewReader(result) err = sbt.decodeTxSigsRS(r) - assert.NoError(t, err) + require.NoError(t, err) // v field is not set for i := 0; i < int(totalBlockTxCount); i++ { - assert.Equal(t, txSigs[i].r, sbt.txSigs[i].r) - assert.Equal(t, txSigs[i].s, sbt.txSigs[i].s) + require.Equal(t, txSigs[i].r, sbt.txSigs[i].r) + require.Equal(t, txSigs[i].s, sbt.txSigs[i].s) } } @@ -153,16 +155,16 @@ func TestSpanBatchTxsTxNonces(t *testing.T) { var buf bytes.Buffer err := sbt.encodeTxNonces(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() sbt.txNonces = nil r := bytes.NewReader(result) err = sbt.decodeTxNonces(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, txNonces, sbt.txNonces) + require.Equal(t, txNonces, sbt.txNonces) } func TestSpanBatchTxsTxGases(t *testing.T) { @@ -179,16 +181,16 @@ func TestSpanBatchTxsTxGases(t *testing.T) { var buf bytes.Buffer err := sbt.encodeTxGases(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() sbt.txGases = nil r := bytes.NewReader(result) err = sbt.decodeTxGases(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, txGases, sbt.txGases) + require.Equal(t, txGases, sbt.txGases) } func TestSpanBatchTxsTxTos(t *testing.T) { @@ -208,19 +210,19 @@ func TestSpanBatchTxsTxTos(t *testing.T) { var buf bytes.Buffer err := sbt.encodeTxTos(&buf) - assert.NoError(t, err) + require.NoError(t, err) // to field is fixed length: 20 bytes - assert.Equal(t, buf.Len(), 20*len(txTos)) + require.Equal(t, buf.Len(), 20*len(txTos)) result := buf.Bytes() sbt.txTos = nil r := bytes.NewReader(result) err = sbt.decodeTxTos(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, txTos, sbt.txTos) + require.Equal(t, txTos, sbt.txTos) } func TestSpanBatchTxsTxDatas(t *testing.T) { @@ -239,7 +241,7 @@ func TestSpanBatchTxsTxDatas(t *testing.T) { var buf bytes.Buffer err := sbt.encodeTxDatas(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() sbt.txDatas = nil @@ -247,10 +249,10 @@ func TestSpanBatchTxsTxDatas(t *testing.T) { r := bytes.NewReader(result) err = sbt.decodeTxDatas(r) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, txDatas, sbt.txDatas) - assert.Equal(t, txTypes, sbt.txTypes) + require.Equal(t, txDatas, sbt.txDatas) + require.Equal(t, txTypes, sbt.txTypes) } func TestSpanBatchTxsRecoverV(t *testing.T) { @@ -290,7 +292,7 @@ func TestSpanBatchTxsRecoverV(t *testing.T) { recoveredVs = append(recoveredVs, txSig.v) } - assert.Equal(t, originalVs, recoveredVs, "recovered v mismatch") + require.Equal(t, originalVs, recoveredVs, "recovered v mismatch") } func TestSpanBatchTxsRoundTrip(t *testing.T) { @@ -304,7 +306,7 @@ func TestSpanBatchTxsRoundTrip(t *testing.T) { var buf bytes.Buffer err := sbt.encode(&buf) - assert.NoError(t, err) + require.NoError(t, err) result := buf.Bytes() r := bytes.NewReader(result) @@ -312,10 +314,10 @@ func TestSpanBatchTxsRoundTrip(t *testing.T) { var sbt2 spanBatchTxs sbt2.totalBlockTxCount = totalBlockTxCount err = sbt2.decode(r) - assert.NoError(t, err) + require.NoError(t, err) sbt2.recoverV(chainID) - assert.Equal(t, sbt, &sbt2) + require.Equal(t, sbt, &sbt2) } } @@ -330,16 +332,16 @@ func TestSpanBatchTxsRoundTripFullTxs(t *testing.T) { for i := 0; i < int(totalblockTxCounts); i++ { tx := testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer) rawTx, err := tx.MarshalBinary() - assert.NoError(t, err) + require.NoError(t, err) txs = append(txs, rawTx) } sbt, err := newSpanBatchTxs(txs, chainID) - assert.NoError(t, err) + require.NoError(t, err) txs2, err := sbt.fullTxs(chainID) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, txs, txs2) + require.Equal(t, txs, txs2) } } @@ -372,17 +374,17 @@ func TestSpanBatchTxsFullTxNotEnoughTxTos(t *testing.T) { for i := 0; i < int(totalblockTxCounts); i++ { tx := testutils.RandomTx(rng, new(big.Int).SetUint64(rng.Uint64()), signer) rawTx, err := tx.MarshalBinary() - assert.NoError(t, err) + require.NoError(t, err) txs = append(txs, rawTx) } sbt, err := newSpanBatchTxs(txs, chainID) - assert.NoError(t, err) + require.NoError(t, err) // drop single to field sbt.txTos = sbt.txTos[:len(sbt.txTos)-2] _, err = sbt.fullTxs(chainID) - assert.EqualError(t, err, "tx to not enough") + require.EqualError(t, err, "tx to not enough") } func TestSpanBatchTxsMaxContractCreationBitsLength(t *testing.T) { @@ -391,7 +393,7 @@ func TestSpanBatchTxsMaxContractCreationBitsLength(t *testing.T) { r := bytes.NewReader([]byte{}) err := sbt.decodeContractCreationBits(r) - assert.ErrorIs(t, err, ErrTooBigSpanBatchFieldSize) + require.ErrorIs(t, err, ErrTooBigSpanBatchSize) } func TestSpanBatchTxsMaxYParityBitsLength(t *testing.T) { @@ -400,5 +402,5 @@ func TestSpanBatchTxsMaxYParityBitsLength(t *testing.T) { r := bytes.NewReader([]byte{}) err := sb.decodeOriginBits(r) - assert.ErrorIs(t, err, ErrTooBigSpanBatchFieldSize) + require.ErrorIs(t, err, ErrTooBigSpanBatchSize) } diff --git a/op-node/rollup/derive/span_channel_out.go b/op-node/rollup/derive/span_channel_out.go index b509247fb704..a272dfaf5225 100644 --- a/op-node/rollup/derive/span_channel_out.go +++ b/op-node/rollup/derive/span_channel_out.go @@ -106,12 +106,12 @@ func (co *SpanChannelOut) AddSingularBatch(batch *SingularBatch, seqNum uint64) return 0, fmt.Errorf("failed to convert SpanBatch into RawSpanBatch: %w", err) } // Encode RawSpanBatch into bytes - if err = rlp.Encode(&buf, NewSpanBatchData(*rawSpanBatch)); err != nil { + if err = rlp.Encode(&buf, NewBatchData(rawSpanBatch)); err != nil { return 0, fmt.Errorf("failed to encode RawSpanBatch into bytes: %w", err) } // Ensure that the total size of all RLP elements is less than or equal to MAX_RLP_BYTES_PER_CHANNEL if buf.Len() > MaxRLPBytesPerChannel { - return 0, fmt.Errorf("could not add %d bytes to channel of %d bytes, max is %d. err: %w", + return 0, fmt.Errorf("could not take %d bytes as replacement of channel of %d bytes, max is %d. err: %w", buf.Len(), co.rlpLength, MaxRLPBytesPerChannel, ErrTooManyRLPBytes) } co.rlpLength = buf.Len() diff --git a/op-node/rollup/driver/driver.go b/op-node/rollup/driver/driver.go index c41fea100a12..1db8d5dff87e 100644 --- a/op-node/rollup/driver/driver.go +++ b/op-node/rollup/driver/driver.go @@ -60,6 +60,7 @@ type DerivationPipeline interface { Finalized() eth.L2BlockRef SafeL2Head() eth.L2BlockRef UnsafeL2Head() eth.L2BlockRef + PendingSafeL2Head() eth.L2BlockRef Origin() eth.L1BlockRef EngineReady() bool EngineSyncTarget() eth.L2BlockRef diff --git a/op-node/rollup/driver/state.go b/op-node/rollup/driver/state.go index f00712dccedf..2cf6cba478e6 100644 --- a/op-node/rollup/driver/state.go +++ b/op-node/rollup/driver/state.go @@ -485,6 +485,7 @@ func (s *Driver) syncStatus() *eth.SyncStatus { UnsafeL2: s.derivation.UnsafeL2Head(), SafeL2: s.derivation.SafeL2Head(), FinalizedL2: s.derivation.Finalized(), + PendingSafeL2: s.derivation.PendingSafeL2Head(), UnsafeL2SyncTarget: s.derivation.UnsafeL2SyncTarget(), EngineSyncTarget: s.derivation.EngineSyncTarget(), } diff --git a/op-node/service.go b/op-node/service.go index e76bc51a3320..b7179cae263c 100644 --- a/op-node/service.go +++ b/op-node/service.go @@ -197,6 +197,9 @@ func NewDriverConfig(ctx *cli.Context) *driver.Config { func NewRollupConfig(log log.Logger, ctx *cli.Context) (*rollup.Config, error) { network := ctx.String(flags.Network.Name) rollupConfigPath := ctx.String(flags.RollupConfig.Name) + if ctx.Bool(flags.BetaExtraNetworks.Name) { + log.Warn("The beta.extra-networks flag is deprecated and can be omitted safely.") + } if network != "" { if rollupConfigPath != "" { log.Error(`Cannot configure network and rollup-config at the same time. @@ -204,10 +207,6 @@ Startup will proceed to use the network-parameter and ignore the rollup config. Conflicting configuration is deprecated, and will stop the op-node from starting in the future. `, "network", network, "rollup_config", rollupConfigPath) } - // check that the network is available - if !chaincfg.IsAvailableNetwork(network, ctx.Bool(flags.BetaExtraNetworks.Name)) { - return nil, fmt.Errorf("unavailable network: %q", network) - } config, err := chaincfg.GetRollupConfig(network) if err != nil { return nil, err diff --git a/op-program/client/driver/driver.go b/op-program/client/driver/driver.go index 95a3df751f32..5487d8f19fd5 100644 --- a/op-program/client/driver/driver.go +++ b/op-program/client/driver/driver.go @@ -25,13 +25,13 @@ type Derivation interface { type L2Source interface { derive.Engine - L2OutputRoot() (eth.Bytes32, error) + L2OutputRoot(uint64) (eth.Bytes32, error) } type Driver struct { logger log.Logger pipeline Derivation - l2OutputRoot func() (eth.Bytes32, error) + l2OutputRoot func(uint64) (eth.Bytes32, error) targetBlockNum uint64 } @@ -77,8 +77,8 @@ func (d *Driver) SafeHead() eth.L2BlockRef { return d.pipeline.SafeL2Head() } -func (d *Driver) ValidateClaim(claimedOutputRoot eth.Bytes32) error { - outputRoot, err := d.l2OutputRoot() +func (d *Driver) ValidateClaim(l2ClaimBlockNum uint64, claimedOutputRoot eth.Bytes32) error { + outputRoot, err := d.l2OutputRoot(l2ClaimBlockNum) if err != nil { return fmt.Errorf("calculate L2 output root: %w", err) } diff --git a/op-program/client/driver/driver_test.go b/op-program/client/driver/driver_test.go index cc24c696cf84..3262ab7ed986 100644 --- a/op-program/client/driver/driver_test.go +++ b/op-program/client/driver/driver_test.go @@ -73,29 +73,29 @@ func TestValidateClaim(t *testing.T) { t.Run("Valid", func(t *testing.T) { driver := createDriver(t, io.EOF) expected := eth.Bytes32{0x11} - driver.l2OutputRoot = func() (eth.Bytes32, error) { + driver.l2OutputRoot = func(_ uint64) (eth.Bytes32, error) { return expected, nil } - err := driver.ValidateClaim(expected) + err := driver.ValidateClaim(uint64(0), expected) require.NoError(t, err) }) t.Run("Invalid", func(t *testing.T) { driver := createDriver(t, io.EOF) - driver.l2OutputRoot = func() (eth.Bytes32, error) { + driver.l2OutputRoot = func(_ uint64) (eth.Bytes32, error) { return eth.Bytes32{0x22}, nil } - err := driver.ValidateClaim(eth.Bytes32{0x11}) + err := driver.ValidateClaim(uint64(0), eth.Bytes32{0x11}) require.ErrorIs(t, err, ErrClaimNotValid) }) t.Run("Error", func(t *testing.T) { driver := createDriver(t, io.EOF) expectedErr := errors.New("boom") - driver.l2OutputRoot = func() (eth.Bytes32, error) { + driver.l2OutputRoot = func(_ uint64) (eth.Bytes32, error) { return eth.Bytes32{}, expectedErr } - err := driver.ValidateClaim(eth.Bytes32{0x11}) + err := driver.ValidateClaim(uint64(0), eth.Bytes32{0x11}) require.ErrorIs(t, err, expectedErr) }) } diff --git a/op-program/client/l2/engine.go b/op-program/client/l2/engine.go index e6ffadebf470..2bc808e4a78a 100644 --- a/op-program/client/l2/engine.go +++ b/op-program/client/l2/engine.go @@ -34,8 +34,11 @@ func NewOracleEngine(rollupCfg *rollup.Config, logger log.Logger, backend engine } } -func (o *OracleEngine) L2OutputRoot() (eth.Bytes32, error) { - outBlock := o.backend.CurrentHeader() +func (o *OracleEngine) L2OutputRoot(l2ClaimBlockNum uint64) (eth.Bytes32, error) { + outBlock := o.backend.GetHeaderByNumber(l2ClaimBlockNum) + if outBlock == nil { + return eth.Bytes32{}, fmt.Errorf("failed to get L2 block at %d", l2ClaimBlockNum) + } stateDB, err := o.backend.StateAt(outBlock.Root) if err != nil { return eth.Bytes32{}, fmt.Errorf("failed to open L2 state db at block %s: %w", outBlock.Hash(), err) diff --git a/op-program/client/program.go b/op-program/client/program.go index 7d037a7b6ebe..b43950bfb871 100644 --- a/op-program/client/program.go +++ b/op-program/client/program.go @@ -79,7 +79,7 @@ func runDerivation(logger log.Logger, cfg *rollup.Config, l2Cfg *params.ChainCon return err } } - return d.ValidateClaim(eth.Bytes32(l2Claim)) + return d.ValidateClaim(l2ClaimBlockNum, eth.Bytes32(l2Claim)) } func CreateHinterChannel() oppio.FileChannel { diff --git a/op-program/host/cmd/main_test.go b/op-program/host/cmd/main_test.go index 508f6033bc4a..081136af117b 100644 --- a/op-program/host/cmd/main_test.go +++ b/op-program/host/cmd/main_test.go @@ -75,7 +75,7 @@ func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) { func TestNetwork(t *testing.T) { t.Run("Unknown", func(t *testing.T) { - verifyArgsInvalid(t, "unavailable network: \"bar\"", replaceRequiredArg("--network", "bar")) + verifyArgsInvalid(t, "invalid network: \"bar\"", replaceRequiredArg("--network", "bar")) }) t.Run("Required", func(t *testing.T) { diff --git a/op-service/cliapp/lifecycle.go b/op-service/cliapp/lifecycle.go index 3afce92898dc..2154c025645d 100644 --- a/op-service/cliapp/lifecycle.go +++ b/op-service/cliapp/lifecycle.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "os" "github.com/urfave/cli/v2" @@ -30,21 +29,22 @@ type Lifecycle interface { // a shutdown when the Stop context is not expired. type LifecycleAction func(ctx *cli.Context, close context.CancelCauseFunc) (Lifecycle, error) +var interruptErr = errors.New("interrupt signal") + // LifecycleCmd turns a LifecycleAction into an CLI action, // by instrumenting it with CLI context and signal based termination. +// The signals are caught with the opio.BlockFn attached to the context, if any. +// If no block function is provided, it adds default interrupt handling. // The app may continue to run post-processing until fully shutting down. // The user can force an early shut-down during post-processing by sending a second interruption signal. func LifecycleCmd(fn LifecycleAction) cli.ActionFunc { - return lifecycleCmd(fn, opio.BlockOnInterruptsContext) -} - -type waitSignalFn func(ctx context.Context, signals ...os.Signal) - -var interruptErr = errors.New("interrupt signal") - -func lifecycleCmd(fn LifecycleAction, blockOnInterrupt waitSignalFn) cli.ActionFunc { return func(ctx *cli.Context) error { hostCtx := ctx.Context + blockOnInterrupt := opio.BlockerFromContext(hostCtx) + if blockOnInterrupt == nil { // add default interrupt blocker to context if none is set. + hostCtx = opio.WithInterruptBlocker(hostCtx) + blockOnInterrupt = opio.BlockerFromContext(hostCtx) + } appCtx, appCancel := context.WithCancelCause(hostCtx) ctx.Context = appCtx diff --git a/op-service/cliapp/lifecycle_test.go b/op-service/cliapp/lifecycle_test.go index 8cb65ee00d40..1a4002729bb5 100644 --- a/op-service/cliapp/lifecycle_test.go +++ b/op-service/cliapp/lifecycle_test.go @@ -3,12 +3,13 @@ package cliapp import ( "context" "errors" - "os" "testing" "time" "github.com/stretchr/testify/require" "github.com/urfave/cli/v2" + + "github.com/ethereum-optimism/optimism/op-service/opio" ) type fakeLifecycle struct { @@ -77,19 +78,19 @@ func TestLifecycleCmd(t *testing.T) { return app, nil } - // puppeteer a system signal waiter with a test signal channel - fakeSignalWaiter := func(ctx context.Context, signals ...os.Signal) { - select { - case <-ctx.Done(): - case <-signalCh: - } - } - // turn our mock app and system signal into a lifecycle-managed command - actionFn := lifecycleCmd(mockAppFn, fakeSignalWaiter) + actionFn := LifecycleCmd(mockAppFn) // try to shut the test down after being locked more than a minute ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + + // puppeteer system signal interrupts by hooking up the test signal channel as "blocker" for the app to use. + ctx = opio.WithBlocker(ctx, func(ctx context.Context) { + select { + case <-ctx.Done(): + case <-signalCh: + } + }) t.Cleanup(cancel) // create a fake CLI context to run our command with diff --git a/op-service/eth/sync_status.go b/op-service/eth/sync_status.go index 74ac24c12cc0..2217fa9439e3 100644 --- a/op-service/eth/sync_status.go +++ b/op-service/eth/sync_status.go @@ -32,6 +32,8 @@ type SyncStatus struct { // FinalizedL2 points to the L2 block that was derived fully from // finalized L1 information, thus irreversible. FinalizedL2 L2BlockRef `json:"finalized_l2"` + // PendingSafeL2 points to the L2 block processed from the batch, but not consolidated to the safe block yet. + PendingSafeL2 L2BlockRef `json:"pending_safe_l2"` // UnsafeL2SyncTarget points to the first unprocessed unsafe L2 block. // It may be zeroed if there is no targeted block. UnsafeL2SyncTarget L2BlockRef `json:"queued_unsafe_l2"` diff --git a/op-service/opio/interrupts.go b/op-service/opio/interrupts.go index 1b886c6d9001..cd1b8485791d 100644 --- a/op-service/opio/interrupts.go +++ b/op-service/opio/interrupts.go @@ -41,3 +41,74 @@ func BlockOnInterruptsContext(ctx context.Context, signals ...os.Signal) { signal.Stop(interruptChannel) } } + +type interruptContextKeyType struct{} + +var blockerContextKey = interruptContextKeyType{} + +type interruptCatcher struct { + incoming chan os.Signal +} + +// Block blocks until either an interrupt signal is received, or the context is cancelled. +// No error is returned on interrupt. +func (c *interruptCatcher) Block(ctx context.Context) { + select { + case <-c.incoming: + case <-ctx.Done(): + } +} + +// WithInterruptBlocker attaches an interrupt handler to the context, +// which continues to receive signals after every block. +// This helps functions block on individual consecutive interrupts. +func WithInterruptBlocker(ctx context.Context) context.Context { + if ctx.Value(blockerContextKey) != nil { // already has an interrupt handler + return ctx + } + catcher := &interruptCatcher{ + incoming: make(chan os.Signal, 10), + } + signal.Notify(catcher.incoming, DefaultInterruptSignals...) + + return context.WithValue(ctx, blockerContextKey, BlockFn(catcher.Block)) +} + +// WithBlocker overrides the interrupt blocker value, +// e.g. to insert a block-function for testing CLI shutdown without actual process signals. +func WithBlocker(ctx context.Context, fn BlockFn) context.Context { + return context.WithValue(ctx, blockerContextKey, fn) +} + +// BlockFn simply blocks until the implementation of the blocker interrupts it, or till the given context is cancelled. +type BlockFn func(ctx context.Context) + +// BlockerFromContext returns a BlockFn that blocks on interrupts when called. +func BlockerFromContext(ctx context.Context) BlockFn { + v := ctx.Value(blockerContextKey) + if v == nil { + return nil + } + return v.(BlockFn) +} + +// CancelOnInterrupt cancels the given context on interrupt. +// If a BlockFn is attached to the context, this is used as interrupt-blocking. +// If not, then the context blocks on a manually handled interrupt signal. +func CancelOnInterrupt(ctx context.Context) context.Context { + inner, cancel := context.WithCancel(ctx) + + blockOnInterrupt := BlockerFromContext(ctx) + if blockOnInterrupt == nil { + blockOnInterrupt = func(ctx context.Context) { + BlockOnInterruptsContext(ctx) // default signals + } + } + + go func() { + blockOnInterrupt(ctx) + cancel() + }() + + return inner +} diff --git a/op-service/sources/batching.go b/op-service/sources/batching/batching.go similarity index 99% rename from op-service/sources/batching.go rename to op-service/sources/batching/batching.go index 958185ac32bb..0cf88f702704 100644 --- a/op-service/sources/batching.go +++ b/op-service/sources/batching/batching.go @@ -1,4 +1,4 @@ -package sources +package batching import ( "context" diff --git a/op-service/sources/batching_test.go b/op-service/sources/batching/batching_test.go similarity index 99% rename from op-service/sources/batching_test.go rename to op-service/sources/batching/batching_test.go index 4d79e3e1f4e6..c2880dd0c92b 100644 --- a/op-service/sources/batching_test.go +++ b/op-service/sources/batching/batching_test.go @@ -1,4 +1,4 @@ -package sources +package batching import ( "context" diff --git a/op-service/sources/batching/call.go b/op-service/sources/batching/call.go new file mode 100644 index 000000000000..f15c63b2753f --- /dev/null +++ b/op-service/sources/batching/call.go @@ -0,0 +1,119 @@ +package batching + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +type BoundContract struct { + abi *abi.ABI + addr common.Address +} + +func NewBoundContract(abi *abi.ABI, addr common.Address) *BoundContract { + return &BoundContract{ + abi: abi, + addr: addr, + } +} + +func (b *BoundContract) Call(method string, args ...interface{}) *ContractCall { + return NewContractCall(b.abi, b.addr, method, args...) +} + +type ContractCall struct { + Abi *abi.ABI + Addr common.Address + Method string + Args []interface{} +} + +func NewContractCall(abi *abi.ABI, addr common.Address, method string, args ...interface{}) *ContractCall { + return &ContractCall{ + Abi: abi, + Addr: addr, + Method: method, + Args: args, + } +} + +func (c *ContractCall) Pack() ([]byte, error) { + return c.Abi.Pack(c.Method, c.Args...) +} + +func (c *ContractCall) ToCallArgs() (interface{}, error) { + data, err := c.Pack() + if err != nil { + return nil, fmt.Errorf("failed to pack arguments: %w", err) + } + msg := ethereum.CallMsg{ + To: &c.Addr, + Data: data, + } + return toCallArg(msg), nil +} + +func (c *ContractCall) Unpack(hex hexutil.Bytes) (*CallResult, error) { + out, err := c.Abi.Unpack(c.Method, hex) + if err != nil { + return nil, fmt.Errorf("failed to unpack data: %w", err) + } + return &CallResult{out: out}, nil +} + +func toCallArg(msg ethereum.CallMsg) interface{} { + arg := map[string]interface{}{ + "from": msg.From, + "to": msg.To, + } + if len(msg.Data) > 0 { + arg["input"] = hexutil.Bytes(msg.Data) + } + if msg.Value != nil { + arg["value"] = (*hexutil.Big)(msg.Value) + } + if msg.Gas != 0 { + arg["gas"] = hexutil.Uint64(msg.Gas) + } + if msg.GasPrice != nil { + arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice) + } + return arg +} + +type CallResult struct { + out []interface{} +} + +func (c *CallResult) GetUint8(i int) uint8 { + return *abi.ConvertType(c.out[i], new(uint8)).(*uint8) +} + +func (c *CallResult) GetUint32(i int) uint32 { + return *abi.ConvertType(c.out[i], new(uint32)).(*uint32) +} + +func (c *CallResult) GetUint64(i int) uint64 { + return *abi.ConvertType(c.out[i], new(uint64)).(*uint64) +} + +func (c *CallResult) GetBool(i int) bool { + return *abi.ConvertType(c.out[i], new(bool)).(*bool) +} + +func (c *CallResult) GetHash(i int) common.Hash { + return *abi.ConvertType(c.out[i], new([32]byte)).(*[32]byte) +} + +func (c *CallResult) GetAddress(i int) common.Address { + return *abi.ConvertType(c.out[i], new([20]byte)).(*[20]byte) +} + +func (c *CallResult) GetBigInt(i int) *big.Int { + return *abi.ConvertType(c.out[i], new(*big.Int)).(**big.Int) +} diff --git a/op-service/sources/batching/call_test.go b/op-service/sources/batching/call_test.go new file mode 100644 index 000000000000..eaf6fe698845 --- /dev/null +++ b/op-service/sources/batching/call_test.go @@ -0,0 +1,152 @@ +package batching + +import ( + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" +) + +func TestContractCall_ToCallArgs(t *testing.T) { + addr := common.Address{0xbd} + testAbi, err := bindings.ERC20MetaData.GetAbi() + require.NoError(t, err) + call := NewContractCall(testAbi, addr, "approve", common.Address{0xcc}, big.NewInt(1234444)) + args, err := call.ToCallArgs() + require.NoError(t, err) + argMap, ok := args.(map[string]interface{}) + require.True(t, ok) + require.Equal(t, argMap["from"], common.Address{}) + require.Equal(t, argMap["to"], &addr) + expectedData, err := call.Pack() + require.NoError(t, err) + require.Equal(t, argMap["input"], hexutil.Bytes(expectedData)) + + require.NotContains(t, argMap, "value") + require.NotContains(t, argMap, "gas") + require.NotContains(t, argMap, "gasPrice") +} + +func TestContractCall_Pack(t *testing.T) { + addr := common.Address{0xbd} + testAbi, err := bindings.ERC20MetaData.GetAbi() + require.NoError(t, err) + sender := common.Address{0xcc} + amount := big.NewInt(1234444) + call := NewContractCall(testAbi, addr, "approve", sender, amount) + actual, err := call.Pack() + require.NoError(t, err) + + expected, err := testAbi.Pack("approve", sender, amount) + require.NoError(t, err) + require.Equal(t, actual, expected) +} + +func TestContractCall_PackInvalid(t *testing.T) { + addr := common.Address{0xbd} + testAbi, err := bindings.ERC20MetaData.GetAbi() + require.NoError(t, err) + // Second arg should be a *big.Int so packing should fail + call := NewContractCall(testAbi, addr, "approve", common.Address{0xcc}, uint32(123)) + _, err = call.Pack() + require.Error(t, err) +} + +func TestContractCall_Unpack(t *testing.T) { + addr := common.Address{0xbd} + testAbi, err := bindings.ERC20MetaData.GetAbi() + require.NoError(t, err) + call := NewContractCall(testAbi, addr, "balanceOf", common.Address{0xcc}) + outputs := testAbi.Methods["balanceOf"].Outputs + expected := big.NewInt(1234) + packed, err := outputs.Pack(expected) + require.NoError(t, err) + + unpacked, err := call.Unpack(packed) + require.NoError(t, err) + require.Equal(t, unpacked.GetBigInt(0), expected) +} + +func TestContractCall_UnpackInvalid(t *testing.T) { + addr := common.Address{0xbd} + testAbi, err := bindings.ERC20MetaData.GetAbi() + require.NoError(t, err) + call := NewContractCall(testAbi, addr, "balanceOf", common.Address{0xcc}) + + // Input data is the wrong format and won't unpack successfully + inputPacked, err := call.Pack() + require.NoError(t, err) + + _, err = call.Unpack(inputPacked) + require.Error(t, err) +} + +func TestCallResult_GetValues(t *testing.T) { + tests := []struct { + name string + getter func(result *CallResult, i int) interface{} + expected interface{} + }{ + { + name: "GetUint8", + getter: func(result *CallResult, i int) interface{} { + return result.GetUint8(i) + }, + expected: uint8(12), + }, + { + name: "GetUint32", + getter: func(result *CallResult, i int) interface{} { + return result.GetUint32(i) + }, + expected: uint32(12346), + }, + { + name: "GetUint64", + getter: func(result *CallResult, i int) interface{} { + return result.GetUint64(i) + }, + expected: uint64(12346), + }, + { + name: "GetBool", + getter: func(result *CallResult, i int) interface{} { + return result.GetBool(i) + }, + expected: true, + }, + { + name: "GetAddress", + getter: func(result *CallResult, i int) interface{} { + return result.GetAddress(i) + }, + expected: ([20]byte)(common.Address{0xaa, 0xbb, 0xcc}), + }, + { + name: "GetHash", + getter: func(result *CallResult, i int) interface{} { + return result.GetHash(i) + }, + expected: ([32]byte)(common.Hash{0xaa, 0xbb, 0xcc}), + }, + { + name: "GetBigInt", + getter: func(result *CallResult, i int) interface{} { + return result.GetBigInt(i) + }, + expected: big.NewInt(2398423), + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + callResult := &CallResult{[]interface{}{nil, 0, "abc", test.expected, "xyz", 3, nil}} + actual := test.getter(callResult, 3) + require.EqualValues(t, test.expected, actual) + }) + } +} diff --git a/op-service/sources/batching/multicall.go b/op-service/sources/batching/multicall.go new file mode 100644 index 000000000000..79322da1f9b7 --- /dev/null +++ b/op-service/sources/batching/multicall.go @@ -0,0 +1,111 @@ +package batching + +import ( + "context" + "fmt" + "io" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" +) + +var DefaultBatchSize = 100 + +type EthRpc interface { + CallContext(ctx context.Context, out interface{}, method string, args ...interface{}) error + BatchCallContext(ctx context.Context, b []rpc.BatchElem) error +} + +type MultiCaller struct { + rpc EthRpc + batchSize int +} + +func NewMultiCaller(rpc EthRpc, batchSize int) *MultiCaller { + return &MultiCaller{ + rpc: rpc, + batchSize: batchSize, + } +} + +func (m *MultiCaller) SingleCall(ctx context.Context, block Block, call *ContractCall) (*CallResult, error) { + results, err := m.Call(ctx, block, call) + if err != nil { + return nil, err + } + return results[0], nil +} + +func (m *MultiCaller) Call(ctx context.Context, block Block, calls ...*ContractCall) ([]*CallResult, error) { + keys := make([]interface{}, len(calls)) + for i := 0; i < len(calls); i++ { + args, err := calls[i].ToCallArgs() + if err != nil { + return nil, err + } + keys[i] = args + } + fetcher := NewIterativeBatchCall[interface{}, *hexutil.Bytes]( + keys, + func(args interface{}) (*hexutil.Bytes, rpc.BatchElem) { + out := new(hexutil.Bytes) + return out, rpc.BatchElem{ + Method: "eth_call", + Args: []interface{}{args, block.value}, + Result: &out, + } + }, + m.rpc.BatchCallContext, + m.rpc.CallContext, + m.batchSize) + for { + if err := fetcher.Fetch(ctx); err == io.EOF { + break + } else if err != nil { + return nil, fmt.Errorf("failed to fetch claims: %w", err) + } + } + results, err := fetcher.Result() + if err != nil { + return nil, fmt.Errorf("failed to get batch call results: %w", err) + } + + callResults := make([]*CallResult, len(results)) + for i, result := range results { + call := calls[i] + out, err := call.Unpack(*result) + if err != nil { + return nil, fmt.Errorf("failed to unpack result: %w", err) + } + callResults[i] = out + } + return callResults, nil +} + +// Block represents the block ref value in RPC calls. +// It can be either a label (e.g. latest), a block number or block hash. +type Block struct { + value any +} + +func (b Block) ArgValue() any { + return b.value +} + +var ( + BlockPending = Block{"pending"} + BlockLatest = Block{"latest"} + BlockSafe = Block{"safe"} + BlockFinalized = Block{"finalized"} +) + +// BlockByNumber references a canonical block by number. +func BlockByNumber(blockNum uint64) Block { + return Block{rpc.BlockNumber(blockNum)} +} + +// BlockByHash references a block by hash. Canonical or non-canonical blocks may be referenced. +func BlockByHash(hash common.Hash) Block { + return Block{rpc.BlockNumberOrHashWithHash(hash, false)} +} diff --git a/op-service/sources/batching/test/stubs.go b/op-service/sources/batching/test/stubs.go new file mode 100644 index 000000000000..393a8ebe931b --- /dev/null +++ b/op-service/sources/batching/test/stubs.go @@ -0,0 +1,113 @@ +package test + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/exp/slices" +) + +type expectedCall struct { + block batching.Block + args []interface{} + packedArgs []byte + outputs []interface{} +} + +func (e *expectedCall) String() string { + return fmt.Sprintf("{block: %v, args: %v, outputs: %v}", e.block, e.args, e.outputs) +} + +type AbiBasedRpc struct { + t *testing.T + abi *abi.ABI + addr common.Address + + expectedCalls map[string][]*expectedCall +} + +func NewAbiBasedRpc(t *testing.T, contractAbi *abi.ABI, addr common.Address) *AbiBasedRpc { + return &AbiBasedRpc{ + t: t, + abi: contractAbi, + addr: addr, + expectedCalls: make(map[string][]*expectedCall), + } +} + +func (l *AbiBasedRpc) SetResponse(method string, block batching.Block, expected []interface{}, output []interface{}) { + if expected == nil { + expected = []interface{}{} + } + if output == nil { + output = []interface{}{} + } + abiMethod, ok := l.abi.Methods[method] + require.Truef(l.t, ok, "No method: %v", method) + packedArgs, err := abiMethod.Inputs.Pack(expected...) + require.NoErrorf(l.t, err, "Invalid expected arguments for method %v: %v", method, expected) + l.expectedCalls[method] = append(l.expectedCalls[method], &expectedCall{ + block: block, + args: expected, + packedArgs: packedArgs, + outputs: output, + }) +} + +func (l *AbiBasedRpc) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + var errs []error + for _, elem := range b { + elem.Error = l.CallContext(ctx, elem.Result, elem.Method, elem.Args...) + errs = append(errs, elem.Error) + } + return errors.Join(errs...) +} + +func (l *AbiBasedRpc) CallContext(_ context.Context, out interface{}, method string, args ...interface{}) error { + require.Equal(l.t, "eth_call", method) + require.Len(l.t, args, 2) + actualBlockRef := args[1] + callOpts, ok := args[0].(map[string]any) + require.True(l.t, ok) + require.Equal(l.t, &l.addr, callOpts["to"]) + data, ok := callOpts["input"].(hexutil.Bytes) + require.True(l.t, ok) + abiMethod, err := l.abi.MethodById(data[0:4]) + require.NoError(l.t, err) + + argData := data[4:] + args, err = abiMethod.Inputs.Unpack(argData) + require.NoError(l.t, err) + require.Len(l.t, args, len(abiMethod.Inputs)) + + expectedCalls, ok := l.expectedCalls[abiMethod.Name] + require.Truef(l.t, ok, "Unexpected call to %v", abiMethod.Name) + var call *expectedCall + for _, candidate := range expectedCalls { + if slices.Equal(candidate.packedArgs, argData) && assert.ObjectsAreEqualValues(candidate.block.ArgValue(), actualBlockRef) { + call = candidate + break + } + } + require.NotNilf(l.t, call, "No expected calls to %v at block %v with arguments: %v\nExpected calls: %v", abiMethod.Name, actualBlockRef, args, expectedCalls) + + output, err := abiMethod.Outputs.Pack(call.outputs...) + require.NoErrorf(l.t, err, "Invalid outputs for method %v: %v", abiMethod.Name, call.outputs) + + // I admit I do not understand Go reflection. + // So leverage json.Unmarshal to set the out value correctly. + j, err := json.Marshal(hexutil.Bytes(output)) + require.NoError(l.t, err) + require.NoError(l.t, json.Unmarshal(j, out)) + return nil +} diff --git a/op-service/sources/batching/types.go b/op-service/sources/batching/types.go new file mode 100644 index 000000000000..4bd0cc2048d6 --- /dev/null +++ b/op-service/sources/batching/types.go @@ -0,0 +1,11 @@ +package batching + +import ( + "context" + + "github.com/ethereum/go-ethereum/rpc" +) + +type BatchCallContextFn func(ctx context.Context, b []rpc.BatchElem) error + +type CallContextFn func(ctx context.Context, result any, method string, args ...any) error diff --git a/op-service/sources/debug_client.go b/op-service/sources/debug_client.go index db5a782281f1..e9bb2ca579a7 100644 --- a/op-service/sources/debug_client.go +++ b/op-service/sources/debug_client.go @@ -4,16 +4,17 @@ import ( "context" "fmt" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/rawdb" ) type DebugClient struct { - callContext CallContextFn + callContext batching.CallContextFn } -func NewDebugClient(callContext CallContextFn) *DebugClient { +func NewDebugClient(callContext batching.CallContextFn) *DebugClient { return &DebugClient{callContext} } diff --git a/op-service/sources/receipts.go b/op-service/sources/receipts.go index f5520624a7f7..fb40689ce6bf 100644 --- a/op-service/sources/receipts.go +++ b/op-service/sources/receipts.go @@ -6,6 +6,7 @@ import ( "io" "sync" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" @@ -138,9 +139,13 @@ var RPCProviderKinds = []RPCProviderKind{ RPCKindBasic, RPCKindAny, RPCKindStandard, - RPCKindRethDB, } +// Copy of RPCProviderKinds with RethDB added to all RethDB to be used but to hide it from the flags +var validRPCProviderKinds = func() []RPCProviderKind { + return append(RPCProviderKinds, RPCKindRethDB) +}() + func (kind RPCProviderKind) String() string { return string(kind) } @@ -159,7 +164,7 @@ func (kind *RPCProviderKind) Clone() any { } func ValidRPCProviderKind(value RPCProviderKind) bool { - for _, k := range RPCProviderKinds { + for _, k := range validRPCProviderKinds { if k == value { return true } @@ -387,7 +392,7 @@ type receiptsFetchingJob struct { receiptHash common.Hash txHashes []common.Hash - fetcher *IterativeBatchCall[common.Hash, *types.Receipt] + fetcher *batching.IterativeBatchCall[common.Hash, *types.Receipt] // [OPTIONAL] RethDB path to fetch receipts from rethDbPath string @@ -420,7 +425,7 @@ type ReceiptsRequester interface { func (job *receiptsFetchingJob) runFetcher(ctx context.Context) error { if job.fetcher == nil { // start new work - job.fetcher = NewIterativeBatchCall[common.Hash, *types.Receipt]( + job.fetcher = batching.NewIterativeBatchCall[common.Hash, *types.Receipt]( job.txHashes, makeReceiptRequest, job.client.BatchCallContext, diff --git a/op-service/sources/types.go b/op-service/sources/types.go index 2655986bb2ca..7ccf4c3b65c5 100644 --- a/op-service/sources/types.go +++ b/op-service/sources/types.go @@ -1,7 +1,6 @@ package sources import ( - "context" "fmt" "math/big" "strings" @@ -18,10 +17,6 @@ import ( "github.com/ethereum-optimism/optimism/op-service/eth" ) -type BatchCallContextFn func(ctx context.Context, b []rpc.BatchElem) error - -type CallContextFn func(ctx context.Context, result any, method string, args ...any) error - // Note: these types are used, instead of the geth types, to enable: // - batched calls of many block requests (standard bindings do extra uncle-header fetches, cannot be batched nicely) // - ignore uncle data (does not even exist anymore post-Merge) diff --git a/op-service/tasks/tasks.go b/op-service/tasks/tasks.go new file mode 100644 index 000000000000..67675995b2c4 --- /dev/null +++ b/op-service/tasks/tasks.go @@ -0,0 +1,32 @@ +package tasks + +import ( + "fmt" + "runtime/debug" + + "golang.org/x/sync/errgroup" +) + +// Group is a tasks group, which can at any point be awaited to complete. +// Tasks in the group are run in separate go routines. +// If a task panics, the panic is recovered with HandleCrit. +type Group struct { + errGroup errgroup.Group + HandleCrit func(err error) +} + +func (t *Group) Go(fn func() error) { + t.errGroup.Go(func() error { + defer func() { + if err := recover(); err != nil { + debug.PrintStack() + t.HandleCrit(fmt.Errorf("panic: %v", err)) + } + }() + return fn() + }) +} + +func (t *Group) Wait() error { + return t.errGroup.Wait() +} diff --git a/op-service/testutils/random.go b/op-service/testutils/random.go index f2d074aad9a2..234dc1c64211 100644 --- a/op-service/testutils/random.go +++ b/op-service/testutils/random.go @@ -141,49 +141,72 @@ func RandomTo(rng *rand.Rand) *common.Address { } func RandomTx(rng *rand.Rand, baseFee *big.Int, signer types.Signer) *types.Transaction { - gas := params.TxGas + uint64(rng.Int63n(2_000_000)) - key := InsecureRandomKey(rng) - tip := big.NewInt(rng.Int63n(10 * params.GWei)) - txTypeList := []int{types.LegacyTxType, types.AccessListTxType, types.DynamicFeeTxType} txType := txTypeList[rng.Intn(len(txTypeList))] - var txData types.TxData + var tx *types.Transaction switch txType { case types.LegacyTxType: - txData = &types.LegacyTx{ - Nonce: rng.Uint64(), - GasPrice: new(big.Int).SetUint64(rng.Uint64()), - Gas: gas, - To: RandomTo(rng), - Value: RandomETH(rng, 10), - Data: RandomData(rng, rng.Intn(1000)), - } + tx = RandomLegacyTx(rng, signer) case types.AccessListTxType: - txData = &types.AccessListTx{ - ChainID: signer.ChainID(), - Nonce: rng.Uint64(), - GasPrice: new(big.Int).SetUint64(rng.Uint64()), - Gas: gas, - To: RandomTo(rng), - Value: RandomETH(rng, 10), - Data: RandomData(rng, rng.Intn(1000)), - AccessList: nil, - } + tx = RandomAccessListTx(rng, signer) case types.DynamicFeeTxType: - txData = &types.DynamicFeeTx{ - ChainID: signer.ChainID(), - Nonce: rng.Uint64(), - GasTipCap: tip, - GasFeeCap: new(big.Int).Add(baseFee, tip), - Gas: gas, - To: RandomTo(rng), - Value: RandomETH(rng, 10), - Data: RandomData(rng, rng.Intn(1000)), - AccessList: nil, - } + tx = RandomDynamicFeeTxWithBaseFee(rng, baseFee, signer) default: panic("invalid tx type") } + return tx +} + +func RandomLegacyTx(rng *rand.Rand, signer types.Signer) *types.Transaction { + key := InsecureRandomKey(rng) + txData := &types.LegacyTx{ + Nonce: rng.Uint64(), + GasPrice: new(big.Int).SetUint64(rng.Uint64()), + Gas: params.TxGas + uint64(rng.Int63n(2_000_000)), + To: RandomTo(rng), + Value: RandomETH(rng, 10), + Data: RandomData(rng, rng.Intn(1000)), + } + tx, err := types.SignNewTx(key, signer, txData) + if err != nil { + panic(err) + } + return tx +} + +func RandomAccessListTx(rng *rand.Rand, signer types.Signer) *types.Transaction { + key := InsecureRandomKey(rng) + txData := &types.AccessListTx{ + ChainID: signer.ChainID(), + Nonce: rng.Uint64(), + GasPrice: new(big.Int).SetUint64(rng.Uint64()), + Gas: params.TxGas + uint64(rng.Int63n(2_000_000)), + To: RandomTo(rng), + Value: RandomETH(rng, 10), + Data: RandomData(rng, rng.Intn(1000)), + AccessList: nil, + } + tx, err := types.SignNewTx(key, signer, txData) + if err != nil { + panic(err) + } + return tx +} + +func RandomDynamicFeeTxWithBaseFee(rng *rand.Rand, baseFee *big.Int, signer types.Signer) *types.Transaction { + key := InsecureRandomKey(rng) + tip := big.NewInt(rng.Int63n(10 * params.GWei)) + txData := &types.DynamicFeeTx{ + ChainID: signer.ChainID(), + Nonce: rng.Uint64(), + GasTipCap: tip, + GasFeeCap: new(big.Int).Add(baseFee, tip), + Gas: params.TxGas + uint64(rng.Int63n(2_000_000)), + To: RandomTo(rng), + Value: RandomETH(rng, 10), + Data: RandomData(rng, rng.Intn(1000)), + AccessList: nil, + } tx, err := types.SignNewTx(key, signer, txData) if err != nil { panic(err) @@ -191,6 +214,11 @@ func RandomTx(rng *rand.Rand, baseFee *big.Int, signer types.Signer) *types.Tran return tx } +func RandomDynamicFeeTx(rng *rand.Rand, signer types.Signer) *types.Transaction { + baseFee := new(big.Int).SetUint64(rng.Uint64()) + return RandomDynamicFeeTxWithBaseFee(rng, baseFee, signer) +} + func RandomReceipt(rng *rand.Rand, signer types.Signer, tx *types.Transaction, txIndex uint64, cumulativeGasUsed uint64) *types.Receipt { gasUsed := params.TxGas + uint64(rng.Int63n(int64(tx.Gas()-params.TxGas+1))) logs := make([]*types.Log, rng.Intn(10)) @@ -296,6 +324,7 @@ func RandomOutputResponse(rng *rand.Rand) *eth.OutputResponse { UnsafeL2: RandomL2BlockRef(rng), SafeL2: RandomL2BlockRef(rng), FinalizedL2: RandomL2BlockRef(rng), + PendingSafeL2: RandomL2BlockRef(rng), EngineSyncTarget: RandomL2BlockRef(rng), }, } diff --git a/ops/docker/ci-builder/Dockerfile b/ops/docker/ci-builder/Dockerfile index a08ac3f10a80..74979f4f4730 100644 --- a/ops/docker/ci-builder/Dockerfile +++ b/ops/docker/ci-builder/Dockerfile @@ -12,6 +12,9 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh && \ chmod +x ./rustup.sh && \ ./rustup.sh -y +# Install nightly toolchain +RUN source $HOME/.profile && rustup update nightly + RUN source $HOME/.profile && cargo install just RUN source $HOME/.profile && cargo install svm-rs @@ -60,8 +63,12 @@ FROM --platform=linux/amd64 python:3.11.4-slim-bullseye ENV GOPATH=/go ENV PATH=/usr/local/go/bin:$GOPATH/bin:$PATH +ENV PATH=/root/.cargo/bin:$PATH ENV DEBIAN_FRONTEND=noninteractive +# Create rust directories for copying the installation into +RUN mkdir /root/.cargo && mkdir /root/.cargo/bin && mkdir /root/.rustup + # copy the go installation, but not the module cache (cache will get stale, and would add a lot of weight) COPY --from=go-build /usr/local/go /usr/local/go # copy tools @@ -71,11 +78,15 @@ COPY --from=go-build /go/bin/golangci-lint /go/bin/golangci-lint COPY --from=go-build /go/bin/goimports /go/bin/goimports COPY --from=go-build /go/bin/abigen /usr/local/bin/abigen COPY --from=go-build /go/bin/geth /usr/local/bin/geth -COPY --from=rust-build /root/.cargo/bin/svm /usr/local/bin/svm -COPY --from=rust-build /root/.cargo/bin/just /usr/local/bin/just + +# copy the rust installation, alongside the installed toolchains +COPY --from=rust-build /root/.cargo/bin /root/.cargo/bin +COPY --from=rust-build /root/.rustup /root/.rustup +# copy tools COPY --from=rust-build /opt/foundry/target/release/forge /usr/local/bin/forge COPY --from=rust-build /opt/foundry/target/release/cast /usr/local/bin/cast COPY --from=rust-build /opt/foundry/target/release/anvil /usr/local/bin/anvil + COPY --from=echidna-test /usr/local/bin/echidna-test /usr/local/bin/echidna-test COPY .nvmrc .nvmrc @@ -86,7 +97,7 @@ ENV SLITHER_VERSION=0.10.0 # note: python3 package in apt is python 3.9, while base image already has python 3.11 RUN /bin/sh -c set -eux; \ apt-get update; \ - apt-get install -y --no-install-recommends bash curl openssh-client git build-essential ca-certificates jq gnupg binutils-mips-linux-gnu; \ + apt-get install -y --no-install-recommends bash curl openssh-client git build-essential pkg-config libssl-dev clang libclang-dev ca-certificates jq gnupg binutils-mips-linux-gnu; \ mkdir -p /etc/apt/keyrings; \ curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \ echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list; \ diff --git a/package.json b/package.json index 9e7879317dbf..841fdf360a61 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,8 @@ "@types/chai-as-promised": "^7.1.4", "@types/mocha": "^10.0.3", "@types/node": "^20.8.9", - "@typescript-eslint/eslint-plugin": "^6.9.0", - "@typescript-eslint/parser": "^6.9.0", + "@typescript-eslint/eslint-plugin": "^6.9.1", + "@typescript-eslint/parser": "^6.9.1", "chai": "^4.3.10", "depcheck": "^1.4.7", "doctoc": "^2.2.0", @@ -59,7 +59,7 @@ "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-promise": "^5.1.0", "eslint-plugin-react": "^7.24.0", - "eslint-plugin-unicorn": "^48.0.1", + "eslint-plugin-unicorn": "^49.0.0", "husky": "^8.0.3", "lint-staged": "15.0.2", "markdownlint": "^0.31.0", diff --git a/packages/chain-mon/package.json b/packages/chain-mon/package.json index dcd3f4ad8965..19abaad32b49 100644 --- a/packages/chain-mon/package.json +++ b/packages/chain-mon/package.json @@ -59,7 +59,7 @@ "@ethersproject/abstract-provider": "^5.7.0", "@nomiclabs/hardhat-ethers": "^2.2.3", "@nomiclabs/hardhat-waffle": "^2.0.6", - "hardhat": "^2.18.3", + "hardhat": "^2.19.0", "ts-node": "^10.9.1", "tsx": "^3.14.0" } diff --git a/packages/common-ts/package.json b/packages/common-ts/package.json index 72060a89145c..a16362195b7b 100644 --- a/packages/common-ts/package.json +++ b/packages/common-ts/package.json @@ -35,7 +35,7 @@ }, "dependencies": { "@eth-optimism/core-utils": "workspace:*", - "@sentry/node": "^7.75.0", + "@sentry/node": "^7.77.0", "bcfg": "^0.2.1", "body-parser": "^1.20.2", "commander": "^11.1.0", diff --git a/packages/contracts-bedrock/.gas-snapshot b/packages/contracts-bedrock/.gas-snapshot index 6a582cf93762..19fba2a7acbf 100644 --- a/packages/contracts-bedrock/.gas-snapshot +++ b/packages/contracts-bedrock/.gas-snapshot @@ -13,9 +13,9 @@ AssetReceiverTest:test_withdrawETH_succeeds() (gas: 28344) AssetReceiverTest:test_withdrawETH_unauthorized_reverts() (gas: 10680) AssetReceiverTest:test_withdrawETHwithAmount_succeeds() (gas: 28241) AssetReceiverTest:test_withdrawETHwithAmount_unauthorized_reverts() (gas: 10738) -AttestationStationTest:test_attest_bulk_succeeds() (gas: 703749) -AttestationStationTest:test_attest_individual_succeeds() (gas: 632087) -AttestationStationTest:test_attest_single_succeeds() (gas: 651325) +AttestationStationTest:test_attest_bulk_succeeds() (gas: 544387) +AttestationStationTest:test_attest_individual_succeeds() (gas: 472850) +AttestationStationTest:test_attest_single_succeeds() (gas: 491962) BlockOracle_Test:test_checkpointAndLoad_succeeds() (gas: 58396) BlockOracle_Test:test_load_noBlockHash_reverts() (gas: 13681) Bytes_slice_Test:test_slice_acrossMultipleWords_works() (gas: 9413) @@ -26,36 +26,36 @@ Bytes_toNibbles_Test:test_toNibbles_expectedResult128Bytes_works() (gas: 78882) Bytes_toNibbles_Test:test_toNibbles_expectedResult5Bytes_works() (gas: 3992) Bytes_toNibbles_Test:test_toNibbles_zeroLengthInput_works() (gas: 823) Constants_Test:test_eip1967Constants_succeeds() (gas: 453) -CrossDomainMessenger_BaseGas_Test:test_baseGas_succeeds() (gas: 20435) -CrossDomainOwnable2_Test:test_onlyOwner_notMessenger_reverts() (gas: 8461) -CrossDomainOwnable2_Test:test_onlyOwner_notOwner2_reverts() (gas: 57494) -CrossDomainOwnable2_Test:test_onlyOwner_notOwner_reverts() (gas: 16610) -CrossDomainOwnable2_Test:test_onlyOwner_succeeds() (gas: 73522) -CrossDomainOwnable3_Test:test_constructor_succeeds() (gas: 10554) -CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notMessenger_reverts() (gas: 28289) -CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner2_reverts() (gas: 73970) -CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner_reverts() (gas: 32000) -CrossDomainOwnable3_Test:test_crossDomainTransferOwnership_succeeds() (gas: 91527) -CrossDomainOwnable3_Test:test_localOnlyOwner_notOwner_reverts() (gas: 13215) -CrossDomainOwnable3_Test:test_localOnlyOwner_succeeds() (gas: 35242) -CrossDomainOwnable3_Test:test_localTransferOwnership_succeeds() (gas: 52084) -CrossDomainOwnable3_Test:test_transferOwnershipNoLocal_succeeds() (gas: 48610) -CrossDomainOwnable3_Test:test_transferOwnership_noLocalZeroAddress_reverts() (gas: 12037) -CrossDomainOwnable3_Test:test_transferOwnership_notOwner_reverts() (gas: 13437) -CrossDomainOwnable3_Test:test_transferOwnership_zeroAddress_reverts() (gas: 12081) -CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 81417) +CrossDomainMessenger_BaseGas_Test:test_baseGas_succeeds() (gas: 20481) +CrossDomainOwnable2_Test:test_onlyOwner_notMessenger_reverts() (gas: 8539) +CrossDomainOwnable2_Test:test_onlyOwner_notOwner2_reverts() (gas: 57515) +CrossDomainOwnable2_Test:test_onlyOwner_notOwner_reverts() (gas: 16655) +CrossDomainOwnable2_Test:test_onlyOwner_succeeds() (gas: 73622) +CrossDomainOwnable3_Test:test_constructor_succeeds() (gas: 10627) +CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notMessenger_reverts() (gas: 28363) +CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner2_reverts() (gas: 73999) +CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner_reverts() (gas: 32096) +CrossDomainOwnable3_Test:test_crossDomainTransferOwnership_succeeds() (gas: 91603) +CrossDomainOwnable3_Test:test_localOnlyOwner_notOwner_reverts() (gas: 13260) +CrossDomainOwnable3_Test:test_localOnlyOwner_succeeds() (gas: 35271) +CrossDomainOwnable3_Test:test_localTransferOwnership_succeeds() (gas: 52164) +CrossDomainOwnable3_Test:test_transferOwnershipNoLocal_succeeds() (gas: 48712) +CrossDomainOwnable3_Test:test_transferOwnership_noLocalZeroAddress_reverts() (gas: 12090) +CrossDomainOwnable3_Test:test_transferOwnership_notOwner_reverts() (gas: 13460) +CrossDomainOwnable3_Test:test_transferOwnership_zeroAddress_reverts() (gas: 12177) +CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 81556) CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597) CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34883) -DelayedVetoable_Getters_Test:test_getters() (gas: 24466) -DelayedVetoable_Getters_TestFail:test_getters_notZeroAddress_reverts() (gas: 36220) -DelayedVetoable_HandleCall_TestFail:test_handleCall_unauthorizedInitiation_reverts() (gas: 21867) +DelayedVetoable_Getters_Test:test_getters() (gas: 24620) +DelayedVetoable_Getters_TestFail:test_getters_notZeroAddress_reverts() (gas: 36289) +DelayedVetoable_HandleCall_TestFail:test_handleCall_unauthorizedInitiation_reverts() (gas: 15165) DeployerWhitelist_Test:test_owner_succeeds() (gas: 7582) DeployerWhitelist_Test:test_storageSlots_succeeds() (gas: 33395) -DisputeGameFactory_Owner_Test:test_owner_succeeds() (gas: 12581) -DisputeGameFactory_SetImplementation_Test:test_setImplementation_notOwner_reverts() (gas: 16042) -DisputeGameFactory_SetImplementation_Test:test_setImplementation_succeeds() (gas: 44301) -DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15950) -DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18642) +DisputeGameFactory_Owner_Test:test_owner_succeeds() (gas: 12611) +DisputeGameFactory_SetImplementation_Test:test_setImplementation_notOwner_reverts() (gas: 16078) +DisputeGameFactory_SetImplementation_Test:test_setImplementation_succeeds() (gas: 44323) +DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15974) +DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18738) Drippie_Test:test_create_calledTwice_reverts() (gas: 168953) Drippie_Test:test_create_succeeds() (gas: 183401) Drippie_Test:test_drip_amount_succeeds() (gas: 285353) @@ -89,221 +89,219 @@ FaucetTest:test_nonAdmin_drip_fails() (gas: 262520) FaucetTest:test_receive_succeeds() (gas: 17401) FaucetTest:test_withdraw_nonAdmin_reverts() (gas: 13145) FaucetTest:test_withdraw_succeeds() (gas: 78359) -FaultDisputeGame_ResolvesCorrectly_CorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 660000) -FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 666860) -FaultDisputeGame_ResolvesCorrectly_CorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 663563) -FaultDisputeGame_ResolvesCorrectly_CorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 666736) -FaultDisputeGame_ResolvesCorrectly_CorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 666049) -FaultDisputeGame_ResolvesCorrectly_IncorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 652764) -FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 658252) -FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 655614) -FaultDisputeGame_ResolvesCorrectly_IncorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 656552) -FaultDisputeGame_ResolvesCorrectly_IncorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 656003) -FaultDisputeGame_Test:test_addLocalData_static_succeeds() (gas: 642642) -FaultDisputeGame_Test:test_createdAt_succeeds() (gas: 10409) -FaultDisputeGame_Test:test_extraData_succeeds() (gas: 32328) -FaultDisputeGame_Test:test_gameData_succeeds() (gas: 32777) -FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8265) -FaultDisputeGame_Test:test_initialize_correctData_succeeds() (gas: 57646) -FaultDisputeGame_Test:test_initialize_firstOutput_reverts() (gas: 210650) -FaultDisputeGame_Test:test_initialize_l1HeadTooOld_reverts() (gas: 228466) -FaultDisputeGame_Test:test_move_clockCorrectness_succeeds() (gas: 594025) -FaultDisputeGame_Test:test_move_clockTimeExceeded_reverts() (gas: 23175) -FaultDisputeGame_Test:test_move_defendRoot_reverts() (gas: 13300) -FaultDisputeGame_Test:test_move_duplicateClaim_reverts() (gas: 147367) -FaultDisputeGame_Test:test_move_duplicateClaimsDifferentSubgames_succeeds() (gas: 556831) -FaultDisputeGame_Test:test_move_gameDepthExceeded_reverts() (gas: 585853) -FaultDisputeGame_Test:test_move_gameNotInProgress_reverts() (gas: 10980) -FaultDisputeGame_Test:test_move_nonExistentParent_reverts() (gas: 24644) -FaultDisputeGame_Test:test_move_simpleAttack_succeeds() (gas: 151915) -FaultDisputeGame_Test:test_resolve_challengeContested_succeeds() (gas: 269432) -FaultDisputeGame_Test:test_resolve_claimAlreadyResolved_reverts() (gas: 272334) -FaultDisputeGame_Test:test_resolve_claimAtMaxDepthAlreadyResolved_reverts() (gas: 586606) -FaultDisputeGame_Test:test_resolve_notInProgress_reverts() (gas: 9754) -FaultDisputeGame_Test:test_resolve_outOfOrderResolution_reverts() (gas: 309015) -FaultDisputeGame_Test:test_resolve_rootContested_succeeds() (gas: 139090) -FaultDisputeGame_Test:test_resolve_rootUncontestedButUnresolved_reverts() (gas: 15884) -FaultDisputeGame_Test:test_resolve_rootUncontestedClockNotExpired_succeeds() (gas: 18428) -FaultDisputeGame_Test:test_resolve_rootUncontested_succeeds() (gas: 51410) -FaultDisputeGame_Test:test_resolve_stepReached_succeeds() (gas: 498406) -FaultDisputeGame_Test:test_resolve_teamDeathmatch_succeeds() (gas: 443357) -FaultDisputeGame_Test:test_rootClaim_succeeds() (gas: 8232) -FeeVault_Test:test_constructor_succeeds() (gas: 18185) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 354421) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2952628) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 542325) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4054518) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 443561) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3489288) -GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 42714) -GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 90658) -GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 75076) -GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 75697) -GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 143181) -GasPriceOracle_Test:test_baseFee_succeeds() (gas: 8325) -GasPriceOracle_Test:test_decimals_succeeds() (gas: 6167) -GasPriceOracle_Test:test_gasPrice_succeeds() (gas: 8294) -GasPriceOracle_Test:test_l1BaseFee_succeeds() (gas: 10656) -GasPriceOracle_Test:test_overhead_succeeds() (gas: 10636) -GasPriceOracle_Test:test_scalar_succeeds() (gas: 10677) -GasPriceOracle_Test:test_setGasPrice_doesNotExist_reverts() (gas: 5910) -GasPriceOracle_Test:test_setL1BaseFee_doesNotExist_reverts() (gas: 5911) -GovernanceToken_Test:test_approve_succeeds() (gas: 133293) -GovernanceToken_Test:test_burnFrom_succeeds() (gas: 122733) -GovernanceToken_Test:test_burn_succeeds() (gas: 114588) -GovernanceToken_Test:test_constructor_succeeds() (gas: 21298) -GovernanceToken_Test:test_decreaseAllowance_succeeds() (gas: 137008) -GovernanceToken_Test:test_increaseAllowance_succeeds() (gas: 137118) -GovernanceToken_Test:test_mint_fromNotOwner_reverts() (gas: 17030) -GovernanceToken_Test:test_mint_fromOwner_succeeds() (gas: 108592) -GovernanceToken_Test:test_transferFrom_succeeds() (gas: 146273) -GovernanceToken_Test:test_transfer_succeeds() (gas: 138108) -Hashing_hashDepositSource_Test:test_hashDepositSource_succeeds() (gas: 633) -Initializer_Test:test_cannotReinitializeL1_succeeds() (gas: 98390) +FaultDisputeGame_ResolvesCorrectly_CorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 660030) +FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 666890) +FaultDisputeGame_ResolvesCorrectly_CorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 663593) +FaultDisputeGame_ResolvesCorrectly_CorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 666766) +FaultDisputeGame_ResolvesCorrectly_CorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 666079) +FaultDisputeGame_ResolvesCorrectly_IncorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 652788) +FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 658276) +FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 655638) +FaultDisputeGame_ResolvesCorrectly_IncorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 656576) +FaultDisputeGame_ResolvesCorrectly_IncorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 656027) +FaultDisputeGame_Test:test_addLocalData_static_succeeds() (gas: 642441) +FaultDisputeGame_Test:test_createdAt_succeeds() (gas: 10476) +FaultDisputeGame_Test:test_extraData_succeeds() (gas: 32422) +FaultDisputeGame_Test:test_gameData_succeeds() (gas: 32857) +FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8302) +FaultDisputeGame_Test:test_initialize_correctData_succeeds() (gas: 57779) +FaultDisputeGame_Test:test_initialize_firstOutput_reverts() (gas: 213868) +FaultDisputeGame_Test:test_initialize_l1HeadTooOld_reverts() (gas: 228488) +FaultDisputeGame_Test:test_move_clockCorrectness_succeeds() (gas: 594294) +FaultDisputeGame_Test:test_move_clockTimeExceeded_reverts() (gas: 23200) +FaultDisputeGame_Test:test_move_defendRoot_reverts() (gas: 13325) +FaultDisputeGame_Test:test_move_duplicateClaim_reverts() (gas: 147396) +FaultDisputeGame_Test:test_move_duplicateClaimsDifferentSubgames_succeeds() (gas: 556844) +FaultDisputeGame_Test:test_move_gameDepthExceeded_reverts() (gas: 585884) +FaultDisputeGame_Test:test_move_gameNotInProgress_reverts() (gas: 11019) +FaultDisputeGame_Test:test_move_nonExistentParent_reverts() (gas: 24674) +FaultDisputeGame_Test:test_move_simpleAttack_succeeds() (gas: 152017) +FaultDisputeGame_Test:test_resolve_challengeContested_succeeds() (gas: 269483) +FaultDisputeGame_Test:test_resolve_claimAlreadyResolved_reverts() (gas: 272368) +FaultDisputeGame_Test:test_resolve_claimAtMaxDepthAlreadyResolved_reverts() (gas: 586621) +FaultDisputeGame_Test:test_resolve_notInProgress_reverts() (gas: 9785) +FaultDisputeGame_Test:test_resolve_outOfOrderResolution_reverts() (gas: 309002) +FaultDisputeGame_Test:test_resolve_rootContested_succeeds() (gas: 139125) +FaultDisputeGame_Test:test_resolve_rootUncontestedButUnresolved_reverts() (gas: 15923) +FaultDisputeGame_Test:test_resolve_rootUncontestedClockNotExpired_succeeds() (gas: 18431) +FaultDisputeGame_Test:test_resolve_rootUncontested_succeeds() (gas: 51487) +FaultDisputeGame_Test:test_resolve_stepReached_succeeds() (gas: 498467) +FaultDisputeGame_Test:test_resolve_teamDeathmatch_succeeds() (gas: 443413) +FaultDisputeGame_Test:test_rootClaim_succeeds() (gas: 8247) +FeeVault_Test:test_constructor_baseFeeVault_succeeds() (gas: 17450) +FeeVault_Test:test_constructor_l1FeeVault_succeeds() (gas: 17418) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 354446) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2952696) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 544949) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4057119) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 446183) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3491910) +GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 45337) +GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 88797) +GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68320) +GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68973) +GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 143307) +GasPriceOracle_Test:test_baseFee_succeeds() (gas: 8348) +GasPriceOracle_Test:test_decimals_succeeds() (gas: 6234) +GasPriceOracle_Test:test_gasPrice_succeeds() (gas: 8340) +GasPriceOracle_Test:test_l1BaseFee_succeeds() (gas: 10680) +GasPriceOracle_Test:test_overhead_succeeds() (gas: 10637) +GasPriceOracle_Test:test_scalar_succeeds() (gas: 10700) +GasPriceOracle_Test:test_setGasPrice_doesNotExist_reverts() (gas: 5956) +GasPriceOracle_Test:test_setL1BaseFee_doesNotExist_reverts() (gas: 5976) +GovernanceToken_Test:test_approve_succeeds() (gas: 138001) +GovernanceToken_Test:test_burnFrom_succeeds() (gas: 127582) +GovernanceToken_Test:test_burn_succeeds() (gas: 119092) +GovernanceToken_Test:test_constructor_succeeds() (gas: 23693) +GovernanceToken_Test:test_decreaseAllowance_succeeds() (gas: 141912) +GovernanceToken_Test:test_increaseAllowance_succeeds() (gas: 142022) +GovernanceToken_Test:test_mint_fromNotOwner_reverts() (gas: 21378) +GovernanceToken_Test:test_mint_fromOwner_succeeds() (gas: 110940) +GovernanceToken_Test:test_transferFrom_succeeds() (gas: 151340) +GovernanceToken_Test:test_transfer_succeeds() (gas: 142867) +Hashing_hashDepositSource_Test:test_hashDepositSource_succeeds() (gas: 700) +Initializer_Test:test_cannotReinitializeL1_succeeds() (gas: 101030) L1BlockNumberTest:test_fallback_succeeds() (gas: 18655) L1BlockNumberTest:test_getL1BlockNumber_succeeds() (gas: 10625) L1BlockNumberTest:test_receive_succeeds() (gas: 25384) -L1BlockTest:test_basefee_succeeds() (gas: 7554) -L1BlockTest:test_hash_succeeds() (gas: 7576) -L1BlockTest:test_number_succeeds() (gas: 7629) -L1BlockTest:test_sequenceNumber_succeeds() (gas: 7630) -L1BlockTest:test_timestamp_succeeds() (gas: 7640) -L1BlockTest:test_updateValues_succeeds() (gas: 60482) -L1CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 24781) -L1CrossDomainMessenger_Test:test_relayMessage_legacyOldReplay_reverts() (gas: 49384) -L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() (gas: 212329) -L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailure_succeeds() (gas: 206087) -L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterSuccess_reverts() (gas: 126344) -L1CrossDomainMessenger_Test:test_relayMessage_legacy_succeeds() (gas: 79599) -L1CrossDomainMessenger_Test:test_relayMessage_retryAfterFailure_succeeds() (gas: 200127) -L1CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 76590) -L1CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 60779) -L1CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 12343) -L1CrossDomainMessenger_Test:test_replayMessage_withValue_reverts() (gas: 33133) -L1CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 392933) -L1CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 1669172) -L1CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 87853) -L1CrossDomainMessenger_Test:test_xDomainSender_notSet_reverts() (gas: 24253) -L1ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 62686) -L1ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 37285) -L1ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 455269) -L1ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 70997) -L1ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 35681) -L1ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 60561) -L1ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 35204) -L1ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 454966) -L1ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 70823) -L1ERC721Bridge_Test:test_constructor_succeeds() (gas: 18861) -L1ERC721Bridge_Test:test_finalizeBridgeERC721_notEscrowed_reverts() (gas: 29475) -L1ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 27220) -L1ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 23241) -L1ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 24990) -L1ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 425245) -L1StandardBridge_BridgeETHTo_Test:test_bridgeETHTo_succeeds() (gas: 514756) -L1StandardBridge_BridgeETH_Test:test_bridgeETH_succeeds() (gas: 501934) -L1StandardBridge_DepositERC20To_Test:test_depositERC20To_succeeds() (gas: 720272) -L1StandardBridge_DepositERC20_Test:test_depositERC20_succeeds() (gas: 717849) -L1StandardBridge_DepositERC20_TestFail:test_depositERC20_notEoa_reverts() (gas: 22276) -L1StandardBridge_DepositETHTo_Test:test_depositETHTo_succeeds() (gas: 514789) -L1StandardBridge_DepositETH_Test:test_depositETH_succeeds() (gas: 502006) -L1StandardBridge_DepositETH_TestFail:test_depositETH_notEoa_reverts() (gas: 40759) -L1StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 54102) -L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 36551) -L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 36738) -L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 36623) -L1StandardBridge_FinalizeERC20Withdrawal_Test:test_finalizeERC20Withdrawal_succeeds() (gas: 498144) -L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notMessenger_reverts() (gas: 33452) -L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notOtherBridge_reverts() (gas: 34118) -L1StandardBridge_FinalizeETHWithdrawal_Test:test_finalizeETHWithdrawal_succeeds() (gas: 64673) -L1StandardBridge_Getter_Test:test_getters_succeeds() (gas: 28383) -L1StandardBridge_Initialize_Test:test_initialize_succeeds() (gas: 27239) -L1StandardBridge_Receive_Test:test_receive_succeeds() (gas: 615130) -L2CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 8477) -L2CrossDomainMessenger_Test:test_relayMessage_retry_succeeds() (gas: 163749) -L2CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 48913) -L2CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 31136) -L2CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 11689) -L2CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 123957) -L2CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 135812) -L2CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 49230) -L2CrossDomainMessenger_Test:test_xDomainSender_senderNotSet_reverts() (gas: 10590) -L2ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 31453) -L2ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 26854) -L2ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 157156) -L2ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 34489) -L2ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 27183) -L2ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 29305) -L2ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 24641) -L2ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 154746) -L2ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 34271) -L2ERC721Bridge_Test:test_constructor_succeeds() (gas: 21004) -L2ERC721Bridge_Test:test_finalizeBridgeERC721_alreadyExists_reverts() (gas: 38661) -L2ERC721Bridge_Test:test_finalizeBridgeERC721_interfaceNotCompliant_reverts() (gas: 246925) -L2ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 27208) -L2ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 23274) -L2ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 27124) -L2ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 179976) -L2OutputOracleUpgradeable_Test:test_initValuesOnImpl_succeeds() (gas: 23902) -L2OutputOracleUpgradeable_Test:test_initValuesOnProxy_succeeds() (gas: 46800) -L2OutputOracleUpgradeable_Test:test_initializeImpl_alreadyInitialized_reverts() (gas: 15216) -L2OutputOracleUpgradeable_Test:test_initializeProxy_alreadyInitialized_reverts() (gas: 20216) -L2OutputOracleUpgradeable_Test:test_upgrading_succeeds() (gas: 187875) -L2OutputOracle_constructor_Test:test_constructor_l2BlockTimeZero_reverts() (gas: 39022) -L2OutputOracle_constructor_Test:test_constructor_submissionInterval_reverts() (gas: 39032) -L2OutputOracle_constructor_Test:test_constructor_succeeds() (gas: 51777) -L2OutputOracle_constructor_Test:test_initialize_badTimestamp_reverts() (gas: 12353) -L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_afterLatest_reverts() (gas: 217031) -L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_finalized_reverts() (gas: 113258) -L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_ifNotChallenger_reverts() (gas: 21018) -L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_nonExistent_reverts() (gas: 111651) -L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_multipleOutputs_succeeds() (gas: 307411) -L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_singleOutput_succeeds() (gas: 185564) -L2OutputOracle_getter_Test:test_computeL2Timestamp_succeeds() (gas: 38198) -L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() (gas: 269700) -L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_noOutputsExis_reverts() (gas: 17892) -L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_previousBlock_succeeds() (gas: 98188) -L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_sameBlock_succeeds() (gas: 98096) -L2OutputOracle_getter_Test:test_getL2Output_succeeds() (gas: 104600) -L2OutputOracle_getter_Test:test_latestBlockNumber_succeeds() (gas: 99129) -L2OutputOracle_getter_Test:test_nextBlockNumber_succeeds() (gas: 17447) -L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_emptyOutput_reverts() (gas: 28812) -L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_futureTimetamp_reverts() (gas: 30792) -L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_notProposer_reverts() (gas: 27928) -L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_proposeAnotherOutput_succeeds() (gas: 103242) -L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unexpectedBlockNumber_reverts() (gas: 30526) -L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unmatchedBlockhash_reverts() (gas: 31526) -L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_wrongFork_reverts() (gas: 31129) -L2OutputOracle_proposeL2Output_Test:test_proposeWithBlockhashAndHeight_succeeds() (gas: 97442) -L2StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 392297) -L2StandardBridge_BridgeERC20To_Test:test_withdrawTo_withdrawingERC20_succeeds() (gas: 392530) -L2StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 387821) -L2StandardBridge_BridgeERC20_Test:test_bridgeLegacyERC20_succeeds() (gas: 396094) -L2StandardBridge_BridgeERC20_Test:test_withdrawLegacyERC20_succeeds() (gas: 396456) -L2StandardBridge_BridgeERC20_Test:test_withdraw_notEOA_reverts() (gas: 251807) -L2StandardBridge_BridgeERC20_Test:test_withdraw_withdrawingERC20_succeeds() (gas: 388103) -L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 26132) -L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 26400) -L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 26159) -L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingERC20_succeeds() (gas: 96091) -L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingETH_succeeds() (gas: 94945) -L2StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 45528) -L2StandardBridge_Test:test_initialize_succeeds() (gas: 26316) -L2StandardBridge_Test:test_receive_succeeds() (gas: 177125) -L2StandardBridge_Test:test_withdraw_ether_succeeds() (gas: 143366) -L2StandardBridge_Test:test_withdraw_insufficientValue_reverts() (gas: 16552) -L2ToL1MessagePasserTest:test_burn_succeeds() (gas: 112530) -L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract_succeeds() (gas: 70343) -L2ToL1MessagePasserTest:test_initiateWithdrawal_fromEOA_succeeds() (gas: 75830) -LegacyERC20ETH_Test:test_approve_doesNotExist_reverts() (gas: 10702) -LegacyERC20ETH_Test:test_burn_doesNotExist_reverts() (gas: 10637) -LegacyERC20ETH_Test:test_crossDomain_succeeds() (gas: 6341) -LegacyERC20ETH_Test:test_decreaseAllowance_doesNotExist_reverts() (gas: 10724) -LegacyERC20ETH_Test:test_increaseAllowance_doesNotExist_reverts() (gas: 10690) -LegacyERC20ETH_Test:test_metadata_succeeds() (gas: 15476) -LegacyERC20ETH_Test:test_mint_doesNotExist_reverts() (gas: 10627) -LegacyERC20ETH_Test:test_transferFrom_doesNotExist_reverts() (gas: 12957) -LegacyERC20ETH_Test:test_transfer_doesNotExist_reverts() (gas: 10755) -LegacyMessagePasser_Test:test_passMessageToL1_succeeds() (gas: 34524) +L1BlockTest:test_basefee_succeeds() (gas: 7599) +L1BlockTest:test_hash_succeeds() (gas: 7694) +L1BlockTest:test_number_succeeds() (gas: 7674) +L1BlockTest:test_sequenceNumber_succeeds() (gas: 7676) +L1BlockTest:test_timestamp_succeeds() (gas: 7663) +L1BlockTest:test_updateValues_succeeds() (gas: 63327) +L1CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 24803) +L1CrossDomainMessenger_Test:test_relayMessage_legacyOldReplay_reverts() (gas: 49407) +L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() (gas: 239750) +L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailure_succeeds() (gas: 233442) +L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterSuccess_reverts() (gas: 126347) +L1CrossDomainMessenger_Test:test_relayMessage_legacy_succeeds() (gas: 79600) +L1CrossDomainMessenger_Test:test_relayMessage_retryAfterFailure_succeeds() (gas: 227460) +L1CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 76636) +L1CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 60799) +L1CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 12410) +L1CrossDomainMessenger_Test:test_replayMessage_withValue_reverts() (gas: 33134) +L1CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 392934) +L1CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 1669270) +L1CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 87957) +L1CrossDomainMessenger_Test:test_xDomainSender_notSet_reverts() (gas: 24282) +L1ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 62759) +L1ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 37333) +L1ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 455270) +L1ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 71022) +L1ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 35752) +L1ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 60611) +L1ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 35188) +L1ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 455010) +L1ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 70870) +L1ERC721Bridge_Test:test_constructor_succeeds() (gas: 18883) +L1ERC721Bridge_Test:test_finalizeBridgeERC721_notEscrowed_reverts() (gas: 29495) +L1ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 27261) +L1ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 23305) +L1ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 25035) +L1ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 425309) +L1StandardBridge_BridgeETHTo_Test:test_bridgeETHTo_succeeds() (gas: 517214) +L1StandardBridge_BridgeETH_Test:test_bridgeETH_succeeds() (gas: 504458) +L1StandardBridge_DepositERC20To_Test:test_depositERC20To_succeeds() (gas: 723450) +L1StandardBridge_DepositERC20_Test:test_depositERC20_succeeds() (gas: 720986) +L1StandardBridge_DepositERC20_TestFail:test_depositERC20_notEoa_reverts() (gas: 24955) +L1StandardBridge_DepositETHTo_Test:test_depositETHTo_succeeds() (gas: 517311) +L1StandardBridge_DepositETH_Test:test_depositETH_succeeds() (gas: 504597) +L1StandardBridge_DepositETH_TestFail:test_depositETH_notEoa_reverts() (gas: 43427) +L1StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 57849) +L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 40320) +L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 40461) +L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 40347) +L1StandardBridge_FinalizeERC20Withdrawal_Test:test_finalizeERC20Withdrawal_succeeds() (gas: 503457) +L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notMessenger_reverts() (gas: 37182) +L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notOtherBridge_reverts() (gas: 37871) +L1StandardBridge_FinalizeETHWithdrawal_Test:test_finalizeETHWithdrawal_succeeds() (gas: 70062) +L1StandardBridge_Getter_Test:test_getters_succeeds() (gas: 32693) +L1StandardBridge_Initialize_Test:test_initialize_succeeds() (gas: 30372) +L1StandardBridge_Receive_Test:test_receive_succeeds() (gas: 617691) +L2CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 8521) +L2CrossDomainMessenger_Test:test_relayMessage_retry_succeeds() (gas: 191101) +L2CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 48936) +L2CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 31159) +L2CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 11756) +L2CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 124025) +L2CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 135887) +L2CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 49311) +L2CrossDomainMessenger_Test:test_xDomainSender_senderNotSet_reverts() (gas: 10686) +L2ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 26498) +L2ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 21814) +L2ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 152123) +L2ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 29494) +L2ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 22193) +L2ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 24354) +L2ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 19651) +L2ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 149786) +L2ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 29326) +L2ERC721Bridge_Test:test_constructor_succeeds() (gas: 14682) +L2ERC721Bridge_Test:test_finalizeBridgeERC721_alreadyExists_reverts() (gas: 33650) +L2ERC721Bridge_Test:test_finalizeBridgeERC721_interfaceNotCompliant_reverts() (gas: 241375) +L2ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 22215) +L2ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 18282) +L2ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 22113) +L2ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 174514) +L2OutputOracleUpgradeable_Test:test_initValuesOnImpl_succeeds() (gas: 32635) +L2OutputOracleUpgradeable_Test:test_initValuesOnProxy_succeeds() (gas: 56666) +L2OutputOracleUpgradeable_Test:test_initializeImpl_alreadyInitialized_reverts() (gas: 24782) +L2OutputOracleUpgradeable_Test:test_initializeProxy_alreadyInitialized_reverts() (gas: 26380) +L2OutputOracleUpgradeable_Test:test_upgrading_succeeds() (gas: 191207) +L2OutputOracle_constructor_Test:test_constructor_l2BlockTimeZero_reverts() (gas: 44322) +L2OutputOracle_constructor_Test:test_constructor_submissionInterval_reverts() (gas: 44354) +L2OutputOracle_constructor_Test:test_constructor_succeeds() (gas: 61399) +L2OutputOracle_constructor_Test:test_initialize_badTimestamp_reverts() (gas: 12433) +L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_afterLatest_reverts() (gas: 226802) +L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_finalized_reverts() (gas: 118576) +L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_ifNotChallenger_reverts() (gas: 21053) +L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_nonExistent_reverts() (gas: 117047) +L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_multipleOutputs_succeeds() (gas: 318177) +L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_singleOutput_succeeds() (gas: 193280) +L2OutputOracle_getter_Test:test_computeL2Timestamp_succeeds() (gas: 44553) +L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() (gas: 277454) +L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_noOutputsExis_reverts() (gas: 17937) +L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_previousBlock_succeeds() (gas: 103541) +L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_sameBlock_succeeds() (gas: 103449) +L2OutputOracle_getter_Test:test_getL2Output_succeeds() (gas: 109931) +L2OutputOracle_getter_Test:test_latestBlockNumber_succeeds() (gas: 104504) +L2OutputOracle_getter_Test:test_nextBlockNumber_succeeds() (gas: 17492) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_emptyOutput_reverts() (gas: 34188) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_futureTimetamp_reverts() (gas: 34217) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_notProposer_reverts() (gas: 26076) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_proposeAnotherOutput_succeeds() (gas: 109345) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unexpectedBlockNumber_reverts() (gas: 33945) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unmatchedBlockhash_reverts() (gas: 34968) +L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_wrongFork_reverts() (gas: 34466) +L2OutputOracle_proposeL2Output_Test:test_proposeWithBlockhashAndHeight_succeeds() (gas: 100845) +L2StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 392327) +L2StandardBridge_BridgeERC20To_Test:test_withdrawTo_withdrawingERC20_succeeds() (gas: 392577) +L2StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 387960) +L2StandardBridge_BridgeERC20_Test:test_bridgeLegacyERC20_succeeds() (gas: 396237) +L2StandardBridge_BridgeERC20_Test:test_withdrawLegacyERC20_succeeds() (gas: 396580) +L2StandardBridge_BridgeERC20_Test:test_withdraw_notEOA_reverts() (gas: 251901) +L2StandardBridge_BridgeERC20_Test:test_withdraw_withdrawingERC20_succeeds() (gas: 388241) +L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 26200) +L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 26422) +L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 26227) +L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingERC20_succeeds() (gas: 96126) +L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingETH_succeeds() (gas: 95023) +L2StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 45610) +L2StandardBridge_Test:test_initialize_succeeds() (gas: 28894) +L2StandardBridge_Test:test_receive_succeeds() (gas: 177147) +L2StandardBridge_Test:test_withdraw_ether_succeeds() (gas: 143411) +L2StandardBridge_Test:test_withdraw_insufficientValue_reverts() (gas: 16586) +LegacyERC20ETH_Test:test_approve_doesNotExist_reverts() (gas: 10745) +LegacyERC20ETH_Test:test_burn_doesNotExist_reverts() (gas: 10705) +LegacyERC20ETH_Test:test_crossDomain_succeeds() (gas: 6400) +LegacyERC20ETH_Test:test_decreaseAllowance_doesNotExist_reverts() (gas: 10747) +LegacyERC20ETH_Test:test_increaseAllowance_doesNotExist_reverts() (gas: 10757) +LegacyERC20ETH_Test:test_metadata_succeeds() (gas: 15795) +LegacyERC20ETH_Test:test_mint_doesNotExist_reverts() (gas: 10672) +LegacyERC20ETH_Test:test_transferFrom_doesNotExist_reverts() (gas: 12980) +LegacyERC20ETH_Test:test_transfer_doesNotExist_reverts() (gas: 10801) +LegacyMessagePasser_Test:test_passMessageToL1_succeeds() (gas: 34629) LibPosition_Test:test_pos_correctness_succeeds() (gas: 38689) LivenessGuard_CheckAfterExecution_TestFails:test_checkAfterExecution_callerIsNotSafe_revert() (gas: 8531) LivenessGuard_CheckTx_Test:test_checkTransaction_succeeds() (gas: 233535) @@ -311,8 +309,8 @@ LivenessGuard_CheckTx_TestFails:test_checkTransaction_callerIsNotSafe_revert() ( LivenessGuard_Constructor_Test:test_constructor_works() (gas: 1198965) LivenessGuard_Getters_Test:test_getters_works() (gas: 10662) LivenessGuard_OwnerManagement_Test:test_addOwner_succeeds() (gas: 274366) -LivenessGuard_OwnerManagement_Test:test_removeOwner_succeeds() (gas: 246263) -LivenessGuard_OwnerManagement_Test:test_swapOwner_succeeds() (gas: 284880) +LivenessGuard_OwnerManagement_Test:test_removeOwner_succeeds() (gas: 243684) +LivenessGuard_OwnerManagement_Test:test_swapOwner_succeeds() (gas: 282299) LivenessGuard_ShowLiveness_Test:test_showLiveness_succeeds() (gas: 28831) LivenessGuard_ShowLiveness_TestFail:test_showLiveness_callIsNotSafeOwner_reverts() (gas: 18770) LivenessModule_CanRemove_Test:test_canRemove_works() (gas: 33026) @@ -321,92 +319,92 @@ LivenessModule_Constructor_TestFail:test_constructor_minOwnersGreaterThanOwners_ LivenessModule_Constructor_TestFail:test_constructor_wrongThreshold_reverts() (gas: 92925) LivenessModule_Get75PercentThreshold_Test:test_get75PercentThreshold_Works() (gas: 26339) LivenessModule_Getters_Test:test_getters_works() (gas: 14853) -LivenessModule_RemoveOwners_Test:test_removeOwners_allOwners_succeeds() (gas: 1326177) -LivenessModule_RemoveOwners_Test:test_removeOwners_oneOwner_succeeds() (gas: 133975) -LivenessModule_RemoveOwners_TestFail:test_removeOwners_belowEmptiedButNotShutDown_reverts() (gas: 1278643) -LivenessModule_RemoveOwners_TestFail:test_removeOwners_belowMinButNotEmptied_reverts() (gas: 1281685) +LivenessModule_RemoveOwners_Test:test_removeOwners_allOwners_succeeds() (gas: 1316393) +LivenessModule_RemoveOwners_Test:test_removeOwners_oneOwner_succeeds() (gas: 130750) +LivenessModule_RemoveOwners_TestFail:test_removeOwners_belowEmptiedButNotShutDown_reverts() (gas: 1269598) +LivenessModule_RemoveOwners_TestFail:test_removeOwners_belowMinButNotEmptied_reverts() (gas: 1273409) LivenessModule_RemoveOwners_TestFail:test_removeOwners_differentArrayLengths_reverts() (gas: 10502) -LivenessModule_RemoveOwners_TestFail:test_removeOwners_guardChanged_reverts() (gas: 2839358) +LivenessModule_RemoveOwners_TestFail:test_removeOwners_guardChanged_reverts() (gas: 2836129) LivenessModule_RemoveOwners_TestFail:test_removeOwners_invalidThreshold_reverts() (gas: 69358) -LivenessModule_RemoveOwners_TestFail:test_removeOwners_ownerHasShownLivenessRecently_reverts() (gas: 80971) -LivenessModule_RemoveOwners_TestFail:test_removeOwners_ownerHasSignedRecently_reverts() (gas: 617629) -LivenessModule_RemoveOwners_TestFail:test_removeOwners_swapToFallbackOwner_reverts() (gas: 1288036) +LivenessModule_RemoveOwners_TestFail:test_removeOwners_ownerHasShownLivenessRecently_reverts() (gas: 77749) +LivenessModule_RemoveOwners_TestFail:test_removeOwners_ownerHasSignedRecently_reverts() (gas: 615047) +LivenessModule_RemoveOwners_TestFail:test_removeOwners_swapToFallbackOwner_reverts() (gas: 1278252) LivenessModule_RemoveOwners_TestFail:test_removeOwners_wrongPreviousOwner_reverts() (gas: 73954) -MIPS_Test:test_add_succeeds() (gas: 122932) -MIPS_Test:test_addiSign_succeeds() (gas: 122923) -MIPS_Test:test_addi_succeeds() (gas: 123120) -MIPS_Test:test_addu_succeeds() (gas: 122974) -MIPS_Test:test_addui_succeeds() (gas: 123182) -MIPS_Test:test_and_succeeds() (gas: 122993) -MIPS_Test:test_andi_succeeds() (gas: 122926) -MIPS_Test:test_beq_succeeds() (gas: 203359) -MIPS_Test:test_bgez_succeeds() (gas: 122219) -MIPS_Test:test_bgtz_succeeds() (gas: 122140) -MIPS_Test:test_blez_succeeds() (gas: 122096) -MIPS_Test:test_bltz_succeeds() (gas: 122239) -MIPS_Test:test_bne_succeeds() (gas: 122305) -MIPS_Test:test_branch_inDelaySlot_fails() (gas: 86514) -MIPS_Test:test_brk_succeeds() (gas: 122609) -MIPS_Test:test_clo_succeeds() (gas: 122661) -MIPS_Test:test_clone_succeeds() (gas: 122562) -MIPS_Test:test_clz_succeeds() (gas: 123132) -MIPS_Test:test_div_succeeds() (gas: 123111) -MIPS_Test:test_divu_succeeds() (gas: 123096) -MIPS_Test:test_exit_succeeds() (gas: 122611) -MIPS_Test:test_fcntl_succeeds() (gas: 204841) -MIPS_Test:test_illegal_instruction_fails() (gas: 91977) -MIPS_Test:test_invalid_root_fails() (gas: 436151) -MIPS_Test:test_jal_nonzeroRegion_succeeds() (gas: 121249) -MIPS_Test:test_jal_succeeds() (gas: 121238) -MIPS_Test:test_jalr_succeeds() (gas: 122357) -MIPS_Test:test_jr_succeeds() (gas: 122051) -MIPS_Test:test_jump_inDelaySlot_fails() (gas: 85882) -MIPS_Test:test_jump_nonzeroRegion_succeeds() (gas: 120993) -MIPS_Test:test_jump_succeeds() (gas: 120923) -MIPS_Test:test_lb_succeeds() (gas: 128164) -MIPS_Test:test_lbu_succeeds() (gas: 128062) -MIPS_Test:test_lh_succeeds() (gas: 128185) -MIPS_Test:test_lhu_succeeds() (gas: 128102) -MIPS_Test:test_ll_succeeds() (gas: 128324) -MIPS_Test:test_lui_succeeds() (gas: 122205) -MIPS_Test:test_lw_succeeds() (gas: 127953) -MIPS_Test:test_lwl_succeeds() (gas: 243070) -MIPS_Test:test_lwr_succeeds() (gas: 243358) -MIPS_Test:test_mfhi_succeeds() (gas: 122566) -MIPS_Test:test_mflo_succeeds() (gas: 122695) -MIPS_Test:test_mmap_succeeds() (gas: 119529) -MIPS_Test:test_movn_succeeds() (gas: 204031) -MIPS_Test:test_movz_succeeds() (gas: 203899) -MIPS_Test:test_mthi_succeeds() (gas: 122610) -MIPS_Test:test_mtlo_succeeds() (gas: 122718) -MIPS_Test:test_mul_succeeds() (gas: 122210) -MIPS_Test:test_mult_succeeds() (gas: 122914) -MIPS_Test:test_multu_succeeds() (gas: 122951) -MIPS_Test:test_nor_succeeds() (gas: 123043) -MIPS_Test:test_or_succeeds() (gas: 123000) -MIPS_Test:test_ori_succeeds() (gas: 123003) -MIPS_Test:test_preimage_read_succeeds() (gas: 235481) -MIPS_Test:test_preimage_write_succeeds() (gas: 127551) -MIPS_Test:test_prestate_exited_succeeds() (gas: 113792) -MIPS_Test:test_sb_succeeds() (gas: 161501) -MIPS_Test:test_sc_succeeds() (gas: 161684) -MIPS_Test:test_sh_succeeds() (gas: 161538) -MIPS_Test:test_sll_succeeds() (gas: 122171) -MIPS_Test:test_sllv_succeeds() (gas: 122400) -MIPS_Test:test_slt_succeeds() (gas: 205226) -MIPS_Test:test_sltu_succeeds() (gas: 123217) -MIPS_Test:test_sra_succeeds() (gas: 122422) -MIPS_Test:test_srav_succeeds() (gas: 122690) -MIPS_Test:test_srl_succeeds() (gas: 122253) -MIPS_Test:test_srlv_succeeds() (gas: 122418) -MIPS_Test:test_step_abi_succeeds() (gas: 58467) -MIPS_Test:test_sub_succeeds() (gas: 123027) -MIPS_Test:test_subu_succeeds() (gas: 123024) -MIPS_Test:test_sw_succeeds() (gas: 161513) -MIPS_Test:test_swl_succeeds() (gas: 161574) -MIPS_Test:test_swr_succeeds() (gas: 161649) -MIPS_Test:test_xor_succeeds() (gas: 123028) -MIPS_Test:test_xori_succeeds() (gas: 123080) +MIPS_Test:test_add_succeeds() (gas: 123021) +MIPS_Test:test_addiSign_succeeds() (gas: 122946) +MIPS_Test:test_addi_succeeds() (gas: 123166) +MIPS_Test:test_addu_succeeds() (gas: 123041) +MIPS_Test:test_addui_succeeds() (gas: 123162) +MIPS_Test:test_and_succeeds() (gas: 123017) +MIPS_Test:test_andi_succeeds() (gas: 122994) +MIPS_Test:test_beq_succeeds() (gas: 203427) +MIPS_Test:test_bgez_succeeds() (gas: 122265) +MIPS_Test:test_bgtz_succeeds() (gas: 122205) +MIPS_Test:test_blez_succeeds() (gas: 122142) +MIPS_Test:test_bltz_succeeds() (gas: 122262) +MIPS_Test:test_bne_succeeds() (gas: 122351) +MIPS_Test:test_branch_inDelaySlot_fails() (gas: 86536) +MIPS_Test:test_brk_succeeds() (gas: 122655) +MIPS_Test:test_clo_succeeds() (gas: 122707) +MIPS_Test:test_clone_succeeds() (gas: 122563) +MIPS_Test:test_clz_succeeds() (gas: 123177) +MIPS_Test:test_div_succeeds() (gas: 123134) +MIPS_Test:test_divu_succeeds() (gas: 123142) +MIPS_Test:test_exit_succeeds() (gas: 122657) +MIPS_Test:test_fcntl_succeeds() (gas: 204864) +MIPS_Test:test_illegal_instruction_fails() (gas: 92045) +MIPS_Test:test_invalid_root_fails() (gas: 436238) +MIPS_Test:test_jal_nonzeroRegion_succeeds() (gas: 121273) +MIPS_Test:test_jal_succeeds() (gas: 121217) +MIPS_Test:test_jalr_succeeds() (gas: 122425) +MIPS_Test:test_jr_succeeds() (gas: 122096) +MIPS_Test:test_jump_inDelaySlot_fails() (gas: 85884) +MIPS_Test:test_jump_nonzeroRegion_succeeds() (gas: 120972) +MIPS_Test:test_jump_succeeds() (gas: 120969) +MIPS_Test:test_lb_succeeds() (gas: 128187) +MIPS_Test:test_lbu_succeeds() (gas: 128085) +MIPS_Test:test_lh_succeeds() (gas: 128229) +MIPS_Test:test_lhu_succeeds() (gas: 128103) +MIPS_Test:test_ll_succeeds() (gas: 128303) +MIPS_Test:test_lui_succeeds() (gas: 122293) +MIPS_Test:test_lw_succeeds() (gas: 127976) +MIPS_Test:test_lwl_succeeds() (gas: 243161) +MIPS_Test:test_lwr_succeeds() (gas: 243428) +MIPS_Test:test_mfhi_succeeds() (gas: 122634) +MIPS_Test:test_mflo_succeeds() (gas: 122718) +MIPS_Test:test_mmap_succeeds() (gas: 119637) +MIPS_Test:test_movn_succeeds() (gas: 204054) +MIPS_Test:test_movz_succeeds() (gas: 203923) +MIPS_Test:test_mthi_succeeds() (gas: 122678) +MIPS_Test:test_mtlo_succeeds() (gas: 122741) +MIPS_Test:test_mul_succeeds() (gas: 122278) +MIPS_Test:test_mult_succeeds() (gas: 122959) +MIPS_Test:test_multu_succeeds() (gas: 123018) +MIPS_Test:test_nor_succeeds() (gas: 123109) +MIPS_Test:test_or_succeeds() (gas: 123024) +MIPS_Test:test_ori_succeeds() (gas: 123026) +MIPS_Test:test_preimage_read_succeeds() (gas: 235502) +MIPS_Test:test_preimage_write_succeeds() (gas: 127574) +MIPS_Test:test_prestate_exited_succeeds() (gas: 113835) +MIPS_Test:test_sb_succeeds() (gas: 161547) +MIPS_Test:test_sc_succeeds() (gas: 161752) +MIPS_Test:test_sh_succeeds() (gas: 161606) +MIPS_Test:test_sll_succeeds() (gas: 122238) +MIPS_Test:test_sllv_succeeds() (gas: 122402) +MIPS_Test:test_slt_succeeds() (gas: 205250) +MIPS_Test:test_sltu_succeeds() (gas: 123285) +MIPS_Test:test_sra_succeeds() (gas: 122490) +MIPS_Test:test_srav_succeeds() (gas: 122758) +MIPS_Test:test_srl_succeeds() (gas: 122276) +MIPS_Test:test_srlv_succeeds() (gas: 122506) +MIPS_Test:test_step_abi_succeeds() (gas: 58532) +MIPS_Test:test_sub_succeeds() (gas: 123007) +MIPS_Test:test_subu_succeeds() (gas: 123092) +MIPS_Test:test_sw_succeeds() (gas: 161604) +MIPS_Test:test_swl_succeeds() (gas: 161621) +MIPS_Test:test_swr_succeeds() (gas: 161696) +MIPS_Test:test_xor_succeeds() (gas: 123029) +MIPS_Test:test_xori_succeeds() (gas: 123147) MerkleTrie_get_Test:test_get_corruptedProof_reverts() (gas: 5733) MerkleTrie_get_Test:test_get_extraProofElements_reverts() (gas: 58889) MerkleTrie_get_Test:test_get_invalidDataRemainder_reverts() (gas: 35845) @@ -428,132 +426,123 @@ MerkleTrie_get_Test:test_get_validProof9_succeeds() (gas: 48802) MerkleTrie_get_Test:test_get_wrongKeyProof_reverts() (gas: 50730) MerkleTrie_get_Test:test_get_zeroBranchValueLength_reverts() (gas: 41684) MerkleTrie_get_Test:test_get_zeroLengthKey_reverts() (gas: 3632) -MintManager_constructor_Test:test_constructor_succeeds() (gas: 10579) -MintManager_mint_Test:test_mint_afterPeriodElapsed_succeeds() (gas: 148117) -MintManager_mint_Test:test_mint_beforePeriodElapsed_reverts() (gas: 140433) -MintManager_mint_Test:test_mint_fromNotOwner_reverts() (gas: 10987) -MintManager_mint_Test:test_mint_fromOwner_succeeds() (gas: 137219) -MintManager_mint_Test:test_mint_moreThanCap_reverts() (gas: 142523) -MintManager_upgrade_Test:test_upgrade_fromNotOwner_reverts() (gas: 10974) -MintManager_upgrade_Test:test_upgrade_fromOwner_succeeds() (gas: 23434) -MintManager_upgrade_Test:test_upgrade_toZeroAddress_reverts() (gas: 11003) +MintManager_constructor_Test:test_constructor_succeeds() (gas: 10623) +MintManager_mint_Test:test_mint_afterPeriodElapsed_succeeds() (gas: 148184) +MintManager_mint_Test:test_mint_beforePeriodElapsed_reverts() (gas: 140479) +MintManager_mint_Test:test_mint_fromNotOwner_reverts() (gas: 11054) +MintManager_mint_Test:test_mint_fromOwner_succeeds() (gas: 137330) +MintManager_mint_Test:test_mint_moreThanCap_reverts() (gas: 142568) +MintManager_upgrade_Test:test_upgrade_fromNotOwner_reverts() (gas: 11041) +MintManager_upgrade_Test:test_upgrade_fromOwner_succeeds() (gas: 23509) +MintManager_upgrade_Test:test_upgrade_toZeroAddress_reverts() (gas: 11070) Multichain:test_script_succeeds() (gas: 3078) -OptimismMintableERC20_Test:test_bridge_succeeds() (gas: 7621) -OptimismMintableERC20_Test:test_burn_notBridge_reverts() (gas: 11164) -OptimismMintableERC20_Test:test_burn_succeeds() (gas: 50996) -OptimismMintableERC20_Test:test_erc165_supportsInterface_succeeds() (gas: 7787) -OptimismMintableERC20_Test:test_l1Token_succeeds() (gas: 7621) -OptimismMintableERC20_Test:test_l2Bridge_succeeds() (gas: 7621) -OptimismMintableERC20_Test:test_legacy_succeeds() (gas: 14322) -OptimismMintableERC20_Test:test_mint_notBridge_reverts() (gas: 11165) -OptimismMintableERC20_Test:test_mint_succeeds() (gas: 63544) -OptimismMintableERC20_Test:test_remoteToken_succeeds() (gas: 7667) -OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 8381) -OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_sameTwice_reverts() (gas: 8937393460516800045) -OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2316169) -OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_zeroRemoteToken_reverts() (gas: 9493) -OptimismMintableERC721_Test:test_burn_notBridge_reverts() (gas: 136966) -OptimismMintableERC721_Test:test_burn_succeeds() (gas: 118832) -OptimismMintableERC721_Test:test_constructor_succeeds() (gas: 24162) -OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11121) -OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140547) -OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9005) -OptimismMintableERC721_Test:test_tokenURI_succeeds() (gas: 163441) -OptimismMintableTokenFactory_Test:test_bridge_succeeds() (gas: 9760) -OptimismMintableTokenFactory_Test:test_createStandardL2TokenWithDecimals_succeeds() (gas: 1303953) -OptimismMintableTokenFactory_Test:test_createStandardL2Token_remoteIsZero_reverts() (gas: 9570) -OptimismMintableTokenFactory_Test:test_createStandardL2Token_sameTwice_reverts() (gas: 8937393460516769327) -OptimismMintableTokenFactory_Test:test_createStandardL2Token_succeeds() (gas: 1303943) -OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 11178) -OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 16111) -OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 26781) -OptimismPortalUpgradeable_Test:test_upgradeToAndCall_upgrading_succeeds() (gas: 191521) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 178667) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 182306) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() (gas: 41780) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 173953) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 181188) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 154740) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 219235) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 220983) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_paused_reverts() (gas: 38706) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() (gas: 209679) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails_fails() (gas: 8797746687696162676) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 171302) -OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 85805) -OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() (gas: 111317) -OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 52973) -OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_paused_reverts() (gas: 58846) -OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() (gas: 297494) -OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() (gas: 227596) +OptimismMintableERC20_Test:test_bridge_succeeds() (gas: 7717) +OptimismMintableERC20_Test:test_burn_notBridge_reverts() (gas: 11165) +OptimismMintableERC20_Test:test_burn_succeeds() (gas: 51050) +OptimismMintableERC20_Test:test_erc165_supportsInterface_succeeds() (gas: 7854) +OptimismMintableERC20_Test:test_l1Token_succeeds() (gas: 7717) +OptimismMintableERC20_Test:test_l2Bridge_succeeds() (gas: 7672) +OptimismMintableERC20_Test:test_legacy_succeeds() (gas: 14540) +OptimismMintableERC20_Test:test_mint_notBridge_reverts() (gas: 11209) +OptimismMintableERC20_Test:test_mint_succeeds() (gas: 63589) +OptimismMintableERC20_Test:test_remoteToken_succeeds() (gas: 7740) +OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 8424) +OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_sameTwice_reverts() (gas: 8937393460516800078) +OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2316545) +OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_zeroRemoteToken_reverts() (gas: 9542) +OptimismMintableERC721_Test:test_burn_notBridge_reverts() (gas: 136967) +OptimismMintableERC721_Test:test_burn_succeeds() (gas: 118874) +OptimismMintableERC721_Test:test_constructor_succeeds() (gas: 24516) +OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11209) +OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140599) +OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9050) +OptimismMintableERC721_Test:test_tokenURI_succeeds() (gas: 163605) +OptimismMintableTokenFactory_Test:test_bridge_succeeds() (gas: 9856) +OptimismMintableTokenFactory_Test:test_createStandardL2TokenWithDecimals_succeeds() (gas: 1142627) +OptimismMintableTokenFactory_Test:test_createStandardL2Token_remoteIsZero_reverts() (gas: 9621) +OptimismMintableTokenFactory_Test:test_createStandardL2Token_sameTwice_reverts() (gas: 8937393460516764416) +OptimismMintableTokenFactory_Test:test_createStandardL2Token_succeeds() (gas: 1142619) +OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 14615) +OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 16228) +OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 26711) +OptimismPortalUpgradeable_Test:test_upgradeToAndCall_upgrading_succeeds() (gas: 186086) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 178734) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 182307) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() (gas: 41781) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 174020) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 181245) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 154807) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 219283) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 220984) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_paused_reverts() (gas: 38773) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() (gas: 209658) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails_fails() (gas: 8797746687696162679) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 171324) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 85828) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() (gas: 111318) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 52996) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_paused_reverts() (gas: 58914) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() (gas: 297495) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() (gas: 227597) OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 166699) -OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() (gas: 154430) -OptimismPortal_Test:test_constructor_succeeds() (gas: 28164) -OptimismPortal_Test:test_depositTransaction_contractCreation_reverts() (gas: 14292) -OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract_succeeds() (gas: 76814) -OptimismPortal_Test:test_depositTransaction_createWithZeroValueForEOA_succeeds() (gas: 77115) -OptimismPortal_Test:test_depositTransaction_largeData_reverts() (gas: 512149) -OptimismPortal_Test:test_depositTransaction_noValueContract_succeeds() (gas: 76767) -OptimismPortal_Test:test_depositTransaction_noValueEOA_succeeds() (gas: 77112) -OptimismPortal_Test:test_depositTransaction_smallGasLimit_reverts() (gas: 14528) -OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation_succeeds() (gas: 83773) -OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() (gas: 75929) -OptimismPortal_Test:test_depositTransaction_withEthValueFromContract_succeeds() (gas: 83476) -OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA_succeeds() (gas: 84069) -OptimismPortal_Test:test_isOutputFinalized_succeeds() (gas: 127617) -OptimismPortal_Test:test_minimumGasLimit_succeeds() (gas: 17430) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() (gas: 154431) +OptimismPortal_Test:test_constructor_succeeds() (gas: 33476) +OptimismPortal_Test:test_depositTransaction_contractCreation_reverts() (gas: 14300) +OptimismPortal_Test:test_depositTransaction_largeData_reverts() (gas: 512218) +OptimismPortal_Test:test_depositTransaction_smallGasLimit_reverts() (gas: 14556) +OptimismPortal_Test:test_isOutputFinalized_succeeds() (gas: 127639) +OptimismPortal_Test:test_minimumGasLimit_succeeds() (gas: 17661) OptimismPortal_Test:test_pause_onlyGuardian_reverts() (gas: 24487) -OptimismPortal_Test:test_pause_succeeds() (gas: 27344) -OptimismPortal_Test:test_receive_succeeds() (gas: 127564) -OptimismPortal_Test:test_simple_isOutputFinalized_succeeds() (gas: 35651) -OptimismPortal_Test:test_unpause_onlyGuardian_reverts() (gas: 31514) -OptimismPortal_Test:test_unpause_succeeds() (gas: 27451) +OptimismPortal_Test:test_pause_succeeds() (gas: 27329) +OptimismPortal_Test:test_simple_isOutputFinalized_succeeds() (gas: 40883) +OptimismPortal_Test:test_unpause_onlyGuardian_reverts() (gas: 31580) +OptimismPortal_Test:test_unpause_succeeds() (gas: 27349) OptimistAllowlistTest:test_constructor_succeeds() (gas: 16407) -OptimistAllowlistTest:test_isAllowedToMint_fromAllowlistAttestorWithFalsyValue_fails() (gas: 49842) -OptimistAllowlistTest:test_isAllowedToMint_fromAllowlistAttestor_succeeds() (gas: 49304) -OptimistAllowlistTest:test_isAllowedToMint_fromCoinbaseQuestAttestorWithFalsyValue_fails() (gas: 49544) -OptimistAllowlistTest:test_isAllowedToMint_fromCoinbaseQuestAttestor_succeeds() (gas: 53534) -OptimistAllowlistTest:test_isAllowedToMint_fromInvite_succeeds() (gas: 235508) -OptimistAllowlistTest:test_isAllowedToMint_fromWrongAllowlistAttestor_fails() (gas: 58311) -OptimistAllowlistTest:test_isAllowedToMint_fromWrongCoinbaseQuestAttestor_fails() (gas: 58268) -OptimistAllowlistTest:test_isAllowedToMint_fromWrongOptimistInviter_fails() (gas: 57601) -OptimistAllowlistTest:test_isAllowedToMint_withMultipleAttestations_succeeds() (gas: 324909) -OptimistAllowlistTest:test_isAllowedToMint_withoutAnyAttestations_fails() (gas: 23210) -OptimistInviterTest:test_claimInvite_claimBeforeMinCommitmentPeriod_reverts() (gas: 142819) -OptimistInviterTest:test_claimInvite_claimForSomeoneElse_succeeds() (gas: 245467) -OptimistInviterTest:test_claimInvite_replayingUsedNonce_reverts() (gas: 288437) -OptimistInviterTest:test_claimInvite_succeeds() (gas: 241374) -OptimistInviterTest:test_claimInvite_usingERC1271Wallet_succeeds() (gas: 245742) -OptimistInviterTest:test_claimInvite_usingSignatureIssuedForDifferentChain_reverts() (gas: 156587) -OptimistInviterTest:test_claimInvite_usingSignatureIssuedForDifferentContract_reverts() (gas: 156478) -OptimistInviterTest:test_claimInvite_usingSignatureIssuedForDifferentVersion_reverts() (gas: 155102) -OptimistInviterTest:test_claimInvite_whenIssuerHasNoInvitesLeft_reverts() (gas: 562110) +OptimistAllowlistTest:test_isAllowedToMint_fromAllowlistAttestorWithFalsyValue_fails() (gas: 49650) +OptimistAllowlistTest:test_isAllowedToMint_fromAllowlistAttestor_succeeds() (gas: 49254) +OptimistAllowlistTest:test_isAllowedToMint_fromCoinbaseQuestAttestorWithFalsyValue_fails() (gas: 49352) +OptimistAllowlistTest:test_isAllowedToMint_fromCoinbaseQuestAttestor_succeeds() (gas: 53433) +OptimistAllowlistTest:test_isAllowedToMint_fromInvite_succeeds() (gas: 235292) +OptimistAllowlistTest:test_isAllowedToMint_fromWrongAllowlistAttestor_fails() (gas: 58122) +OptimistAllowlistTest:test_isAllowedToMint_fromWrongCoinbaseQuestAttestor_fails() (gas: 58079) +OptimistAllowlistTest:test_isAllowedToMint_fromWrongOptimistInviter_fails() (gas: 57412) +OptimistAllowlistTest:test_isAllowedToMint_withMultipleAttestations_succeeds() (gas: 324720) +OptimistAllowlistTest:test_isAllowedToMint_withoutAnyAttestations_fails() (gas: 23046) +OptimistInviterTest:test_claimInvite_claimBeforeMinCommitmentPeriod_reverts() (gas: 142794) +OptimistInviterTest:test_claimInvite_claimForSomeoneElse_succeeds() (gas: 245313) +OptimistInviterTest:test_claimInvite_replayingUsedNonce_reverts() (gas: 288334) +OptimistInviterTest:test_claimInvite_succeeds() (gas: 241271) +OptimistInviterTest:test_claimInvite_usingERC1271Wallet_succeeds() (gas: 245678) +OptimistInviterTest:test_claimInvite_usingSignatureIssuedForDifferentChain_reverts() (gas: 156562) +OptimistInviterTest:test_claimInvite_usingSignatureIssuedForDifferentContract_reverts() (gas: 156453) +OptimistInviterTest:test_claimInvite_usingSignatureIssuedForDifferentVersion_reverts() (gas: 155077) +OptimistInviterTest:test_claimInvite_whenIssuerHasNoInvitesLeft_reverts() (gas: 561851) OptimistInviterTest:test_claimInvite_whenIssuerNeverReceivedInvites_reverts() (gas: 110711) -OptimistInviterTest:test_claimInvite_withIncorrectSignature_reverts() (gas: 253095) -OptimistInviterTest:test_claimInvite_withoutCommittingHash_reverts() (gas: 119210) -OptimistInviterTest:test_commitInvite_committingForSomeoneElse_succeeds() (gas: 140584) -OptimistInviterTest:test_commitInvite_committingForYourself_succeeds() (gas: 138628) -OptimistInviterTest:test_commitInvite_committingSameHashTwice_reverts() (gas: 142056) -OptimistInviterTest:test_grantInvites_adminAddingInvites_succeeds() (gas: 190757) +OptimistInviterTest:test_claimInvite_withIncorrectSignature_reverts() (gas: 253045) +OptimistInviterTest:test_claimInvite_withoutCommittingHash_reverts() (gas: 119185) +OptimistInviterTest:test_commitInvite_committingForSomeoneElse_succeeds() (gas: 140559) +OptimistInviterTest:test_commitInvite_committingForYourself_succeeds() (gas: 138603) +OptimistInviterTest:test_commitInvite_committingSameHashTwice_reverts() (gas: 142031) +OptimistInviterTest:test_grantInvites_adminAddingInvites_succeeds() (gas: 190682) OptimistInviterTest:test_grantInvites_nonAdminAddingInvites_reverts() (gas: 14026) OptimistInviterTest:test_initialize_succeeds() (gas: 10573) OptimistTest:test_approve_soulbound_reverts() (gas: 70487) -OptimistTest:test_baseURI_returnsCorrectBaseURI_succeeds() (gas: 124568) +OptimistTest:test_baseURI_returnsCorrectBaseURI_succeeds() (gas: 124566) OptimistTest:test_burn_byNonOwner_reverts() (gas: 73197) OptimistTest:test_burn_byOwner_succeeds() (gas: 54487) OptimistTest:test_initialize_succeeds() (gas: 20840) -OptimistTest:test_mint_afterAllowlistAttestation_succeeds() (gas: 121465) -OptimistTest:test_mint_afterCoinbaseQuestAttestation_succeeds() (gas: 130362) -OptimistTest:test_mint_afterInviteClaimed_succeeds() (gas: 311331) -OptimistTest:test_mint_afterMultipleAttestations_succeeds() (gas: 377762) -OptimistTest:test_mint_forAlreadyMintedClaimer_reverts() (gas: 118023) -OptimistTest:test_mint_forNonAllowlistedClaimer_reverts() (gas: 29886) +OptimistTest:test_mint_afterAllowlistAttestation_succeeds() (gas: 121365) +OptimistTest:test_mint_afterCoinbaseQuestAttestation_succeeds() (gas: 130109) +OptimistTest:test_mint_afterInviteClaimed_succeeds() (gas: 310811) +OptimistTest:test_mint_afterMultipleAttestations_succeeds() (gas: 377472) +OptimistTest:test_mint_forAlreadyMintedClaimer_reverts() (gas: 117923) +OptimistTest:test_mint_forNonAllowlistedClaimer_reverts() (gas: 29722) OptimistTest:test_mint_secondaryMinter_succeeds() (gas: 72711) -OptimistTest:test_multicall_batchingClaimAndMint_succeeds() (gas: 308376) +OptimistTest:test_multicall_batchingClaimAndMint_succeeds() (gas: 308008) OptimistTest:test_setApprovalForAll_soulbound_reverts() (gas: 74239) OptimistTest:test_supportsInterface_returnsCorrectInterfaceForERC721_succeeds() (gas: 5805) OptimistTest:test_tokenIdOfAddress_returnsOwnerID_succeeds() (gas: 63730) -OptimistTest:test_tokenURI_returnsCorrectTokenURI_succeeds() (gas: 195908) +OptimistTest:test_tokenURI_returnsCorrectTokenURI_succeeds() (gas: 195905) OptimistTest:test_transferFrom_soulbound_reverts() (gas: 75512) PreimageOracle_Test:test_keccak256PreimageKey_succeeds() (gas: 319) PreimageOracle_Test:test_loadKeccak256PreimagePart_outOfBoundsOffset_reverts() (gas: 8971) @@ -561,10 +550,10 @@ PreimageOracle_Test:test_loadKeccak256PreimagePart_succeeds() (gas: 76076) PreimageOracle_Test:test_loadLocalData_multipleContexts_succeeds() (gas: 147718) PreimageOracle_Test:test_loadLocalData_onePart_succeeds() (gas: 75905) PreimageOracle_Test:test_loadLocalData_outOfBoundsOffset_reverts() (gas: 8882) -ProtocolVersions_Initialize_Test:test_initialize_events_succeeds() (gas: 52181) -ProtocolVersions_Initialize_Test:test_initialize_values_succeeds() (gas: 32301) -ProtocolVersions_Setters_TestFail:test_setRecommended_notOwner_reverts() (gas: 15508) -ProtocolVersions_Setters_TestFail:test_setRequired_notOwner_reverts() (gas: 15520) +ProtocolVersions_Initialize_Test:test_initialize_events_succeeds() (gas: 41623) +ProtocolVersions_Initialize_Test:test_initialize_values_succeeds() (gas: 45046) +ProtocolVersions_Setters_TestFail:test_setRecommended_notOwner_reverts() (gas: 15553) +ProtocolVersions_Setters_TestFail:test_setRequired_notOwner_reverts() (gas: 15587) ProxyAdmin_Test:test_chugsplashChangeProxyAdmin_succeeds() (gas: 36440) ProxyAdmin_Test:test_chugsplashGetProxyAdmin_succeeds() (gas: 15675) ProxyAdmin_Test:test_chugsplashGetProxyImplementation_succeeds() (gas: 51084) @@ -599,44 +588,44 @@ Proxy_Test:test_upgradeToAndCall_functionDoesNotExist_reverts() (gas: 107980) Proxy_Test:test_upgradeToAndCall_isPayable_succeeds() (gas: 53744) Proxy_Test:test_upgradeToAndCall_succeeds() (gas: 125192) Proxy_Test:test_upgradeTo_clashingFunctionSignatures_succeeds() (gas: 101363) -RLPReader_readBytes_Test:test_readBytes_bytestring00_succeeds() (gas: 1863) -RLPReader_readBytes_Test:test_readBytes_bytestring01_succeeds() (gas: 1840) +RLPReader_readBytes_Test:test_readBytes_bytestring00_succeeds() (gas: 1841) +RLPReader_readBytes_Test:test_readBytes_bytestring01_succeeds() (gas: 1818) RLPReader_readBytes_Test:test_readBytes_bytestring7f_succeeds() (gas: 1861) -RLPReader_readBytes_Test:test_readBytes_invalidListLength_reverts() (gas: 3903) +RLPReader_readBytes_Test:test_readBytes_invalidListLength_reverts() (gas: 3946) RLPReader_readBytes_Test:test_readBytes_invalidPrefix_reverts() (gas: 3961) RLPReader_readBytes_Test:test_readBytes_invalidRemainder_reverts() (gas: 4155) RLPReader_readBytes_Test:test_readBytes_invalidStringLength_reverts() (gas: 3857) RLPReader_readBytes_Test:test_readBytes_revertListItem_reverts() (gas: 3998) RLPReader_readList_Test:test_readList_dictTest1_succeeds() (gas: 23140) RLPReader_readList_Test:test_readList_empty_succeeds() (gas: 4610) -RLPReader_readList_Test:test_readList_incorrectLengthInArray_reverts() (gas: 3976) +RLPReader_readList_Test:test_readList_incorrectLengthInArray_reverts() (gas: 3954) RLPReader_readList_Test:test_readList_int32Overflow2_reverts() (gas: 4139) -RLPReader_readList_Test:test_readList_int32Overflow_reverts() (gas: 4138) +RLPReader_readList_Test:test_readList_int32Overflow_reverts() (gas: 4116) RLPReader_readList_Test:test_readList_invalidRemainder_reverts() (gas: 4114) RLPReader_readList_Test:test_readList_invalidShortList_reverts() (gas: 3967) RLPReader_readList_Test:test_readList_invalidValue_reverts() (gas: 3878) RLPReader_readList_Test:test_readList_leadingZerosInLongLengthArray1_reverts() (gas: 3982) -RLPReader_readList_Test:test_readList_leadingZerosInLongLengthArray2_reverts() (gas: 3945) +RLPReader_readList_Test:test_readList_leadingZerosInLongLengthArray2_reverts() (gas: 3968) RLPReader_readList_Test:test_readList_leadingZerosInLongLengthList1_reverts() (gas: 3984) -RLPReader_readList_Test:test_readList_listLongerThan32Elements_reverts() (gas: 38612) +RLPReader_readList_Test:test_readList_listLongerThan32Elements_reverts() (gas: 38590) RLPReader_readList_Test:test_readList_listOfLists2_succeeds() (gas: 12122) -RLPReader_readList_Test:test_readList_listOfLists_succeeds() (gas: 9472) -RLPReader_readList_Test:test_readList_longList1_succeeds() (gas: 28354) -RLPReader_readList_Test:test_readList_longList2_succeeds() (gas: 196352) -RLPReader_readList_Test:test_readList_longListLessThan56Bytes_reverts() (gas: 4023) -RLPReader_readList_Test:test_readList_longStringLength_reverts() (gas: 3946) +RLPReader_readList_Test:test_readList_listOfLists_succeeds() (gas: 9450) +RLPReader_readList_Test:test_readList_longList1_succeeds() (gas: 28332) +RLPReader_readList_Test:test_readList_longList2_succeeds() (gas: 196395) +RLPReader_readList_Test:test_readList_longListLessThan56Bytes_reverts() (gas: 4046) +RLPReader_readList_Test:test_readList_longStringLength_reverts() (gas: 3924) RLPReader_readList_Test:test_readList_longStringLessThan56Bytes_reverts() (gas: 4009) -RLPReader_readList_Test:test_readList_multiList_succeeds() (gas: 11695) +RLPReader_readList_Test:test_readList_multiList_succeeds() (gas: 11737) RLPReader_readList_Test:test_readList_nonOptimalLongLengthArray1_reverts() (gas: 3999) -RLPReader_readList_Test:test_readList_nonOptimalLongLengthArray2_reverts() (gas: 4044) +RLPReader_readList_Test:test_readList_nonOptimalLongLengthArray2_reverts() (gas: 4022) RLPReader_readList_Test:test_readList_notEnoughContentForList1_reverts() (gas: 4115) -RLPReader_readList_Test:test_readList_notEnoughContentForList2_reverts() (gas: 4117) +RLPReader_readList_Test:test_readList_notEnoughContentForList2_reverts() (gas: 4161) RLPReader_readList_Test:test_readList_notEnoughContentForString1_reverts() (gas: 4072) -RLPReader_readList_Test:test_readList_notEnoughContentForString2_reverts() (gas: 4094) +RLPReader_readList_Test:test_readList_notEnoughContentForString2_reverts() (gas: 4138) RLPReader_readList_Test:test_readList_notLongEnough_reverts() (gas: 3955) -RLPReader_readList_Test:test_readList_shortListMax1_succeeds() (gas: 39602) +RLPReader_readList_Test:test_readList_shortListMax1_succeeds() (gas: 39580) RLPWriter_writeList_Test:test_writeList_dictTest1_succeeds() (gas: 36979) -RLPWriter_writeList_Test:test_writeList_empty_succeeds() (gas: 1711) +RLPWriter_writeList_Test:test_writeList_empty_succeeds() (gas: 1666) RLPWriter_writeList_Test:test_writeList_listoflists2_succeeds() (gas: 16566) RLPWriter_writeList_Test:test_writeList_listoflists_succeeds() (gas: 10841) RLPWriter_writeList_Test:test_writeList_longlist1_succeeds() (gas: 40383) @@ -644,22 +633,22 @@ RLPWriter_writeList_Test:test_writeList_longlist2_succeeds() (gas: 280754) RLPWriter_writeList_Test:test_writeList_multiList_succeeds() (gas: 22446) RLPWriter_writeList_Test:test_writeList_shortListMax1_succeeds() (gas: 36793) RLPWriter_writeList_Test:test_writeList_stringList_succeeds() (gas: 10697) -RLPWriter_writeString_Test:test_writeString_bytestring00_succeeds() (gas: 951) -RLPWriter_writeString_Test:test_writeString_bytestring01_succeeds() (gas: 951) +RLPWriter_writeString_Test:test_writeString_bytestring00_succeeds() (gas: 929) +RLPWriter_writeString_Test:test_writeString_bytestring01_succeeds() (gas: 906) RLPWriter_writeString_Test:test_writeString_bytestring7f_succeeds() (gas: 972) -RLPWriter_writeString_Test:test_writeString_empty_succeeds() (gas: 1633) +RLPWriter_writeString_Test:test_writeString_empty_succeeds() (gas: 1611) RLPWriter_writeString_Test:test_writeString_longstring2_succeeds() (gas: 258768) -RLPWriter_writeString_Test:test_writeString_longstring_succeeds() (gas: 16961) +RLPWriter_writeString_Test:test_writeString_longstring_succeeds() (gas: 16939) RLPWriter_writeString_Test:test_writeString_shortstring2_succeeds() (gas: 15376) RLPWriter_writeString_Test:test_writeString_shortstring_succeeds() (gas: 2470) -RLPWriter_writeUint_Test:test_writeUint_mediumint2_succeeds() (gas: 8721) +RLPWriter_writeUint_Test:test_writeUint_mediumint2_succeeds() (gas: 8699) RLPWriter_writeUint_Test:test_writeUint_mediumint3_succeeds() (gas: 9098) -RLPWriter_writeUint_Test:test_writeUint_mediumint_succeeds() (gas: 8357) +RLPWriter_writeUint_Test:test_writeUint_mediumint_succeeds() (gas: 8380) RLPWriter_writeUint_Test:test_writeUint_smallint2_succeeds() (gas: 7249) RLPWriter_writeUint_Test:test_writeUint_smallint3_succeeds() (gas: 7271) -RLPWriter_writeUint_Test:test_writeUint_smallint4_succeeds() (gas: 7272) -RLPWriter_writeUint_Test:test_writeUint_smallint_succeeds() (gas: 7250) -RLPWriter_writeUint_Test:test_writeUint_zero_succeeds() (gas: 7734) +RLPWriter_writeUint_Test:test_writeUint_smallint4_succeeds() (gas: 7250) +RLPWriter_writeUint_Test:test_writeUint_smallint_succeeds() (gas: 7294) +RLPWriter_writeUint_Test:test_writeUint_zero_succeeds() (gas: 7777) ResolvedDelegateProxy_Test:test_fallback_addressManagerNotSet_reverts() (gas: 605906) ResolvedDelegateProxy_Test:test_fallback_delegateCallBar_reverts() (gas: 24783) ResourceMetering_Test:test_meter_denominatorEq1_reverts() (gas: 20024064) @@ -672,40 +661,38 @@ ResourceMetering_Test:test_meter_updateTwoEmptyBlocks_succeeds() (gas: 23703) ResourceMetering_Test:test_meter_useMax_succeeds() (gas: 20020816) ResourceMetering_Test:test_meter_useMoreThanMax_reverts() (gas: 19549) SafeCall_Test:test_callWithMinGas_noLeakageHigh_succeeds() (gas: 1021670598) -SafeCall_Test:test_callWithMinGas_noLeakageLow_succeeds() (gas: 1095190710) -Semver_Test:test_behindProxy_succeeds() (gas: 507558) -Semver_Test:test_version_succeeds() (gas: 9418) -SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2_succeeds() (gas: 78333) -SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2recipientReverts_fails() (gas: 46486) -SequencerFeeVault_Test:test_constructor_succeeds() (gas: 5526) -SequencerFeeVault_Test:test_minWithdrawalAmount_succeeds() (gas: 5464) -SequencerFeeVault_Test:test_receive_succeeds() (gas: 17373) -SequencerFeeVault_Test:test_withdraw_notEnough_reverts() (gas: 9332) -SequencerFeeVault_Test:test_withdraw_toL1_succeeds() (gas: 171675) -SetPrevBaseFee_Test:test_setPrevBaseFee_succeeds() (gas: 11549) -StandardBridge_Stateless_Test:test_isCorrectTokenPair_succeeds() (gas: 49936) -StandardBridge_Stateless_Test:test_isOptimismMintableERC20_succeeds() (gas: 33072) +SafeCall_Test:test_callWithMinGas_noLeakageLow_succeeds() (gas: 1095190688) +SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2_succeeds() (gas: 80640) +SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2recipientReverts_fails() (gas: 48948) +SequencerFeeVault_Test:test_constructor_succeeds() (gas: 7705) +SequencerFeeVault_Test:test_minWithdrawalAmount_succeeds() (gas: 12794) +SequencerFeeVault_Test:test_receive_succeeds() (gas: 17395) +SequencerFeeVault_Test:test_withdraw_notEnough_reverts() (gas: 9399) +SequencerFeeVault_Test:test_withdraw_toL1_succeeds() (gas: 618343) +SetPrevBaseFee_Test:test_setPrevBaseFee_succeeds() (gas: 11595) +StandardBridge_Stateless_Test:test_isCorrectTokenPair_succeeds() (gas: 50137) +StandardBridge_Stateless_Test:test_isOptimismMintableERC20_succeeds() (gas: 33142) Storage_Roundtrip_Test:test_setGetAddress_succeeds(bytes32,address) (runs: 64, μ: 31821, ~: 31821) Storage_Roundtrip_Test:test_setGetBytes32_succeeds(bytes32,bytes32) (runs: 64, μ: 31598, ~: 31598) Storage_Roundtrip_Test:test_setGetUint_succeeds(bytes32,uint256) (runs: 64, μ: 30731, ~: 31664) -SystemConfig_Initialize_Test:test_initialize_events_succeeds() (gas: 71972) -SystemConfig_Initialize_Test:test_initialize_startBlockNoop_reverts() (gas: 81247) -SystemConfig_Initialize_Test:test_initialize_startBlockOverride_succeeds() (gas: 65143) -SystemConfig_Initialize_Test:test_initialize_values_succeeds() (gas: 64968) -SystemConfig_Initialize_TestFail:test_initialize_lowGasLimit_reverts() (gas: 57177) -SystemConfig_Setters_TestFail:test_setBatcherHash_notOwner_reverts() (gas: 15607) -SystemConfig_Setters_TestFail:test_setGasConfig_notOwner_reverts() (gas: 15577) -SystemConfig_Setters_TestFail:test_setGasLimit_notOwner_reverts() (gas: 15676) -SystemConfig_Setters_TestFail:test_setResourceConfig_badMinMax_reverts() (gas: 18541) -SystemConfig_Setters_TestFail:test_setResourceConfig_badPrecision_reverts() (gas: 21142) -SystemConfig_Setters_TestFail:test_setResourceConfig_lowGasLimit_reverts() (gas: 22146) -SystemConfig_Setters_TestFail:test_setResourceConfig_notOwner_reverts() (gas: 16799) -SystemConfig_Setters_TestFail:test_setResourceConfig_zeroDenominator_reverts() (gas: 18578) -SystemConfig_Setters_TestFail:test_setUnsafeBlockSigner_notOwner_reverts() (gas: 15590) +SystemConfig_Initialize_Test:test_initialize_events_succeeds() (gas: 88188) +SystemConfig_Initialize_Test:test_initialize_startBlockNoop_reverts() (gas: 77218) +SystemConfig_Initialize_Test:test_initialize_startBlockOverride_succeeds() (gas: 81116) +SystemConfig_Initialize_Test:test_initialize_values_succeeds() (gas: 88546) +SystemConfig_Initialize_TestFail:test_initialize_lowGasLimit_reverts() (gas: 59900) +SystemConfig_Setters_TestFail:test_setBatcherHash_notOwner_reverts() (gas: 15675) +SystemConfig_Setters_TestFail:test_setGasConfig_notOwner_reverts() (gas: 15644) +SystemConfig_Setters_TestFail:test_setGasLimit_notOwner_reverts() (gas: 15743) +SystemConfig_Setters_TestFail:test_setResourceConfig_badMinMax_reverts() (gas: 18592) +SystemConfig_Setters_TestFail:test_setResourceConfig_badPrecision_reverts() (gas: 21216) +SystemConfig_Setters_TestFail:test_setResourceConfig_lowGasLimit_reverts() (gas: 22264) +SystemConfig_Setters_TestFail:test_setResourceConfig_notOwner_reverts() (gas: 16867) +SystemConfig_Setters_TestFail:test_setResourceConfig_zeroDenominator_reverts() (gas: 18629) +SystemConfig_Setters_TestFail:test_setUnsafeBlockSigner_notOwner_reverts() (gas: 15658) TransactorTest:test_call_succeeds() (gas: 26709) TransactorTest:test_call_unauthorized_reverts() (gas: 18117) TransactorTest:test_constructor_succeeds() (gas: 9739) TransactorTest:test_delegateCall_succeeds() (gas: 20909) TransactorTest:test_delegateCall_unauthorized_reverts() (gas: 18124) TransferOnionTest:test_constructor_succeeds() (gas: 564855) -TransferOnionTest:test_unwrap_succeeds() (gas: 724955) +TransferOnionTest:test_unwrap_succeeds() (gas: 724955) \ No newline at end of file diff --git a/packages/contracts-bedrock/deploy-config/goerli.json b/packages/contracts-bedrock/deploy-config/goerli.json index 5c084b4fd36c..a724c1b7dd31 100644 --- a/packages/contracts-bedrock/deploy-config/goerli.json +++ b/packages/contracts-bedrock/deploy-config/goerli.json @@ -40,6 +40,6 @@ "eip1559DenominatorCanyon": 250, "eip1559Elasticity": 10, "systemConfigStartBlock": 8300214, - "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", - "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000" + "requiredProtocolVersion": "0x0000000000000000000000000000000000000003000000010000000000000000", + "recommendedProtocolVersion": "0x0000000000000000000000000000000000000003000000010000000000000000" } diff --git a/packages/contracts-bedrock/deploy-config/hardhat.json b/packages/contracts-bedrock/deploy-config/hardhat.json index 3a59eb60ccb8..79ebd620d1d8 100644 --- a/packages/contracts-bedrock/deploy-config/hardhat.json +++ b/packages/contracts-bedrock/deploy-config/hardhat.json @@ -5,8 +5,8 @@ "l1StartingBlockTag": "earliest", "l1ChainID": 900, "l2ChainID": 901, - "l2BlockTime": 1, - "l1BlockTime": 2, + "l2BlockTime": 2, + "l1BlockTime": 12, "maxSequencerDrift": 300, "sequencerWindowSize": 15, "channelTimeout": 40, @@ -14,8 +14,8 @@ "batchInboxAddress": "0xff00000000000000000000000000000000000000", "batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", "l2OutputOracleSubmissionInterval": 6, - "l2OutputOracleStartingTimestamp": 0, - "l2OutputOracleStartingBlockNumber": 0, + "l2OutputOracleStartingTimestamp": 1, + "l2OutputOracleStartingBlockNumber": 1, "gasPriceOracleOverhead": 2100, "gasPriceOracleScalar": 1000000, "l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", @@ -35,7 +35,7 @@ "governanceTokenName": "Optimism", "governanceTokenSymbol": "OP", "governanceTokenOwner": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", - "finalizationPeriodSeconds": 2, + "finalizationPeriodSeconds": 36, "eip1559Denominator": 50, "eip1559DenominatorCanyon": 250, "eip1559Elasticity": 10, diff --git a/packages/contracts-bedrock/deployments/4460/.chainId b/packages/contracts-bedrock/deployments/4460/.chainId new file mode 100644 index 000000000000..361dd3a2f486 --- /dev/null +++ b/packages/contracts-bedrock/deployments/4460/.chainId @@ -0,0 +1 @@ +4460 \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/58008/.chainId b/packages/contracts-bedrock/deployments/58008/.chainId new file mode 100644 index 000000000000..df498f3fb9d4 --- /dev/null +++ b/packages/contracts-bedrock/deployments/58008/.chainId @@ -0,0 +1 @@ +58008 \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/84532/.chainId b/packages/contracts-bedrock/deployments/84532/.chainId new file mode 100644 index 000000000000..667f99daf6e6 --- /dev/null +++ b/packages/contracts-bedrock/deployments/84532/.chainId @@ -0,0 +1 @@ +84532 \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/919/.chainId b/packages/contracts-bedrock/deployments/919/.chainId new file mode 100644 index 000000000000..8cef75946fe3 --- /dev/null +++ b/packages/contracts-bedrock/deployments/919/.chainId @@ -0,0 +1 @@ +919 \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/999999999/.chainId b/packages/contracts-bedrock/deployments/999999999/.chainId new file mode 100644 index 000000000000..d2caa99e0807 --- /dev/null +++ b/packages/contracts-bedrock/deployments/999999999/.chainId @@ -0,0 +1 @@ +999999999 \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-sepolia/.chainId b/packages/contracts-bedrock/deployments/optimism-sepolia/.chainId new file mode 100644 index 000000000000..03f37de82513 --- /dev/null +++ b/packages/contracts-bedrock/deployments/optimism-sepolia/.chainId @@ -0,0 +1 @@ +11155420 \ No newline at end of file diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 56cb38380213..fb3a63478b10 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -52,3 +52,10 @@ ignore = ['src/vendor/WETH9.sol'] [profile.ci.fuzz] runs = 512 + +################################################################ +# PROFILE: LITE # +################################################################ + +[profile.lite] +optimizer = false diff --git a/packages/contracts-bedrock/invariant-docs/CrossDomainMessenger.md b/packages/contracts-bedrock/invariant-docs/CrossDomainMessenger.md index 3fae2cddfa87..95ed2ffdfc19 100644 --- a/packages/contracts-bedrock/invariant-docs/CrossDomainMessenger.md +++ b/packages/contracts-bedrock/invariant-docs/CrossDomainMessenger.md @@ -1,14 +1,14 @@ # `CrossDomainMessenger` Invariants ## A call to `relayMessage` should succeed if at least the minimum gas limit can be supplied to the target context, there is enough gas to complete execution of `relayMessage` after the target context's execution is finished, and the target context did not revert. -**Test:** [`CrossDomainMessenger.t.sol#L136`](../test/invariants/CrossDomainMessenger.t.sol#L136) +**Test:** [`CrossDomainMessenger.t.sol#L137`](../test/invariants/CrossDomainMessenger.t.sol#L137) There are two minimum gas limits here: - The outer min gas limit is for the call from the `OptimismPortal` to the `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function with the `message` and inner limit. - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target contract. ## A call to `relayMessage` should assign the message hash to the `failedMessages` mapping if not enough gas is supplied to forward `minGasLimit` to the target context or if there is not enough gas to complete execution of `relayMessage` after the target context's execution is finished. -**Test:** [`CrossDomainMessenger.t.sol#L169`](../test/invariants/CrossDomainMessenger.t.sol#L169) +**Test:** [`CrossDomainMessenger.t.sol#L170`](../test/invariants/CrossDomainMessenger.t.sol#L170) There are two minimum gas limits here: - The outer min gas limit is for the call from the `OptimismPortal` to the `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function with the `message` and inner limit. diff --git a/packages/contracts-bedrock/invariant-docs/OptimismPortal.md b/packages/contracts-bedrock/invariant-docs/OptimismPortal.md index c13d0212128d..b1b2c38cb278 100644 --- a/packages/contracts-bedrock/invariant-docs/OptimismPortal.md +++ b/packages/contracts-bedrock/invariant-docs/OptimismPortal.md @@ -1,21 +1,21 @@ # `OptimismPortal` Invariants ## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`. -**Test:** [`OptimismPortal.t.sol#L148`](../test/invariants/OptimismPortal.t.sol#L148) +**Test:** [`OptimismPortal.t.sol#L151`](../test/invariants/OptimismPortal.t.sol#L151) All deposits, barring creation transactions and transactions sent to `address(0)`, should always succeed. ## `finalizeWithdrawalTransaction` should revert if the finalization period has not elapsed. -**Test:** [`OptimismPortal.t.sol#L171`](../test/invariants/OptimismPortal.t.sol#L171) +**Test:** [`OptimismPortal.t.sol#L174`](../test/invariants/OptimismPortal.t.sol#L174) 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:** [`OptimismPortal.t.sol#L201`](../test/invariants/OptimismPortal.t.sol#L201) +**Test:** [`OptimismPortal.t.sol#L204`](../test/invariants/OptimismPortal.t.sol#L204) 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:** [`OptimismPortal.t.sol#L230`](../test/invariants/OptimismPortal.t.sol#L230) +**Test:** [`OptimismPortal.t.sol#L233`](../test/invariants/OptimismPortal.t.sol#L233) 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. \ No newline at end of file diff --git a/packages/contracts-bedrock/package.json b/packages/contracts-bedrock/package.json index 80c75c11cb51..2a539c9f9b9c 100644 --- a/packages/contracts-bedrock/package.json +++ b/packages/contracts-bedrock/package.json @@ -49,8 +49,8 @@ "lint": "pnpm lint:fix && pnpm lint:check" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^6.9.0", - "@typescript-eslint/parser": "^6.9.0", + "@typescript-eslint/eslint-plugin": "^6.9.1", + "@typescript-eslint/parser": "^6.9.1", "tsx": "^3.14.0", "typescript": "^5.2.2", "ethers": "^5.7.0", diff --git a/packages/contracts-bedrock/periphery-deploy-config/4460.json b/packages/contracts-bedrock/periphery-deploy-config/4460.json new file mode 100644 index 000000000000..a429b89f9a69 --- /dev/null +++ b/packages/contracts-bedrock/periphery-deploy-config/4460.json @@ -0,0 +1,24 @@ +{ + "faucetAdmin": "0x212E789D4523D4BAF464f8Fb2A9B9dff2B36e5A6", + "faucetDrippieOwner": "0x10ab157483dd308f8B38aCF2ad823dfD255F56b5", + "faucetDripV1Value": 20000000000000000000, + "faucetDripV1Interval": 3600, + "faucetDripV1Threshold": 100000000000000000000, + "faucetDripV2Interval": 604800, + "faucetDripV2Threshold": 20000000000000000000, + "faucetDripV2Value": 500000000000000000000, + "faucetAdminDripV1Interval": 86400, + "faucetAdminDripV1Threshold": 100000000000000000, + "faucetAdminDripV1Value": 1000000000000000000, + "faucetGelatoTreasury": "0x644CB00854EDC55FE8CCC9c1967BABb22F08Ad2f", + "faucetGelatoRecipient": "0x0E9b4649eB0760A4F01646636E032D68cFDe58FF", + "faucetGelatoBalanceV1DripInterval": 86400, + "faucetGelatoBalanceV1Value": 1000000000000000000, + "faucetGelatoThreshold": 100000000000000000, + "faucetOnchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOnchainAuthModuleTtl": 86400, + "faucetOnchainAuthModuleAmount": 1000000000000000000, + "faucetOffchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOffchainAuthModuleTtl": 86400, + "faucetOffchainAuthModuleAmount": 50000000000000000 +} diff --git a/packages/contracts-bedrock/periphery-deploy-config/58008.json b/packages/contracts-bedrock/periphery-deploy-config/58008.json new file mode 100644 index 000000000000..a429b89f9a69 --- /dev/null +++ b/packages/contracts-bedrock/periphery-deploy-config/58008.json @@ -0,0 +1,24 @@ +{ + "faucetAdmin": "0x212E789D4523D4BAF464f8Fb2A9B9dff2B36e5A6", + "faucetDrippieOwner": "0x10ab157483dd308f8B38aCF2ad823dfD255F56b5", + "faucetDripV1Value": 20000000000000000000, + "faucetDripV1Interval": 3600, + "faucetDripV1Threshold": 100000000000000000000, + "faucetDripV2Interval": 604800, + "faucetDripV2Threshold": 20000000000000000000, + "faucetDripV2Value": 500000000000000000000, + "faucetAdminDripV1Interval": 86400, + "faucetAdminDripV1Threshold": 100000000000000000, + "faucetAdminDripV1Value": 1000000000000000000, + "faucetGelatoTreasury": "0x644CB00854EDC55FE8CCC9c1967BABb22F08Ad2f", + "faucetGelatoRecipient": "0x0E9b4649eB0760A4F01646636E032D68cFDe58FF", + "faucetGelatoBalanceV1DripInterval": 86400, + "faucetGelatoBalanceV1Value": 1000000000000000000, + "faucetGelatoThreshold": 100000000000000000, + "faucetOnchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOnchainAuthModuleTtl": 86400, + "faucetOnchainAuthModuleAmount": 1000000000000000000, + "faucetOffchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOffchainAuthModuleTtl": 86400, + "faucetOffchainAuthModuleAmount": 50000000000000000 +} diff --git a/packages/contracts-bedrock/periphery-deploy-config/84532.json b/packages/contracts-bedrock/periphery-deploy-config/84532.json new file mode 100644 index 000000000000..a429b89f9a69 --- /dev/null +++ b/packages/contracts-bedrock/periphery-deploy-config/84532.json @@ -0,0 +1,24 @@ +{ + "faucetAdmin": "0x212E789D4523D4BAF464f8Fb2A9B9dff2B36e5A6", + "faucetDrippieOwner": "0x10ab157483dd308f8B38aCF2ad823dfD255F56b5", + "faucetDripV1Value": 20000000000000000000, + "faucetDripV1Interval": 3600, + "faucetDripV1Threshold": 100000000000000000000, + "faucetDripV2Interval": 604800, + "faucetDripV2Threshold": 20000000000000000000, + "faucetDripV2Value": 500000000000000000000, + "faucetAdminDripV1Interval": 86400, + "faucetAdminDripV1Threshold": 100000000000000000, + "faucetAdminDripV1Value": 1000000000000000000, + "faucetGelatoTreasury": "0x644CB00854EDC55FE8CCC9c1967BABb22F08Ad2f", + "faucetGelatoRecipient": "0x0E9b4649eB0760A4F01646636E032D68cFDe58FF", + "faucetGelatoBalanceV1DripInterval": 86400, + "faucetGelatoBalanceV1Value": 1000000000000000000, + "faucetGelatoThreshold": 100000000000000000, + "faucetOnchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOnchainAuthModuleTtl": 86400, + "faucetOnchainAuthModuleAmount": 1000000000000000000, + "faucetOffchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOffchainAuthModuleTtl": 86400, + "faucetOffchainAuthModuleAmount": 50000000000000000 +} diff --git a/packages/contracts-bedrock/periphery-deploy-config/901.json b/packages/contracts-bedrock/periphery-deploy-config/901.json new file mode 100644 index 000000000000..a429b89f9a69 --- /dev/null +++ b/packages/contracts-bedrock/periphery-deploy-config/901.json @@ -0,0 +1,24 @@ +{ + "faucetAdmin": "0x212E789D4523D4BAF464f8Fb2A9B9dff2B36e5A6", + "faucetDrippieOwner": "0x10ab157483dd308f8B38aCF2ad823dfD255F56b5", + "faucetDripV1Value": 20000000000000000000, + "faucetDripV1Interval": 3600, + "faucetDripV1Threshold": 100000000000000000000, + "faucetDripV2Interval": 604800, + "faucetDripV2Threshold": 20000000000000000000, + "faucetDripV2Value": 500000000000000000000, + "faucetAdminDripV1Interval": 86400, + "faucetAdminDripV1Threshold": 100000000000000000, + "faucetAdminDripV1Value": 1000000000000000000, + "faucetGelatoTreasury": "0x644CB00854EDC55FE8CCC9c1967BABb22F08Ad2f", + "faucetGelatoRecipient": "0x0E9b4649eB0760A4F01646636E032D68cFDe58FF", + "faucetGelatoBalanceV1DripInterval": 86400, + "faucetGelatoBalanceV1Value": 1000000000000000000, + "faucetGelatoThreshold": 100000000000000000, + "faucetOnchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOnchainAuthModuleTtl": 86400, + "faucetOnchainAuthModuleAmount": 1000000000000000000, + "faucetOffchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOffchainAuthModuleTtl": 86400, + "faucetOffchainAuthModuleAmount": 50000000000000000 +} diff --git a/packages/contracts-bedrock/periphery-deploy-config/919.json b/packages/contracts-bedrock/periphery-deploy-config/919.json new file mode 100644 index 000000000000..a429b89f9a69 --- /dev/null +++ b/packages/contracts-bedrock/periphery-deploy-config/919.json @@ -0,0 +1,24 @@ +{ + "faucetAdmin": "0x212E789D4523D4BAF464f8Fb2A9B9dff2B36e5A6", + "faucetDrippieOwner": "0x10ab157483dd308f8B38aCF2ad823dfD255F56b5", + "faucetDripV1Value": 20000000000000000000, + "faucetDripV1Interval": 3600, + "faucetDripV1Threshold": 100000000000000000000, + "faucetDripV2Interval": 604800, + "faucetDripV2Threshold": 20000000000000000000, + "faucetDripV2Value": 500000000000000000000, + "faucetAdminDripV1Interval": 86400, + "faucetAdminDripV1Threshold": 100000000000000000, + "faucetAdminDripV1Value": 1000000000000000000, + "faucetGelatoTreasury": "0x644CB00854EDC55FE8CCC9c1967BABb22F08Ad2f", + "faucetGelatoRecipient": "0x0E9b4649eB0760A4F01646636E032D68cFDe58FF", + "faucetGelatoBalanceV1DripInterval": 86400, + "faucetGelatoBalanceV1Value": 1000000000000000000, + "faucetGelatoThreshold": 100000000000000000, + "faucetOnchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOnchainAuthModuleTtl": 86400, + "faucetOnchainAuthModuleAmount": 1000000000000000000, + "faucetOffchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOffchainAuthModuleTtl": 86400, + "faucetOffchainAuthModuleAmount": 50000000000000000 +} diff --git a/packages/contracts-bedrock/periphery-deploy-config/999999999.json b/packages/contracts-bedrock/periphery-deploy-config/999999999.json new file mode 100644 index 000000000000..a429b89f9a69 --- /dev/null +++ b/packages/contracts-bedrock/periphery-deploy-config/999999999.json @@ -0,0 +1,24 @@ +{ + "faucetAdmin": "0x212E789D4523D4BAF464f8Fb2A9B9dff2B36e5A6", + "faucetDrippieOwner": "0x10ab157483dd308f8B38aCF2ad823dfD255F56b5", + "faucetDripV1Value": 20000000000000000000, + "faucetDripV1Interval": 3600, + "faucetDripV1Threshold": 100000000000000000000, + "faucetDripV2Interval": 604800, + "faucetDripV2Threshold": 20000000000000000000, + "faucetDripV2Value": 500000000000000000000, + "faucetAdminDripV1Interval": 86400, + "faucetAdminDripV1Threshold": 100000000000000000, + "faucetAdminDripV1Value": 1000000000000000000, + "faucetGelatoTreasury": "0x644CB00854EDC55FE8CCC9c1967BABb22F08Ad2f", + "faucetGelatoRecipient": "0x0E9b4649eB0760A4F01646636E032D68cFDe58FF", + "faucetGelatoBalanceV1DripInterval": 86400, + "faucetGelatoBalanceV1Value": 1000000000000000000, + "faucetGelatoThreshold": 100000000000000000, + "faucetOnchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOnchainAuthModuleTtl": 86400, + "faucetOnchainAuthModuleAmount": 1000000000000000000, + "faucetOffchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOffchainAuthModuleTtl": 86400, + "faucetOffchainAuthModuleAmount": 50000000000000000 +} diff --git a/packages/contracts-bedrock/periphery-deploy-config/optimism-goerli.json b/packages/contracts-bedrock/periphery-deploy-config/optimism-goerli.json index ecc0e38255af..a429b89f9a69 100644 --- a/packages/contracts-bedrock/periphery-deploy-config/optimism-goerli.json +++ b/packages/contracts-bedrock/periphery-deploy-config/optimism-goerli.json @@ -1,6 +1,6 @@ { - "faucetAdmin": "0x8F0EBDaA1cF7106bE861753B0f9F5c0250fE0819", - "faucetDrippieOwner": "0xEa193Fd9565284E7534dDDA15b07B119e7792644", + "faucetAdmin": "0x212E789D4523D4BAF464f8Fb2A9B9dff2B36e5A6", + "faucetDrippieOwner": "0x10ab157483dd308f8B38aCF2ad823dfD255F56b5", "faucetDripV1Value": 20000000000000000000, "faucetDripV1Interval": 3600, "faucetDripV1Threshold": 100000000000000000000, @@ -11,14 +11,14 @@ "faucetAdminDripV1Threshold": 100000000000000000, "faucetAdminDripV1Value": 1000000000000000000, "faucetGelatoTreasury": "0x644CB00854EDC55FE8CCC9c1967BABb22F08Ad2f", - "faucetGelatoRecipient": "0x789e58a4B08A23a7f60141959C6ABbdC0D0C4Aba", + "faucetGelatoRecipient": "0x0E9b4649eB0760A4F01646636E032D68cFDe58FF", "faucetGelatoBalanceV1DripInterval": 86400, "faucetGelatoBalanceV1Value": 1000000000000000000, "faucetGelatoThreshold": 100000000000000000, - "faucetOnchainAuthModuleAdmin": "0x8F0EBDaA1cF7106bE861753B0f9F5c0250fE0819", + "faucetOnchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", "faucetOnchainAuthModuleTtl": 86400, "faucetOnchainAuthModuleAmount": 1000000000000000000, - "faucetOffchainAuthModuleAdmin": "0x8F0EBDaA1cF7106bE861753B0f9F5c0250fE0819", + "faucetOffchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", "faucetOffchainAuthModuleTtl": 86400, "faucetOffchainAuthModuleAmount": 50000000000000000 } diff --git a/packages/contracts-bedrock/periphery-deploy-config/optimism-sepolia.json b/packages/contracts-bedrock/periphery-deploy-config/optimism-sepolia.json new file mode 100644 index 000000000000..a429b89f9a69 --- /dev/null +++ b/packages/contracts-bedrock/periphery-deploy-config/optimism-sepolia.json @@ -0,0 +1,24 @@ +{ + "faucetAdmin": "0x212E789D4523D4BAF464f8Fb2A9B9dff2B36e5A6", + "faucetDrippieOwner": "0x10ab157483dd308f8B38aCF2ad823dfD255F56b5", + "faucetDripV1Value": 20000000000000000000, + "faucetDripV1Interval": 3600, + "faucetDripV1Threshold": 100000000000000000000, + "faucetDripV2Interval": 604800, + "faucetDripV2Threshold": 20000000000000000000, + "faucetDripV2Value": 500000000000000000000, + "faucetAdminDripV1Interval": 86400, + "faucetAdminDripV1Threshold": 100000000000000000, + "faucetAdminDripV1Value": 1000000000000000000, + "faucetGelatoTreasury": "0x644CB00854EDC55FE8CCC9c1967BABb22F08Ad2f", + "faucetGelatoRecipient": "0x0E9b4649eB0760A4F01646636E032D68cFDe58FF", + "faucetGelatoBalanceV1DripInterval": 86400, + "faucetGelatoBalanceV1Value": 1000000000000000000, + "faucetGelatoThreshold": 100000000000000000, + "faucetOnchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOnchainAuthModuleTtl": 86400, + "faucetOnchainAuthModuleAmount": 1000000000000000000, + "faucetOffchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOffchainAuthModuleTtl": 86400, + "faucetOffchainAuthModuleAmount": 50000000000000000 +} diff --git a/packages/contracts-bedrock/scripts/Deploy.s.sol b/packages/contracts-bedrock/scripts/Deploy.s.sol index db40c87ef3da..72764d8b8005 100644 --- a/packages/contracts-bedrock/scripts/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/Deploy.s.sol @@ -42,7 +42,7 @@ import { BOBA } from "src/boba/BOBA.sol"; import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; -import { AlphabetVM } from "../test/FaultDisputeGame.t.sol"; +import { AlphabetVM } from "test/mocks/AlphabetVM.sol"; import "src/libraries/DisputeTypes.sol"; /// @title Deploy @@ -53,13 +53,12 @@ import "src/libraries/DisputeTypes.sol"; contract Deploy is Deployer { DeployConfig cfg; - /// @notice The name of the script, used to ensure the right deploy artifacts - /// are used. + /// @inheritdoc Deployer function name() public pure override returns (string memory name_) { name_ = "Deploy"; } - function setUp() public override { + function setUp() public virtual override { super.setUp(); string memory path = string.concat(vm.projectRoot(), "/deploy-config/", deploymentContext, ".json"); @@ -99,7 +98,7 @@ contract Deploy is Deployer { /// @notice The create2 salt used for deployment of the contract implementations. /// Using this helps to reduce config across networks as the implementation /// addresses will be the same across networks when deployed with create2. - function implSalt() public returns (bytes32) { + function implSalt() internal returns (bytes32) { return keccak256(bytes(vm.envOr("IMPL_SALT", string("ethers phoenix")))); } diff --git a/packages/contracts-bedrock/scripts/DeployConfig.s.sol b/packages/contracts-bedrock/scripts/DeployConfig.s.sol index 89157e04a545..b2b924b9cb60 100644 --- a/packages/contracts-bedrock/scripts/DeployConfig.s.sol +++ b/packages/contracts-bedrock/scripts/DeployConfig.s.sol @@ -4,8 +4,8 @@ pragma solidity ^0.8.0; import { Script } from "forge-std/Script.sol"; import { console2 as console } from "forge-std/console2.sol"; import { stdJson } from "forge-std/StdJson.sol"; -import { Executables } from "./Executables.sol"; -import { Chains } from "./Chains.sol"; +import { Executables } from "scripts/Executables.sol"; +import { Chains } from "scripts/Chains.sol"; /// @title DeployConfig /// @notice Represents the configuration required to deploy the system. It is expected @@ -33,8 +33,11 @@ contract DeployConfig is Script { uint256 public finalizationPeriodSeconds; address public proxyAdminOwner; address public baseFeeVaultRecipient; + uint256 public baseFeeVaultMinimumWithdrawalAmount; address public l1FeeVaultRecipient; + uint256 public l1FeeVaultMinimumWithdrawalAmount; address public sequencerFeeVaultRecipient; + uint256 public sequencerFeeVaultMinimumWithdrawalAmount; string public governanceTokenName; string public governanceTokenSymbol; address public governanceTokenOwner; @@ -79,8 +82,11 @@ contract DeployConfig is Script { finalizationPeriodSeconds = stdJson.readUint(_json, "$.finalizationPeriodSeconds"); proxyAdminOwner = stdJson.readAddress(_json, "$.proxyAdminOwner"); baseFeeVaultRecipient = stdJson.readAddress(_json, "$.baseFeeVaultRecipient"); + baseFeeVaultMinimumWithdrawalAmount = stdJson.readUint(_json, "$.baseFeeVaultMinimumWithdrawalAmount"); l1FeeVaultRecipient = stdJson.readAddress(_json, "$.l1FeeVaultRecipient"); + l1FeeVaultMinimumWithdrawalAmount = stdJson.readUint(_json, "$.l1FeeVaultMinimumWithdrawalAmount"); sequencerFeeVaultRecipient = stdJson.readAddress(_json, "$.sequencerFeeVaultRecipient"); + sequencerFeeVaultMinimumWithdrawalAmount = stdJson.readUint(_json, "$.sequencerFeeVaultMinimumWithdrawalAmount"); governanceTokenName = stdJson.readString(_json, "$.governanceTokenName"); governanceTokenSymbol = stdJson.readString(_json, "$.governanceTokenSymbol"); governanceTokenOwner = stdJson.readAddress(_json, "$.governanceTokenOwner"); diff --git a/packages/contracts-bedrock/scripts/DeployPeriphery.s.sol b/packages/contracts-bedrock/scripts/DeployPeriphery.s.sol index 3cb7519832d5..cd183cbd6529 100644 --- a/packages/contracts-bedrock/scripts/DeployPeriphery.s.sol +++ b/packages/contracts-bedrock/scripts/DeployPeriphery.s.sol @@ -12,7 +12,6 @@ import { Proxy } from "src/universal/Proxy.sol"; import { Faucet } from "src/periphery/faucet/Faucet.sol"; import { Drippie } from "src/periphery/drippie/Drippie.sol"; import { CheckGelatoLow } from "src/periphery/drippie/dripchecks/CheckGelatoLow.sol"; -import { CheckBalanceHigh } from "src/periphery/drippie/dripchecks/CheckBalanceHigh.sol"; import { CheckBalanceLow } from "src/periphery/drippie/dripchecks/CheckBalanceLow.sol"; import { CheckTrue } from "src/periphery/drippie/dripchecks/CheckTrue.sol"; import { AdminFaucetAuthModule } from "src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol"; @@ -62,7 +61,6 @@ contract DeployPeriphery is Deployer { deployFaucetDrippie(); deployCheckTrue(); deployCheckBalanceLow(); - deployCheckBalanceHigh(); deployCheckGelatoLow(); deployOnChainAuthModule(); deployOffChainAuthModule(); @@ -199,25 +197,6 @@ contract DeployPeriphery is Deployer { } } - /// @notice Deploy CheckBalanceHigh contract. - function deployCheckBalanceHigh() public broadcast returns (address addr_) { - bytes32 salt = keccak256(bytes("CheckBalanceHigh")); - bytes32 initCodeHash = keccak256(abi.encodePacked(type(CheckBalanceHigh).creationCode)); - address preComputedAddress = computeCreate2Address(salt, initCodeHash); - if (preComputedAddress.code.length > 0) { - console.log("CheckBalanceHigh already deployed at %s", preComputedAddress); - save("CheckBalanceHigh", preComputedAddress); - addr_ = preComputedAddress; - } else { - CheckBalanceHigh checkBalanceHigh = new CheckBalanceHigh{ salt: salt }(); - - save("CheckBalanceHigh", address(checkBalanceHigh)); - console.log("CheckBalanceHigh deployed at %s", address(checkBalanceHigh)); - - addr_ = address(checkBalanceHigh); - } - } - /// @notice Deploy CheckGelatoLow contract. function deployCheckGelatoLow() public broadcast returns (address addr_) { bytes32 salt = keccak256(bytes("CheckGelatoLow")); @@ -468,7 +447,7 @@ contract DeployPeriphery is Deployer { /// @notice installs the OnChain AuthModule on the Faucet contract. function installOnChainAuthModule() public broadcast { string memory moduleName = "OnChainAuthModule"; - Faucet faucet = Faucet(mustGetAddress("Faucet")); + Faucet faucet = Faucet(mustGetAddress("FaucetProxy")); AdminFaucetAuthModule onChainAuthModule = AdminFaucetAuthModule(mustGetAddress(moduleName)); if (faucet.isModuleEnabled(onChainAuthModule)) { console.log("%s already installed.", moduleName); @@ -488,7 +467,7 @@ contract DeployPeriphery is Deployer { /// @notice installs the OffChain AuthModule on the Faucet contract. function installOffChainAuthModule() public broadcast { string memory moduleName = "OffChainAuthModule"; - Faucet faucet = Faucet(mustGetAddress("Faucet")); + Faucet faucet = Faucet(mustGetAddress("FaucetProxy")); AdminFaucetAuthModule offChainAuthModule = AdminFaucetAuthModule(mustGetAddress(moduleName)); if (faucet.isModuleEnabled(offChainAuthModule)) { console.log("%s already installed.", moduleName); @@ -507,7 +486,7 @@ contract DeployPeriphery is Deployer { /// @notice installs all of the auth module in the faucet contract. function installFaucetAuthModulesConfigs() public { - Faucet faucet = Faucet(mustGetAddress("Faucet")); + Faucet faucet = Faucet(mustGetAddress("FaucetProxy")); console.log("Installing auth modules at %s", address(faucet)); installOnChainAuthModule(); installOffChainAuthModule(); diff --git a/packages/contracts-bedrock/scripts/Deployer.sol b/packages/contracts-bedrock/scripts/Deployer.sol index 789cc676ba1c..c9730edc15d8 100644 --- a/packages/contracts-bedrock/scripts/Deployer.sol +++ b/packages/contracts-bedrock/scripts/Deployer.sol @@ -166,6 +166,8 @@ abstract contract Deployer is Script { /// @notice Returns the name of the deployment script. Children contracts /// must implement this to ensure that the deploy artifacts can be found. + /// This should be the same as the name of the script and is used as the file + /// name inside of the `broadcast` directory when looking up deployment artifacts. function name() public pure virtual returns (string memory); /// @notice Returns all of the deployments done in the current context. diff --git a/packages/contracts-bedrock/scripts/universal/EnhancedScript.sol b/packages/contracts-bedrock/scripts/universal/EnhancedScript.sol index fea9521ef733..065756db5b73 100644 --- a/packages/contracts-bedrock/scripts/universal/EnhancedScript.sol +++ b/packages/contracts-bedrock/scripts/universal/EnhancedScript.sol @@ -3,16 +3,16 @@ pragma solidity 0.8.15; import { console } from "forge-std/console.sol"; import { Script } from "forge-std/Script.sol"; -import { Semver } from "../../src/universal/Semver.sol"; +import { ISemver } from "../../src/universal/ISemver.sol"; /// @title EnhancedScript /// @notice Enhances forge-std' Script.sol with some additional application-specific functionality. /// Logs simulation links using Tenderly. abstract contract EnhancedScript is Script { - /// @notice Helper function used to compute the hash of Semver's version string to be used in a + /// @notice Helper function used to compute the hash of ISemver's version string to be used in a /// comparison. function _versionHash(address _addr) internal view returns (bytes32) { - return keccak256(bytes(Semver(_addr).version())); + return keccak256(bytes(ISemver(_addr).version())); } /// @notice Log a tenderly simulation link. The TENDERLY_USERNAME and TENDERLY_PROJECT diff --git a/packages/contracts-bedrock/scripts/upgrades/Multichain.s.sol b/packages/contracts-bedrock/scripts/upgrades/Multichain.s.sol index 1afb79f4c9de..365973b9f620 100644 --- a/packages/contracts-bedrock/scripts/upgrades/Multichain.s.sol +++ b/packages/contracts-bedrock/scripts/upgrades/Multichain.s.sol @@ -10,7 +10,6 @@ import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { Constants } from "src/libraries/Constants.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; import { ResourceMetering } from "src/L1/ResourceMetering.sol"; -import { Semver } from "src/universal/Semver.sol"; import { DeployConfig } from "scripts/DeployConfig.s.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index baf78554fc45..8fbbb333e0af 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -1,5 +1,5 @@ { - "src/EAS/EAS.sol": "0xea04b7a9ec170ce9cbd466ede87650f9e9ffe3d725d7951cef5777a98a840173", + "src/EAS/EAS.sol": "0xe5e9700b94a88a2e1baabe4bfa66d5c1c94e811bcc5d2c64526afc649df59118", "src/EAS/SchemaRegistry.sol": "0x5ee1a0c3b2bf1eb5edb53fb0967cf13856be546f0f16fe7acdc3e4f286db6831", "src/L1/DelayedVetoable.sol": "0x276c6276292095e6aa37a70008cf4e0d1cbcc020dbc9107459bbc72ab5ed744f", "src/L1/L1CrossDomainMessenger.sol": "0x2aa4e06827bc48484212eb2bdc30fd604ffd23b37e401b78ef428c12fa9b8385", @@ -26,12 +26,12 @@ "src/legacy/DeployerWhitelist.sol": "0x0a6840074734c9d167321d3299be18ef911a415e4c471fa92af7d6cfaa8336d4", "src/legacy/L1BlockNumber.sol": "0x20d83a636c5e2067fca8c0ed505b295174e6eddb25960d8705e6b6fea8e77fa6", "src/legacy/LegacyMessagePasser.sol": "0x80f355c9710af586f58cf6a86d1925e0073d1e504d0b3d814284af1bafe4dece", - "src/periphery/op-nft/AttestationStation.sol": "0x9cf6f2fd909f9bcff229a137198186749a839cfa3d11ddbb3021fe71c30a2fa9", - "src/periphery/op-nft/Optimist.sol": "0x38407f766aa9d394403e9da388dd0265b48901789f3e8a28af50014f9f5251d9", - "src/periphery/op-nft/OptimistAllowlist.sol": "0x53e9a9dfecbae036fd468e8f34c80c7d9c35bd8908c8a6483db44dbc5128ad69", - "src/periphery/op-nft/OptimistInviter.sol": "0xfdd5b9d45205ef9372ba37f7a6394724695e676d27a47cb154ee6e4148490013", - "src/universal/OptimismMintableERC20.sol": "0x716db294648fce1bb41c5f95a20f92445f165a568886f21edd922d5c9b2cb0b5", - "src/universal/OptimismMintableERC20Factory.sol": "0xfcf2eb56777478f47f3bf2f1111aa2e3769d5ed28a6f5fceff4517683447131a", + "src/periphery/op-nft/AttestationStation.sol": "0x067b29fe24734c121469c1cb2e9b2602ddabb9e07792338b766cab341776cd78", + "src/periphery/op-nft/Optimist.sol": "0x128113cd97433987220f25b59d883d5ee7e70ff2214a536c0df3d892e13287fc", + "src/periphery/op-nft/OptimistAllowlist.sol": "0x12e5d0a79c8c05cfd41be8a1bcbd5c889652182a723aeb5eccb35e0ee2a5b6c0", + "src/periphery/op-nft/OptimistInviter.sol": "0xe5353f882475396ca8c3c0f8905baf3450697612ee6ac1d7053a80f6e1ecdd3b", + "src/universal/OptimismMintableERC20.sol": "0x099bea9f5d2f0a827f87485a4e51b8055981f6d84a0e974d226ba6d8ed5ba73d", + "src/universal/OptimismMintableERC20Factory.sol": "0x8d4cbf4cc30a0bb72925b5d2e0386b8f91559f00933a9c7cf3dcc118e34fe61b", "src/universal/OptimismMintableERC721.sol": "0x4c73bf8474fa7eb091796a4db7e57bc5f26d50a3d1cfcb78d5efa47ced5ced2b", "src/universal/OptimismMintableERC721Factory.sol": "0x935fd97018b6ef10fa813d9d43ab7a77c80885f7a8d7feb430097645cb2abd2c", "src/universal/StorageSetter.sol": "0x6372647d8a67d243bc2fb40d2c4bf5807022d94d52d9423cfed27a7d57918635" diff --git a/packages/contracts-bedrock/src/EAS/EAS.sol b/packages/contracts-bedrock/src/EAS/EAS.sol index 387688e834be..a5ca8e1dfb4a 100644 --- a/packages/contracts-bedrock/src/EAS/EAS.sol +++ b/packages/contracts-bedrock/src/EAS/EAS.sol @@ -16,7 +16,7 @@ import { NotFound, NO_EXPIRATION_TIME, uncheckedInc -} from "./Common.sol"; +} from "src/EAS/Common.sol"; import { Attestation, @@ -31,9 +31,9 @@ import { MultiRevocationRequest, RevocationRequest, RevocationRequestData -} from "./IEAS.sol"; +} from "src/EAS/IEAS.sol"; -import { ISchemaRegistry, SchemaRecord } from "./ISchemaRegistry.sol"; +import { ISchemaRegistry, SchemaRecord } from "src/EAS/ISchemaRegistry.sol"; struct AttestationsResult { uint256 usedValue; // Total ETH amount that was sent to resolvers. diff --git a/packages/contracts-bedrock/src/EAS/eip1271/EIP1271Verifier.sol b/packages/contracts-bedrock/src/EAS/eip1271/EIP1271Verifier.sol index 22c5860bab0c..d32d11d8ee48 100644 --- a/packages/contracts-bedrock/src/EAS/eip1271/EIP1271Verifier.sol +++ b/packages/contracts-bedrock/src/EAS/eip1271/EIP1271Verifier.sol @@ -10,7 +10,7 @@ import { DelegatedAttestationRequest, DelegatedRevocationRequest, RevocationRequestData -} from "../IEAS.sol"; +} from "src/EAS/IEAS.sol"; import { DeadlineExpired, @@ -20,7 +20,7 @@ import { MAX_GAP, stringToBytes32, bytes32ToString -} from "../Common.sol"; +} from "src/EAS/Common.sol"; /// @title EIP1271Verifier /// @notice EIP1271Verifier typed signatures verifier for EAS delegated attestations. diff --git a/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol b/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol index bd3898bebffc..4e51c3e89c0d 100644 --- a/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol +++ b/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol @@ -1,16 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import { Semver } from "../../universal/Semver.sol"; +import { IEAS, Attestation } from "src/EAS/IEAS.sol"; +import { AccessDenied, InvalidEAS, InvalidLength, uncheckedInc } from "src/EAS/Common.sol"; -import { IEAS, Attestation } from "../IEAS.sol"; -import { AccessDenied, InvalidEAS, InvalidLength, uncheckedInc } from "../Common.sol"; - -import { ISchemaResolver } from "./ISchemaResolver.sol"; +import { ISchemaResolver } from "src/EAS/resolver/ISchemaResolver.sol"; /// @title SchemaResolver /// @notice The base schema resolver contract. -abstract contract SchemaResolver is ISchemaResolver, Semver { +abstract contract SchemaResolver is ISchemaResolver { error InsufficientValue(); error NotPayable(); @@ -19,7 +17,7 @@ abstract contract SchemaResolver is ISchemaResolver, Semver { /// @dev Creates a new resolver. /// @param eas The address of the global EAS contract. - constructor(IEAS eas) Semver(1, 2, 0) { + constructor(IEAS eas) { if (address(eas) == address(0)) { revert InvalidEAS(); } diff --git a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckBalanceHigh.sol b/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckBalanceHigh.sol deleted file mode 100644 index b531c93acb44..000000000000 --- a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckBalanceHigh.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import { IDripCheck } from "../IDripCheck.sol"; - -/// @title CheckBalanceHigh -/// @notice DripCheck for checking if an account's balance is above a given threshold. -contract CheckBalanceHigh is IDripCheck { - struct Params { - address target; - uint256 threshold; - } - - /// @notice External event used to help client-side tooling encode parameters. - /// @param params Parameters to encode. - event _EventToExposeStructInABI__Params(Params params); - - /// @inheritdoc IDripCheck - function check(bytes memory _params) external view returns (bool execute_) { - Params memory params = abi.decode(_params, (Params)); - - // Check target balance is above threshold. - execute_ = params.target.balance > params.threshold; - } -} diff --git a/packages/contracts-bedrock/src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol b/packages/contracts-bedrock/src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol index d162b5b2b4ec..115810d9d139 100644 --- a/packages/contracts-bedrock/src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol +++ b/packages/contracts-bedrock/src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol @@ -14,7 +14,7 @@ contract AdminFaucetAuthModule is IFaucetAuthModule, EIP712 { address public immutable ADMIN; /// @notice EIP712 typehash for the Proof type. - bytes32 public constant PROOF_TYPEHASH = keccak256("Proof(address recipient,bytes32 nonce,bytes32 id)"); + bytes32 public immutable PROOF_TYPEHASH = keccak256("Proof(address recipient,bytes32 nonce,bytes32 id)"); /// @notice Struct that represents a proof that verifies the admin. /// @custom:field recipient Address that will be receiving the faucet funds. diff --git a/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol b/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol index c36beb497f72..b9af730a71d4 100644 --- a/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol +++ b/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Semver } from "../../universal/Semver.sol"; +import { ISemver } from "src/universal/ISemver.sol"; /// @title AttestationStation /// @author Optimism Collective /// @author Gitcoin /// @notice Where attestations live. -contract AttestationStation is Semver { +contract AttestationStation is ISemver { /// @notice Struct representing data that is being attested. /// @custom:field about Address for which the attestation is about. /// @custom:field key A bytes32 key for the attestation. @@ -28,8 +28,9 @@ contract AttestationStation is Semver { /// @param val Value of the attestation. event AttestationCreated(address indexed creator, address indexed about, bytes32 indexed key, bytes val); - /// @custom:semver 1.1.2 - constructor() Semver(1, 1, 2) { } + /// @notice Semantic version. + /// @custom:semver 1.2.0 + string public constant version = "1.2.0"; /// @notice Allows anyone to create an attestation. /// @param _about Address that the attestation is about. diff --git a/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol b/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol index 9fef8007b01c..74d04b087d86 100644 --- a/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol +++ b/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Semver } from "../../universal/Semver.sol"; +import { ISemver } from "src/universal/ISemver.sol"; import { ERC721BurnableUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol"; -import { AttestationStation } from "./AttestationStation.sol"; -import { OptimistAllowlist } from "./OptimistAllowlist.sol"; +import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; +import { OptimistAllowlist } from "src/periphery/op-nft/OptimistAllowlist.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; /// @author Optimism Collective /// @author Gitcoin /// @title Optimist /// @notice A Soul Bound Token for real humans only(tm). -contract Optimist is ERC721BurnableUpgradeable, Semver { +contract Optimist is ERC721BurnableUpgradeable, ISemver { /// @notice Attestation key used by the attestor to attest the baseURI. bytes32 public constant BASE_URI_ATTESTATION_KEY = bytes32("optimist.base-uri"); @@ -25,7 +25,10 @@ contract Optimist is ERC721BurnableUpgradeable, Semver { /// @notice Address of the OptimistAllowlist contract. OptimistAllowlist public immutable OPTIMIST_ALLOWLIST; - /// @custom:semver 2.0.2 + /// @notice Semantic version. + /// @custom:semver 2.1.0 + string public constant version = "2.1.0"; + /// @param _name Token name. /// @param _symbol Token symbol. /// @param _baseURIAttestor Address of the baseURI attestor. @@ -37,9 +40,7 @@ contract Optimist is ERC721BurnableUpgradeable, Semver { address _baseURIAttestor, AttestationStation _attestationStation, OptimistAllowlist _optimistAllowlist - ) - Semver(2, 0, 2) - { + ) { BASE_URI_ATTESTOR = _baseURIAttestor; ATTESTATION_STATION = _attestationStation; OPTIMIST_ALLOWLIST = _optimistAllowlist; diff --git a/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol b/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol index ad576261bed6..b8212a37c674 100644 --- a/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol +++ b/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Semver } from "../../universal/Semver.sol"; -import { AttestationStation } from "./AttestationStation.sol"; -import { OptimistConstants } from "./libraries/OptimistConstants.sol"; +import { ISemver } from "src/universal/ISemver.sol"; +import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; +import { OptimistConstants } from "src/periphery/op-nft/libraries/OptimistConstants.sol"; /// @title OptimistAllowlist /// @notice Source of truth for whether an address is able to mint an Optimist NFT. /// isAllowedToMint function checks various signals to return boolean value /// for whether an address is eligible or not. -contract OptimistAllowlist is Semver { +contract OptimistAllowlist is ISemver { /// @notice Attestation key used by the AllowlistAttestor to manually add addresses to the /// allowlist. bytes32 public constant OPTIMIST_CAN_MINT_ATTESTATION_KEY = bytes32("optimist.can-mint"); @@ -30,7 +30,10 @@ contract OptimistAllowlist is Semver { /// attestations. address public immutable OPTIMIST_INVITER; - /// @custom:semver 1.0.2 + /// @notice Semantic version. + /// @custom:semver 1.1.0 + string public constant version = "1.1.0"; + /// @param _attestationStation Address of the AttestationStation contract. /// @param _allowlistAttestor Address of the allowlist attestor. /// @param _coinbaseQuestAttestor Address of the Coinbase Quest attestor. @@ -40,9 +43,7 @@ contract OptimistAllowlist is Semver { address _allowlistAttestor, address _coinbaseQuestAttestor, address _optimistInviter - ) - Semver(1, 0, 2) - { + ) { ATTESTATION_STATION = _attestationStation; ALLOWLIST_ATTESTOR = _allowlistAttestor; COINBASE_QUEST_ATTESTOR = _coinbaseQuestAttestor; diff --git a/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol b/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol index 805a2a648cf7..222405d77c33 100644 --- a/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol +++ b/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { OptimistConstants } from "./libraries/OptimistConstants.sol"; -import { Semver } from "../../universal/Semver.sol"; -import { AttestationStation } from "./AttestationStation.sol"; +import { OptimistConstants } from "src/periphery/op-nft/libraries/OptimistConstants.sol"; +import { ISemver } from "src/universal/ISemver.sol"; +import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; import { SignatureChecker } from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol"; @@ -32,7 +32,7 @@ import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cry /// 6) claimer waits for the MIN_COMMITMENT_PERIOD to pass. /// 7) claimer reveals the plaintext ClaimableInvite and the signature using the /// claimInvite function, receiving the "optimist.can-mint-from-invite" attestation -contract OptimistInviter is Semver, EIP712Upgradeable { +contract OptimistInviter is ISemver, EIP712Upgradeable { /// @notice Emitted when an invite is claimed. /// @param issuer Address that issued the signature. /// @param claimer Address that claimed the invite. @@ -87,10 +87,13 @@ contract OptimistInviter is Semver, EIP712Upgradeable { /// @notice Maps from addresses to number of invites they have. mapping(address => uint256) public inviteCounts; - /// @custom:semver 1.0.2 + /// @notice Semantic version. + /// @custom:semver 1.1.0 + string public constant version = "1.1.0"; + /// @param _inviteGranter Address of the invite granter. /// @param _attestationStation Address of the AttestationStation contract. - constructor(address _inviteGranter, AttestationStation _attestationStation) Semver(1, 0, 2) { + constructor(address _inviteGranter, AttestationStation _attestationStation) { INVITE_GRANTER = _inviteGranter; ATTESTATION_STATION = _attestationStation; } diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol index f00474043fa0..43ddd65424f8 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.15; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import { ILegacyMintableERC20, IOptimismMintableERC20 } from "src/universal/IOptimismMintableERC20.sol"; -import { Semver } from "src/universal/Semver.sol"; +import { ISemver } from "src/universal/ISemver.sol"; /// @title OptimismMintableERC20 /// @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed @@ -12,7 +12,7 @@ import { Semver } from "src/universal/Semver.sol"; /// use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa. /// Designed to be backwards compatible with the older StandardL2ERC20 token which was only /// meant for use on L2. -contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, Semver { +contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, ISemver { /// @notice Address of the corresponding version of this token on the remote chain. address public immutable REMOTE_TOKEN; @@ -38,7 +38,10 @@ contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, _; } - /// @custom:semver 1.2.1 + /// @notice Semantic version. + /// @custom:semver 1.3.0 + string public constant version = "1.3.0"; + /// @param _bridge Address of the L2 standard bridge. /// @param _remoteToken Address of the corresponding L1 token. /// @param _name ERC20 name. @@ -51,7 +54,6 @@ contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, uint8 _decimals ) ERC20(_name, _symbol) - Semver(1, 2, 1) { REMOTE_TOKEN = _remoteToken; BRIDGE = _bridge; diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol index b7f86dbadaab..c254dab3802b 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol @@ -32,8 +32,8 @@ contract OptimismMintableERC20Factory is ISemver, Initializable { event OptimismMintableERC20Created(address indexed localToken, address indexed remoteToken, address deployer); /// @notice Semantic version. - /// @custom:semver 1.6.1 - string public constant version = "1.6.1"; + /// @custom:semver 1.7.0 + string public constant version = "1.7.0"; /// @notice The semver MUST be bumped any time that there is a change in /// the OptimismMintableERC20 token contract since this contract diff --git a/packages/contracts-bedrock/src/universal/Semver.sol b/packages/contracts-bedrock/src/universal/Semver.sol deleted file mode 100644 index 5f81053a776a..000000000000 --- a/packages/contracts-bedrock/src/universal/Semver.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; - -/// @title Semver -/// @notice Semver is a simple contract for managing contract versions. -contract Semver { - /// @notice Contract version number (major). - uint256 private immutable MAJOR_VERSION; - - /// @notice Contract version number (minor). - uint256 private immutable MINOR_VERSION; - - /// @notice Contract version number (patch). - uint256 private immutable PATCH_VERSION; - - /// @param _major Version number (major). - /// @param _minor Version number (minor). - /// @param _patch Version number (patch). - constructor(uint256 _major, uint256 _minor, uint256 _patch) { - MAJOR_VERSION = _major; - MINOR_VERSION = _minor; - PATCH_VERSION = _patch; - } - - /// @notice Returns the full semver contract version. - /// @return Semver contract version as a string. - function version() public view returns (string memory) { - return string( - abi.encodePacked( - Strings.toString(MAJOR_VERSION), - ".", - Strings.toString(MINOR_VERSION), - ".", - Strings.toString(PATCH_VERSION) - ) - ); - } -} diff --git a/packages/contracts-bedrock/test/AdminFaucetAuthModule.t.sol b/packages/contracts-bedrock/test/AdminFaucetAuthModule.t.sol index 340bbfe4aa83..93a10329b452 100644 --- a/packages/contracts-bedrock/test/AdminFaucetAuthModule.t.sol +++ b/packages/contracts-bedrock/test/AdminFaucetAuthModule.t.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { AdminFaucetAuthModule } from "src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol"; import { Faucet } from "src/periphery/faucet/Faucet.sol"; -import { FaucetHelper } from "test/Helpers.sol"; +import { FaucetHelper } from "test/mocks/FaucetHelper.sol"; /// @title AdminFaucetAuthModuleTest /// @notice Tests the AdminFaucetAuthModule contract. diff --git a/packages/contracts-bedrock/test/AssetReceiver.t.sol b/packages/contracts-bedrock/test/AssetReceiver.t.sol index 87c14e2608dd..4ee74e43d127 100644 --- a/packages/contracts-bedrock/test/AssetReceiver.t.sol +++ b/packages/contracts-bedrock/test/AssetReceiver.t.sol @@ -3,8 +3,8 @@ pragma solidity 0.8.15; // Testing utilities import { Test } from "forge-std/Test.sol"; -import { TestERC20 } from "test/Helpers.sol"; -import { TestERC721 } from "test/Helpers.sol"; +import { TestERC20 } from "test/mocks/TestERC20.sol"; +import { TestERC721 } from "test/mocks/TestERC721.sol"; import { AssetReceiver } from "src/periphery/AssetReceiver.sol"; contract AssetReceiver_Initializer is Test { diff --git a/packages/contracts-bedrock/test/BenchmarkTest.t.sol b/packages/contracts-bedrock/test/BenchmarkTest.t.sol index 780162b66b0d..ef5662d17e6d 100644 --- a/packages/contracts-bedrock/test/BenchmarkTest.t.sol +++ b/packages/contracts-bedrock/test/BenchmarkTest.t.sol @@ -4,19 +4,21 @@ pragma solidity 0.8.15; // Testing utilities import { Test } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; -import "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { Types } from "src/libraries/Types.sol"; // Free function for setting the prevBaseFee param in the OptimismPortal. function setPrevBaseFee(Vm _vm, address _op, uint128 _prevBaseFee) { _vm.store(address(_op), bytes32(uint256(1)), bytes32((block.number << 192) | _prevBaseFee)); } -contract SetPrevBaseFee_Test is Portal_Initializer { +contract SetPrevBaseFee_Test is CommonTest { function test_setPrevBaseFee_succeeds() external { - setPrevBaseFee(vm, address(op), 100 gwei); - (uint128 prevBaseFee,, uint64 prevBlockNum) = op.params(); + setPrevBaseFee(vm, address(optimismPortal), 100 gwei); + (uint128 prevBaseFee,, uint64 prevBlockNum) = optimismPortal.params(); assertEq(uint256(prevBaseFee), 100 gwei); assertEq(uint256(prevBlockNum), block.number); } @@ -27,7 +29,7 @@ contract SetPrevBaseFee_Test is Portal_Initializer { // so that they are nothing more than the call we want measure the gas cost of. // In order to achieve this we make no assertions, and handle everything else in the setUp() // function. -contract GasBenchMark_OptimismPortal is Portal_Initializer { +contract GasBenchMark_OptimismPortal is CommonTest { // Reusable default values for a test withdrawal Types.WithdrawalTransaction _defaultTx; @@ -61,61 +63,64 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer { messagePasserStorageRoot: _storageRoot, latestBlockhash: bytes32(uint256(0)) }); - _proposedBlockNumber = oracle.nextBlockNumber(); - _proposedOutputIndex = oracle.nextOutputIndex(); + _proposedBlockNumber = l2OutputOracle.nextBlockNumber(); + _proposedOutputIndex = l2OutputOracle.nextOutputIndex(); } // Get the system into a nice ready-to-use state. function setUp() public virtual override { // Configure the oracle to return the output root we've prepared. - vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1); - vm.prank(oracle.PROPOSER()); - oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0); + vm.warp(l2OutputOracle.computeL2Timestamp(_proposedBlockNumber) + 1); + vm.prank(l2OutputOracle.PROPOSER()); + l2OutputOracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0); // Warp beyond the finalization period for the block we've proposed. - vm.warp(oracle.getL2Output(_proposedOutputIndex).timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp( + l2OutputOracle.getL2Output(_proposedOutputIndex).timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + + 1 + ); // Fund the portal so that we can withdraw ETH. - vm.deal(address(op), 0xFFFFFFFF); + vm.deal(address(optimismPortal), 0xFFFFFFFF); } function test_depositTransaction_benchmark() external { - op.depositTransaction{ value: NON_ZERO_VALUE }( - NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA + optimismPortal.depositTransaction{ value: 100 }( + address(1), 0, 50000, false, hex"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000" ); } function test_depositTransaction_benchmark_1() external { - setPrevBaseFee(vm, address(op), 1 gwei); - op.depositTransaction{ value: NON_ZERO_VALUE }( - NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA + setPrevBaseFee(vm, address(optimismPortal), 1 gwei); + optimismPortal.depositTransaction{ value: 100 }( + address(1), 0, 50000, false, hex"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000" ); } function test_proveWithdrawalTransaction_benchmark() external { - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); } } -contract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer { +contract GasBenchMark_L1CrossDomainMessenger is Bridge_Initializer { function test_sendMessage_benchmark_0() external { vm.pauseGasMetering(); - setPrevBaseFee(vm, address(op), 1 gwei); + setPrevBaseFee(vm, address(optimismPortal), 1 gwei); // The amount of data typically sent during a bridge deposit. bytes memory data = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; vm.resumeGasMetering(); - L1Messenger.sendMessage(bob, data, uint32(100)); + l1CrossDomainMessenger.sendMessage(bob, data, uint32(100)); } function test_sendMessage_benchmark_1() external { vm.pauseGasMetering(); - setPrevBaseFee(vm, address(op), 10 gwei); + setPrevBaseFee(vm, address(optimismPortal), 10 gwei); // The amount of data typically sent during a bridge deposit. bytes memory data = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; vm.resumeGasMetering(); - L1Messenger.sendMessage(bob, data, uint32(100)); + l1CrossDomainMessenger.sendMessage(bob, data, uint32(100)); } } @@ -124,28 +129,28 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer { super.setUp(); deal(address(L1Token), alice, 100000, true); vm.startPrank(alice, alice); - L1Token.approve(address(L1Bridge), type(uint256).max); + L1Token.approve(address(l1StandardBridge), type(uint256).max); } function test_depositETH_benchmark_0() external { vm.pauseGasMetering(); - setPrevBaseFee(vm, address(op), 1 gwei); + setPrevBaseFee(vm, address(optimismPortal), 1 gwei); vm.resumeGasMetering(); - L1Bridge.depositETH{ value: 500 }(50000, hex""); + l1StandardBridge.depositETH{ value: 500 }(50000, hex""); } function test_depositETH_benchmark_1() external { vm.pauseGasMetering(); - setPrevBaseFee(vm, address(op), 10 gwei); + setPrevBaseFee(vm, address(optimismPortal), 10 gwei); vm.resumeGasMetering(); - L1Bridge.depositETH{ value: 500 }(50000, hex""); + l1StandardBridge.depositETH{ value: 500 }(50000, hex""); } function test_depositERC20_benchmark_0() external { vm.pauseGasMetering(); - setPrevBaseFee(vm, address(op), 1 gwei); + setPrevBaseFee(vm, address(optimismPortal), 1 gwei); vm.resumeGasMetering(); - L1Bridge.bridgeERC20({ + l1StandardBridge.bridgeERC20({ _localToken: address(L1Token), _remoteToken: address(L2Token), _amount: 100, @@ -156,9 +161,9 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer { function test_depositERC20_benchmark_1() external { vm.pauseGasMetering(); - setPrevBaseFee(vm, address(op), 10 gwei); + setPrevBaseFee(vm, address(optimismPortal), 10 gwei); vm.resumeGasMetering(); - L1Bridge.bridgeERC20({ + l1StandardBridge.bridgeERC20({ _localToken: address(L1Token), _remoteToken: address(L2Token), _amount: 100, @@ -171,35 +176,36 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer { contract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer { function setUp() public virtual override { super.setUp(); - deal(address(L1Token), address(L1Bridge), 100, true); + deal(address(L1Token), address(l1StandardBridge), 100, true); vm.mockCall( - address(L1Bridge.messenger()), + address(l1StandardBridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L1Bridge.OTHER_BRIDGE())) + abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); - vm.startPrank(address(L1Bridge.messenger())); - vm.deal(address(L1Bridge.messenger()), 100); + vm.startPrank(address(l1StandardBridge.messenger())); + vm.deal(address(l1StandardBridge.messenger()), 100); } function test_finalizeETHWithdrawal_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. - L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex""); + l1StandardBridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex""); } } -contract GasBenchMark_L2OutputOracle is L2OutputOracle_Initializer { +contract GasBenchMark_L2OutputOracle is CommonTest { uint256 nextBlockNumber; function setUp() public override { super.setUp(); - nextBlockNumber = oracle.nextBlockNumber(); + nextBlockNumber = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber); + address proposer = cfg.l2OutputOracleProposer(); vm.startPrank(proposer); } function test_proposeL2Output_benchmark() external { - oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0); + l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0); } } diff --git a/packages/contracts-bedrock/test/CheckBalanceHigh.t.sol b/packages/contracts-bedrock/test/CheckBalanceHigh.t.sol deleted file mode 100644 index 3102f560f3c8..000000000000 --- a/packages/contracts-bedrock/test/CheckBalanceHigh.t.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import { Test } from "forge-std/Test.sol"; -import { CheckBalanceHigh } from "src/periphery/drippie/dripchecks/CheckBalanceHigh.sol"; - -/// @title CheckBalanceHighTest -/// @notice Tests the CheckBalanceHigh contract via fuzzing both the success case -/// and the failure case. -contract CheckBalanceHighTest is Test { - /// @notice An instance of the CheckBalanceHigh contract. - CheckBalanceHigh c; - - /// @notice Deploy the `CheckTrue` contract. - function setUp() external { - c = new CheckBalanceHigh(); - } - - /// @notice Fuzz the `check` function and assert that it always returns true - /// when the target's balance is larger than the threshold. - function testFuzz_check_succeeds(address _target, uint256 _threshold) external { - CheckBalanceHigh.Params memory p = CheckBalanceHigh.Params({ target: _target, threshold: _threshold }); - - // prevent overflows - vm.assume(_threshold != type(uint256).max); - vm.deal(_target, _threshold + 1); - - assertEq(c.check(abi.encode(p)), true); - } - - /// @notice Fuzz the `check` function and assert that it always returns false - /// when the target's balance is smaller than the threshold. - function testFuzz_check_lowBalance_fails(address _target, uint256 _threshold) external { - CheckBalanceHigh.Params memory p = CheckBalanceHigh.Params({ target: _target, threshold: _threshold }); - - vm.assume(_target.balance < _threshold); - - assertEq(c.check(abi.encode(p)), false); - } -} diff --git a/packages/contracts-bedrock/test/CheckGelatoLow.t.sol b/packages/contracts-bedrock/test/CheckGelatoLow.t.sol index fb213742c917..b8a25a72e3b3 100644 --- a/packages/contracts-bedrock/test/CheckGelatoLow.t.sol +++ b/packages/contracts-bedrock/test/CheckGelatoLow.t.sol @@ -20,7 +20,7 @@ contract MockGelatoTreasury is IGelatoTreasury { } /// @title CheckGelatoLowTest -/// @notice Tests the CheckBalanceHigh contract via fuzzing both the success case +/// @notice Tests the CheckGelatoLow contract via fuzzing both the success case /// and the failure case. contract CheckGelatoLowTest is Test { /// @notice An instance of the CheckGelatoLow contract. diff --git a/packages/contracts-bedrock/test/CommonTest.t.sol b/packages/contracts-bedrock/test/CommonTest.t.sol deleted file mode 100644 index a3a64b6d9b22..000000000000 --- a/packages/contracts-bedrock/test/CommonTest.t.sol +++ /dev/null @@ -1,829 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -// Testing utilities -import { Test, StdUtils } from "forge-std/Test.sol"; -import { Vm } from "forge-std/Vm.sol"; -import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; -import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol"; -import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; -import { L2StandardBridge } from "src/L2/L2StandardBridge.sol"; -import { StandardBridge } from "src/universal/StandardBridge.sol"; -import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; -import { L2ERC721Bridge } from "src/L2/L2ERC721Bridge.sol"; -import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; -import { OptimismMintableERC721Factory } from "src/universal/OptimismMintableERC721Factory.sol"; -import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; -import { OptimismPortal } from "src/L1/OptimismPortal.sol"; -import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; -import { L2CrossDomainMessenger } from "src/L2/L2CrossDomainMessenger.sol"; -import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol"; -import { FeeVault } from "src/universal/FeeVault.sol"; -import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; -import { LegacyERC20ETH } from "src/legacy/LegacyERC20ETH.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { Types } from "src/libraries/Types.sol"; -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { Proxy } from "src/universal/Proxy.sol"; -import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import { ResolvedDelegateProxy } from "src/legacy/ResolvedDelegateProxy.sol"; -import { AddressManager } from "src/legacy/AddressManager.sol"; -import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol"; -import { IL1ChugSplashDeployer } from "src/legacy/L1ChugSplashProxy.sol"; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; -import { LegacyMintableERC20 } from "src/legacy/LegacyMintableERC20.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; -import { ResourceMetering } from "src/L1/ResourceMetering.sol"; -import { Constants } from "src/libraries/Constants.sol"; - -contract CommonTest is Test { - address alice = address(128); - address bob = address(256); - address multisig = address(512); - - address immutable ZERO_ADDRESS = address(0); - address immutable NON_ZERO_ADDRESS = address(1); - uint256 immutable NON_ZERO_VALUE = 100; - uint256 immutable ZERO_VALUE = 0; - uint64 immutable NON_ZERO_GASLIMIT = 50000; - bytes32 nonZeroHash = keccak256(abi.encode("NON_ZERO")); - bytes NON_ZERO_DATA = hex"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000"; - - event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); - - /// @dev OpenZeppelin Ownable.sol transferOwnership event - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - FFIInterface ffi; - - function setUp() public virtual { - // Give alice and bob some ETH - vm.deal(alice, 1 << 16); - vm.deal(bob, 1 << 16); - vm.deal(multisig, 1 << 16); - - vm.label(alice, "alice"); - vm.label(bob, "bob"); - vm.label(multisig, "multisig"); - - // Make sure we have a non-zero base fee - vm.fee(1000000000); - - ffi = new FFIInterface(); - } - - function emitTransactionDeposited( - address _from, - address _to, - uint256 _mint, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes memory _data - ) - internal - { - emit TransactionDeposited(_from, _to, 0, abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data)); - } -} - -contract L2OutputOracle_Initializer is CommonTest { - // Test target - L2OutputOracle oracle; - L2OutputOracle oracleImpl; - - L2ToL1MessagePasser messagePasser = L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)); - - // Constructor arguments - address internal proposer = 0x000000000000000000000000000000000000AbBa; - address internal owner = 0x000000000000000000000000000000000000ACDC; - uint256 internal submissionInterval = 1800; - uint256 internal l2BlockTime = 2; - uint256 internal startingBlockNumber = 200; - uint256 internal startingTimestamp = 1000; - uint256 internal finalizationPeriodSeconds = 7 days; - address guardian; - - // Test data - uint256 initL1Time; - - event OutputProposed( - bytes32 indexed outputRoot, uint256 indexed l2OutputIndex, uint256 indexed l2BlockNumber, uint256 l1Timestamp - ); - - event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex); - - // Advance the evm's time to meet the L2OutputOracle's requirements for proposeL2Output - function warpToProposeTime(uint256 _nextBlockNumber) public { - vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1); - } - - /// @dev Helper function to propose an output. - function proposeAnotherOutput() public { - bytes32 proposedOutput2 = keccak256(abi.encode()); - uint256 nextBlockNumber = oracle.nextBlockNumber(); - uint256 nextOutputIndex = oracle.nextOutputIndex(); - warpToProposeTime(nextBlockNumber); - uint256 proposedNumber = oracle.latestBlockNumber(); - - // Ensure the submissionInterval is enforced - assertEq(nextBlockNumber, proposedNumber + submissionInterval); - - vm.roll(nextBlockNumber + 1); - - vm.expectEmit(true, true, true, true); - emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp); - - vm.prank(proposer); - oracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0); - } - - function setUp() public virtual override { - super.setUp(); - guardian = makeAddr("guardian"); - - // By default the first block has timestamp and number zero, which will cause underflows in the - // tests, so we'll move forward to these block values. - initL1Time = startingTimestamp + 1; - vm.warp(initL1Time); - vm.roll(startingBlockNumber); - // Deploy the L2OutputOracle and transfer owernship to the proposer - oracleImpl = new L2OutputOracle({ - _submissionInterval: submissionInterval, - _l2BlockTime: l2BlockTime, - _finalizationPeriodSeconds: finalizationPeriodSeconds - }); - Proxy proxy = new Proxy(multisig); - vm.prank(multisig); - proxy.upgradeToAndCall( - address(oracleImpl), - abi.encodeCall(L2OutputOracle.initialize, (startingBlockNumber, startingTimestamp, proposer, owner)) - ); - oracle = L2OutputOracle(address(proxy)); - vm.label(address(oracle), "L2OutputOracle"); - - // Set the L2ToL1MessagePasser at the correct address - vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code); - - vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, "L2ToL1MessagePasser"); - } -} - -contract Portal_Initializer is L2OutputOracle_Initializer { - // Test target - OptimismPortal internal opImpl; - OptimismPortal internal op; - SystemConfig systemConfig; - - event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); - event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); - - function setUp() public virtual override { - super.setUp(); - - Proxy systemConfigProxy = new Proxy(multisig); - - SystemConfig systemConfigImpl = new SystemConfig(); - - vm.prank(multisig); - systemConfigProxy.upgradeToAndCall( - address(systemConfigImpl), - abi.encodeCall( - SystemConfig.initialize, - ( - address(1), //_owner, - 0, //_overhead, - 10000, //_scalar, - bytes32(0), //_batcherHash, - 30_000_000, //_gasLimit, - address(0), //_unsafeBlockSigner, - Constants.DEFAULT_RESOURCE_CONFIG(), //_config, - 0, //_startBlock - address(0xff), // _batchInbox - SystemConfig.Addresses({ // _addresses - l1CrossDomainMessenger: address(0), - l1ERC721Bridge: address(0), - l1StandardBridge: address(0), - l2OutputOracle: address(oracle), - optimismPortal: address(op), - optimismMintableERC20Factory: address(0) - }) - ) - ) - ); - - systemConfig = SystemConfig(address(systemConfigProxy)); - - opImpl = new OptimismPortal(); - - Proxy proxy = new Proxy(multisig); - vm.prank(multisig); - proxy.upgradeToAndCall( - address(opImpl), abi.encodeCall(OptimismPortal.initialize, (oracle, guardian, systemConfig, false)) - ); - op = OptimismPortal(payable(address(proxy))); - vm.label(address(op), "OptimismPortal"); - } -} - -contract Messenger_Initializer is Portal_Initializer { - AddressManager internal addressManager; - L1CrossDomainMessenger internal L1Messenger; - L2CrossDomainMessenger internal L2Messenger = L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER); - - event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit); - - event SentMessageExtension1(address indexed sender, uint256 value); - - event MessagePassed( - uint256 indexed nonce, - address indexed sender, - address indexed target, - uint256 value, - uint256 gasLimit, - bytes data, - bytes32 withdrawalHash - ); - - event RelayedMessage(bytes32 indexed msgHash); - event FailedRelayedMessage(bytes32 indexed msgHash); - - event TransactionDeposited( - address indexed from, - address indexed to, - uint256 mint, - uint256 value, - uint64 gasLimit, - bool isCreation, - bytes data - ); - - event WhatHappened(bool success, bytes returndata); - - function setUp() public virtual override { - super.setUp(); - - // Deploy the address manager - vm.prank(multisig); - addressManager = new AddressManager(); - - // Setup implementation - L1CrossDomainMessenger L1MessengerImpl = new L1CrossDomainMessenger(); - - // Setup the address manager and proxy - vm.prank(multisig); - addressManager.setAddress("OVM_L1CrossDomainMessenger", address(L1MessengerImpl)); - ResolvedDelegateProxy proxy = new ResolvedDelegateProxy( - addressManager, - "OVM_L1CrossDomainMessenger" - ); - L1Messenger = L1CrossDomainMessenger(address(proxy)); - L1Messenger.initialize(op); - - vm.etch(Predeploys.L2_CROSS_DOMAIN_MESSENGER, address(new L2CrossDomainMessenger(address(L1Messenger))).code); - - L2Messenger.initialize(); - - // Label addresses - vm.label(address(addressManager), "AddressManager"); - vm.label(address(L1MessengerImpl), "L1CrossDomainMessenger_Impl"); - vm.label(address(L1Messenger), "L1CrossDomainMessenger_Proxy"); - vm.label(Predeploys.LEGACY_ERC20_ETH, "LegacyERC20ETH"); - vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L2CrossDomainMessenger"); - - vm.label(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)), "L1CrossDomainMessenger_aliased"); - } -} - -contract Bridge_Initializer is Messenger_Initializer { - L1StandardBridge L1Bridge; - L2StandardBridge L2Bridge; - OptimismMintableERC20Factory L2TokenFactory; - OptimismMintableERC20Factory L1TokenFactory; - ERC20 L1Token; - ERC20 BadL1Token; - OptimismMintableERC20 L2Token; - LegacyMintableERC20 LegacyL2Token; - ERC20 NativeL2Token; - ERC20 BadL2Token; - OptimismMintableERC20 RemoteL1Token; - - event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes data); - - event ETHWithdrawalFinalized(address indexed from, address indexed to, uint256 amount, bytes data); - - event ERC20DepositInitiated( - address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data - ); - - event ERC20WithdrawalFinalized( - address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data - ); - - event WithdrawalInitiated( - address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data - ); - - event DepositFinalized( - address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data - ); - - event DepositFailed( - address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data - ); - - event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes data); - - event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes data); - - event ERC20BridgeInitiated( - address indexed localToken, - address indexed remoteToken, - address indexed from, - address to, - uint256 amount, - bytes data - ); - - event ERC20BridgeFinalized( - address indexed localToken, - address indexed remoteToken, - address indexed from, - address to, - uint256 amount, - bytes data - ); - - function setUp() public virtual override { - super.setUp(); - - vm.label(Predeploys.L2_STANDARD_BRIDGE, "L2StandardBridge"); - vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, "OptimismMintableERC20Factory"); - - // Deploy the L1 bridge and initialize it with the address of the - // L1CrossDomainMessenger - L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig); - vm.mockCall(multisig, abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector), abi.encode(true)); - vm.startPrank(multisig); - proxy.setCode(address(new L1StandardBridge()).code); - vm.clearMockedCalls(); - address L1Bridge_Impl = proxy.getImplementation(); - vm.stopPrank(); - - L1Bridge = L1StandardBridge(payable(address(proxy))); - L1Bridge.initialize({ _messenger: L1Messenger }); - - vm.label(address(proxy), "L1StandardBridge_Proxy"); - vm.label(address(L1Bridge_Impl), "L1StandardBridge_Impl"); - - // Deploy the L2StandardBridge, move it to the correct predeploy - // address and then initialize it. It is safe to call initialize directly - // on the proxy because the bytecode was set in state with `etch`. - vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(new L2StandardBridge(StandardBridge(payable(proxy)))).code); - L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)); - L2Bridge.initialize(); - - // Set up the L2 mintable token factory - OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(); - vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code); - L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY); - L2TokenFactory.initialize(Predeploys.L2_STANDARD_BRIDGE); - - vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code); - - L1Token = new ERC20("Native L1 Token", "L1T"); - - LegacyL2Token = new LegacyMintableERC20({ - _l2Bridge: address(L2Bridge), - _l1Token: address(L1Token), - _name: string.concat("LegacyL2-", L1Token.name()), - _symbol: string.concat("LegacyL2-", L1Token.symbol()) - }); - vm.label(address(LegacyL2Token), "LegacyMintableERC20"); - - // Deploy the L2 ERC20 now - L2Token = OptimismMintableERC20( - L2TokenFactory.createStandardL2Token( - address(L1Token), - string(abi.encodePacked("L2-", L1Token.name())), - string(abi.encodePacked("L2-", L1Token.symbol())) - ) - ); - - BadL2Token = OptimismMintableERC20( - L2TokenFactory.createStandardL2Token( - address(1), - string(abi.encodePacked("L2-", L1Token.name())), - string(abi.encodePacked("L2-", L1Token.symbol())) - ) - ); - - NativeL2Token = new ERC20("Native L2 Token", "L2T"); - Proxy factoryProxy = new Proxy(multisig); - OptimismMintableERC20Factory L1TokenFactoryImpl = new OptimismMintableERC20Factory(); - - vm.prank(multisig); - factoryProxy.upgradeToAndCall( - address(L1TokenFactoryImpl), abi.encodeCall(OptimismMintableERC20Factory.initialize, address(L1Bridge)) - ); - - L1TokenFactory = OptimismMintableERC20Factory(address(factoryProxy)); - - RemoteL1Token = OptimismMintableERC20( - L1TokenFactory.createStandardL2Token( - address(NativeL2Token), - string(abi.encodePacked("L1-", NativeL2Token.name())), - string(abi.encodePacked("L1-", NativeL2Token.symbol())) - ) - ); - - BadL1Token = OptimismMintableERC20( - L1TokenFactory.createStandardL2Token( - address(1), - string(abi.encodePacked("L1-", NativeL2Token.name())), - string(abi.encodePacked("L1-", NativeL2Token.symbol())) - ) - ); - } -} - -contract ERC721Bridge_Initializer is Bridge_Initializer { - L1ERC721Bridge L1NFTBridge; - L2ERC721Bridge L2NFTBridge; - - function setUp() public virtual override { - super.setUp(); - - // Deploy the L1ERC721Bridge. - L1ERC721Bridge l1BridgeImpl = new L1ERC721Bridge(); - Proxy l1BridgeProxy = new Proxy(multisig); - - vm.prank(multisig); - l1BridgeProxy.upgradeToAndCall( - address(l1BridgeImpl), abi.encodeCall(L1ERC721Bridge.initialize, (CrossDomainMessenger(L1Messenger))) - ); - - L1NFTBridge = L1ERC721Bridge(address(l1BridgeProxy)); - - // Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address. - L2ERC721Bridge l2BridgeImpl = new L2ERC721Bridge(address(L1NFTBridge)); - Proxy l2BridgeProxy = new Proxy(multisig); - vm.etch(Predeploys.L2_ERC721_BRIDGE, address(l2BridgeProxy).code); - - // set the storage slot for admin - bytes32 OWNER_KEY = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; - vm.store(Predeploys.L2_ERC721_BRIDGE, OWNER_KEY, bytes32(uint256(uint160(multisig)))); - - vm.prank(multisig); - Proxy(payable(Predeploys.L2_ERC721_BRIDGE)).upgradeToAndCall( - address(l2BridgeImpl), abi.encodeCall(L2ERC721Bridge.initialize, ()) - ); - - // Set up a reference to the L2ERC721Bridge. - L2NFTBridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE); - - // Label the L1 and L2 bridges. - vm.label(address(L1NFTBridge), "L1ERC721Bridge"); - vm.label(address(L2NFTBridge), "L2ERC721Bridge"); - } -} - -contract FeeVault_Initializer is Bridge_Initializer { - SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET)); - address constant recipient = address(1024); - - event Withdrawal(uint256 value, address to, address from); - - event Withdrawal(uint256 value, address to, address from, FeeVault.WithdrawalNetwork withdrawalNetwork); -} - -contract FFIInterface is Test { - function getProveWithdrawalTransactionInputs(Types.WithdrawalTransaction memory _tx) - external - returns (bytes32, bytes32, bytes32, bytes32, bytes[] memory) - { - string[] memory cmds = new string[](9); - cmds[0] = "scripts/go-ffi/go-ffi"; - cmds[1] = "diff"; - cmds[2] = "getProveWithdrawalTransactionInputs"; - cmds[3] = vm.toString(_tx.nonce); - cmds[4] = vm.toString(_tx.sender); - cmds[5] = vm.toString(_tx.target); - cmds[6] = vm.toString(_tx.value); - cmds[7] = vm.toString(_tx.gasLimit); - cmds[8] = vm.toString(_tx.data); - - bytes memory result = vm.ffi(cmds); - ( - bytes32 stateRoot, - bytes32 storageRoot, - bytes32 outputRoot, - bytes32 withdrawalHash, - bytes[] memory withdrawalProof - ) = abi.decode(result, (bytes32, bytes32, bytes32, bytes32, bytes[])); - - return (stateRoot, storageRoot, outputRoot, withdrawalHash, withdrawalProof); - } - - function hashCrossDomainMessage( - uint256 _nonce, - address _sender, - address _target, - uint256 _value, - uint256 _gasLimit, - bytes memory _data - ) - external - returns (bytes32) - { - string[] memory cmds = new string[](9); - cmds[0] = "scripts/go-ffi/go-ffi"; - cmds[1] = "diff"; - cmds[2] = "hashCrossDomainMessage"; - cmds[3] = vm.toString(_nonce); - cmds[4] = vm.toString(_sender); - cmds[5] = vm.toString(_target); - cmds[6] = vm.toString(_value); - cmds[7] = vm.toString(_gasLimit); - cmds[8] = vm.toString(_data); - - bytes memory result = vm.ffi(cmds); - return abi.decode(result, (bytes32)); - } - - function hashWithdrawal( - uint256 _nonce, - address _sender, - address _target, - uint256 _value, - uint256 _gasLimit, - bytes memory _data - ) - external - returns (bytes32) - { - string[] memory cmds = new string[](9); - cmds[0] = "scripts/go-ffi/go-ffi"; - cmds[1] = "diff"; - cmds[2] = "hashWithdrawal"; - cmds[3] = vm.toString(_nonce); - cmds[4] = vm.toString(_sender); - cmds[5] = vm.toString(_target); - cmds[6] = vm.toString(_value); - cmds[7] = vm.toString(_gasLimit); - cmds[8] = vm.toString(_data); - - bytes memory result = vm.ffi(cmds); - return abi.decode(result, (bytes32)); - } - - function hashOutputRootProof( - bytes32 _version, - bytes32 _stateRoot, - bytes32 _messagePasserStorageRoot, - bytes32 _latestBlockhash - ) - external - returns (bytes32) - { - string[] memory cmds = new string[](7); - cmds[0] = "scripts/go-ffi/go-ffi"; - cmds[1] = "diff"; - cmds[2] = "hashOutputRootProof"; - cmds[3] = Strings.toHexString(uint256(_version)); - cmds[4] = Strings.toHexString(uint256(_stateRoot)); - cmds[5] = Strings.toHexString(uint256(_messagePasserStorageRoot)); - cmds[6] = Strings.toHexString(uint256(_latestBlockhash)); - - bytes memory result = vm.ffi(cmds); - return abi.decode(result, (bytes32)); - } - - function hashDepositTransaction( - address _from, - address _to, - uint256 _mint, - uint256 _value, - uint64 _gas, - bytes memory _data, - uint64 _logIndex - ) - external - returns (bytes32) - { - string[] memory cmds = new string[](11); - cmds[0] = "scripts/go-ffi/go-ffi"; - cmds[1] = "diff"; - cmds[2] = "hashDepositTransaction"; - cmds[3] = "0x0000000000000000000000000000000000000000000000000000000000000000"; - cmds[4] = vm.toString(_logIndex); - cmds[5] = vm.toString(_from); - cmds[6] = vm.toString(_to); - cmds[7] = vm.toString(_mint); - cmds[8] = vm.toString(_value); - cmds[9] = vm.toString(_gas); - cmds[10] = vm.toString(_data); - - bytes memory result = vm.ffi(cmds); - return abi.decode(result, (bytes32)); - } - - function encodeDepositTransaction(Types.UserDepositTransaction calldata txn) external returns (bytes memory) { - string[] memory cmds = new string[](12); - cmds[0] = "scripts/go-ffi/go-ffi"; - cmds[1] = "diff"; - cmds[2] = "encodeDepositTransaction"; - cmds[3] = vm.toString(txn.from); - cmds[4] = vm.toString(txn.to); - cmds[5] = vm.toString(txn.value); - cmds[6] = vm.toString(txn.mint); - cmds[7] = vm.toString(txn.gasLimit); - cmds[8] = vm.toString(txn.isCreation); - cmds[9] = vm.toString(txn.data); - cmds[10] = vm.toString(txn.l1BlockHash); - cmds[11] = vm.toString(txn.logIndex); - - bytes memory result = vm.ffi(cmds); - return abi.decode(result, (bytes)); - } - - function encodeCrossDomainMessage( - uint256 _nonce, - address _sender, - address _target, - uint256 _value, - uint256 _gasLimit, - bytes memory _data - ) - external - returns (bytes memory) - { - string[] memory cmds = new string[](9); - cmds[0] = "scripts/go-ffi/go-ffi"; - cmds[1] = "diff"; - cmds[2] = "encodeCrossDomainMessage"; - cmds[3] = vm.toString(_nonce); - cmds[4] = vm.toString(_sender); - cmds[5] = vm.toString(_target); - cmds[6] = vm.toString(_value); - cmds[7] = vm.toString(_gasLimit); - cmds[8] = vm.toString(_data); - - bytes memory result = vm.ffi(cmds); - return abi.decode(result, (bytes)); - } - - function decodeVersionedNonce(uint256 nonce) external returns (uint256, uint256) { - string[] memory cmds = new string[](4); - cmds[0] = "scripts/go-ffi/go-ffi"; - cmds[1] = "diff"; - cmds[2] = "decodeVersionedNonce"; - cmds[3] = vm.toString(nonce); - - bytes memory result = vm.ffi(cmds); - return abi.decode(result, (uint256, uint256)); - } - - function getMerkleTrieFuzzCase(string memory variant) - external - returns (bytes32, bytes memory, bytes memory, bytes[] memory) - { - string[] memory cmds = new string[](6); - cmds[0] = "./scripts/go-ffi/go-ffi"; - cmds[1] = "trie"; - cmds[2] = variant; - - return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[])); - } - - function getCannonMemoryProof(uint32 pc, uint32 insn) external returns (bytes32, bytes memory) { - string[] memory cmds = new string[](5); - cmds[0] = "scripts/go-ffi/go-ffi"; - cmds[1] = "diff"; - cmds[2] = "cannonMemoryProof"; - cmds[3] = vm.toString(pc); - cmds[4] = vm.toString(insn); - bytes memory result = vm.ffi(cmds); - (bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes)); - return (memRoot, proof); - } - - function getCannonMemoryProof( - uint32 pc, - uint32 insn, - uint32 memAddr, - uint32 memVal - ) - external - returns (bytes32, bytes memory) - { - string[] memory cmds = new string[](7); - cmds[0] = "scripts/go-ffi/go-ffi"; - cmds[1] = "diff"; - cmds[2] = "cannonMemoryProof"; - cmds[3] = vm.toString(pc); - cmds[4] = vm.toString(insn); - cmds[5] = vm.toString(memAddr); - cmds[6] = vm.toString(memVal); - bytes memory result = vm.ffi(cmds); - (bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes)); - return (memRoot, proof); - } -} - -library EIP1967Helper { - Vm internal constant vm = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); - - function getAdmin(address _proxy) internal view returns (address) { - return address(uint160(uint256(vm.load(address(_proxy), Constants.PROXY_OWNER_ADDRESS)))); - } - - function getImplementation(address _proxy) internal view returns (address) { - return address(uint160(uint256(vm.load(address(_proxy), Constants.PROXY_IMPLEMENTATION_ADDRESS)))); - } -} - -// Used for testing a future upgrade beyond the current implementations. -// We include some variables so that we can sanity check accessing storage values after an upgrade. -contract NextImpl is Initializable { - // Initializable occupies the zero-th slot. - bytes32 slot1; - bytes32[19] __gap; - bytes32 slot21; - bytes32 public constant slot21Init = bytes32(hex"1337"); - - function initialize(uint8 _init) public reinitializer(_init) { - // Slot21 is unused by an of our upgradeable contracts. - // This is used to verify that we can access this value after an upgrade. - slot21 = slot21Init; - } -} - -contract Reverter { - fallback() external { - revert(); - } -} - -// Useful for testing reentrancy guards -contract CallerCaller { - event WhatHappened(bool success, bytes returndata); - - fallback() external { - (bool success, bytes memory returndata) = msg.sender.call(msg.data); - emit WhatHappened(success, returndata); - assembly { - switch success - case 0 { revert(add(returndata, 0x20), mload(returndata)) } - default { return(add(returndata, 0x20), mload(returndata)) } - } - } -} - -// Used for testing the `CrossDomainMessenger`'s per-message reentrancy guard. -contract ConfigurableCaller { - bool doRevert = true; - address target; - bytes payload; - - event WhatHappened(bool success, bytes returndata); - - /// @notice Call the configured target with the configured payload OR revert. - function call() external { - if (doRevert) { - revert("ConfigurableCaller: revert"); - } else { - (bool success, bytes memory returndata) = address(target).call(payload); - emit WhatHappened(success, returndata); - assembly { - switch success - case 0 { revert(add(returndata, 0x20), mload(returndata)) } - default { return(add(returndata, 0x20), mload(returndata)) } - } - } - } - - /// @notice Set whether or not to have `call` revert. - function setDoRevert(bool _doRevert) external { - doRevert = _doRevert; - } - - /// @notice Set the target for the call made in `call`. - function setTarget(address _target) external { - target = _target; - } - - /// @notice Set the payload for the call made in `call`. - function setPayload(bytes calldata _payload) external { - payload = _payload; - } - - /// @notice Fallback function that reverts if `doRevert` is true. - /// Otherwise, it does nothing. - fallback() external { - if (doRevert) { - revert("ConfigurableCaller: revert"); - } - } -} diff --git a/packages/contracts-bedrock/test/CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/CrossDomainMessenger.t.sol index f525adc21c1a..a254b7312eee 100644 --- a/packages/contracts-bedrock/test/CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/CrossDomainMessenger.t.sol @@ -2,26 +2,29 @@ pragma solidity 0.8.15; // Testing utilities -import { Messenger_Initializer, Reverter, CallerCaller, CommonTest } from "test/CommonTest.t.sol"; -import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; +import { Test } from "forge-std/Test.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; +import { CallerCaller, Reverter } from "test/mocks/Callers.sol"; // Libraries -import { Predeploys } from "../src/libraries/Predeploys.sol"; -import { Hashing } from "../src/libraries/Hashing.sol"; -import { Encoding } from "../src/libraries/Encoding.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { Hashing } from "src/libraries/Hashing.sol"; +import { Encoding } from "src/libraries/Encoding.sol"; + +import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; // CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2 // CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract. -contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer { +contract CrossDomainMessenger_BaseGas_Test is Bridge_Initializer { /// @dev Ensure that baseGas passes for the max value of _minGasLimit, /// this is about 4 Billion. function test_baseGas_succeeds() external view { - L1Messenger.baseGas(hex"ff", type(uint32).max); + l1CrossDomainMessenger.baseGas(hex"ff", type(uint32).max); } /// @dev Fuzz for other values which might cause a revert in baseGas. function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view { - L1Messenger.baseGas(hex"ff", _minGasLimit); + l1CrossDomainMessenger.baseGas(hex"ff", _minGasLimit); } /// @notice The baseGas function should always return a value greater than @@ -30,8 +33,8 @@ contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer { /// gas to the OptimismPortal. function testFuzz_baseGas_portalMinGasLimit_succeeds(bytes memory _data, uint32 _minGasLimit) external { vm.assume(_data.length <= type(uint64).max); - uint64 baseGas = L1Messenger.baseGas(_data, _minGasLimit); - uint64 minGasLimit = op.minimumGasLimit(uint64(_data.length)); + uint64 baseGas = l1CrossDomainMessenger.baseGas(_data, _minGasLimit); + uint64 minGasLimit = optimismPortal.minimumGasLimit(uint64(_data.length)); assertTrue(baseGas >= minGasLimit); } } @@ -39,21 +42,21 @@ contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer { /// @title ExternalRelay /// @notice A mock external contract called via the SafeCall inside /// the CrossDomainMessenger's `relayMessage` function. -contract ExternalRelay is CommonTest { +contract ExternalRelay is Test { address internal op; address internal fuzzedSender; - L1CrossDomainMessenger internal L1Messenger; + L1CrossDomainMessenger internal l1CrossDomainMessenger; event FailedRelayedMessage(bytes32 indexed msgHash); constructor(L1CrossDomainMessenger _l1Messenger, address _op) { - L1Messenger = _l1Messenger; + l1CrossDomainMessenger = _l1Messenger; op = _op; } /// @notice Internal helper function to relay a message and perform assertions. function _internalRelay(address _innerSender) internal { - address initialSender = L1Messenger.xDomainMessageSender(); + address initialSender = l1CrossDomainMessenger.xDomainMessageSender(); bytes memory callMessage = getCallData(); @@ -70,7 +73,7 @@ contract ExternalRelay is CommonTest { emit FailedRelayedMessage(hash); vm.prank(address(op)); - L1Messenger.relayMessage({ + l1CrossDomainMessenger.relayMessage({ _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), _sender: _innerSender, _target: address(this), @@ -79,9 +82,9 @@ contract ExternalRelay is CommonTest { _message: callMessage }); - assertTrue(L1Messenger.failedMessages(hash)); - assertFalse(L1Messenger.successfulMessages(hash)); - assertEq(initialSender, L1Messenger.xDomainMessageSender()); + assertTrue(l1CrossDomainMessenger.failedMessages(hash)); + assertFalse(l1CrossDomainMessenger.successfulMessages(hash)); + assertEq(initialSender, l1CrossDomainMessenger.xDomainMessageSender()); } /// @notice externalCallWithMinGas is called by the CrossDomainMessenger. @@ -108,7 +111,7 @@ contract ExternalRelay is CommonTest { /// @title CrossDomainMessenger_RelayMessage_Test /// @notice Fuzz tests re-entrancy into the CrossDomainMessenger relayMessage function. -contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer { +contract CrossDomainMessenger_RelayMessage_Test is Bridge_Initializer { // Storage slot of the l2Sender uint256 constant senderSlotIndex = 50; @@ -116,7 +119,7 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer { function setUp() public override { super.setUp(); - er = new ExternalRelay(L1Messenger, address(op)); + er = new ExternalRelay(l1CrossDomainMessenger, address(optimismPortal)); } /// @dev This test mocks an OptimismPortal call to the L1CrossDomainMessenger via @@ -148,9 +151,9 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer { }); // set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); - vm.prank(address(op)); - L1Messenger.relayMessage({ + vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); + vm.prank(address(optimismPortal)); + l1CrossDomainMessenger.relayMessage({ _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), _sender: sender, _target: target, @@ -159,11 +162,11 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer { _message: callMessage }); - assertTrue(L1Messenger.successfulMessages(hash)); - assertEq(L1Messenger.failedMessages(hash), false); + assertTrue(l1CrossDomainMessenger.successfulMessages(hash)); + assertEq(l1CrossDomainMessenger.failedMessages(hash), false); // Ensures that the `xDomainMsgSender` is set back to `Predeploys.L2_CROSS_DOMAIN_MESSENGER` vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); - L1Messenger.xDomainMessageSender(); + l1CrossDomainMessenger.xDomainMessageSender(); } } diff --git a/packages/contracts-bedrock/test/CrossDomainOwnable.t.sol b/packages/contracts-bedrock/test/CrossDomainOwnable.t.sol index 27c8757066f7..1e7c10556a53 100644 --- a/packages/contracts-bedrock/test/CrossDomainOwnable.t.sol +++ b/packages/contracts-bedrock/test/CrossDomainOwnable.t.sol @@ -2,17 +2,18 @@ pragma solidity 0.8.15; // Testing utilities -import { Vm, VmSafe } from "forge-std/Vm.sol"; -import { CommonTest, Portal_Initializer } from "test/CommonTest.t.sol"; +import { VmSafe } from "forge-std/Vm.sol"; +import { Test } from "forge-std/Test.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol"; // Target contract dependencies -import { AddressAliasHelper } from "../src/vendor/AddressAliasHelper.sol"; +import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; // Target contract -import { CrossDomainOwnable } from "../src/L2/CrossDomainOwnable.sol"; +import { CrossDomainOwnable } from "src/L2/CrossDomainOwnable.sol"; contract XDomainSetter is CrossDomainOwnable { uint256 public value; @@ -22,11 +23,10 @@ contract XDomainSetter is CrossDomainOwnable { } } -contract CrossDomainOwnable_Test is CommonTest { +contract CrossDomainOwnable_Test is Test { XDomainSetter setter; - function setUp() public override { - super.setUp(); + function setUp() public { setter = new XDomainSetter(); } @@ -46,7 +46,7 @@ contract CrossDomainOwnable_Test is CommonTest { } } -contract CrossDomainOwnableThroughPortal_Test is Portal_Initializer { +contract CrossDomainOwnableThroughPortal_Test is CommonTest { XDomainSetter setter; /// @dev Sets up the test suite. @@ -63,7 +63,7 @@ contract CrossDomainOwnableThroughPortal_Test is Portal_Initializer { vm.recordLogs(); vm.prank(alice); - op.depositTransaction({ + optimismPortal.depositTransaction({ _to: address(setter), _value: 0, _gasLimit: 30_000, diff --git a/packages/contracts-bedrock/test/CrossDomainOwnable2.t.sol b/packages/contracts-bedrock/test/CrossDomainOwnable2.t.sol index c059872c784a..fa1244a0b0e1 100644 --- a/packages/contracts-bedrock/test/CrossDomainOwnable2.t.sol +++ b/packages/contracts-bedrock/test/CrossDomainOwnable2.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest, Messenger_Initializer } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; // Libraries import { Hashing } from "src/libraries/Hashing.sol"; @@ -10,10 +10,10 @@ import { Encoding } from "src/libraries/Encoding.sol"; import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol"; // Target contract dependencies -import { AddressAliasHelper } from "../src/vendor/AddressAliasHelper.sol"; +import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; // Target contract -import { CrossDomainOwnable2 } from "../src/L2/CrossDomainOwnable2.sol"; +import { CrossDomainOwnable2 } from "src/L2/CrossDomainOwnable2.sol"; contract XDomainSetter2 is CrossDomainOwnable2 { uint256 public value; @@ -23,7 +23,7 @@ contract XDomainSetter2 is CrossDomainOwnable2 { } } -contract CrossDomainOwnable2_Test is Messenger_Initializer { +contract CrossDomainOwnable2_Test is Bridge_Initializer { XDomainSetter2 setter; /// @dev Sets up the test suite. @@ -44,9 +44,9 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer { // set the xDomainMsgSender storage slot bytes32 key = bytes32(uint256(204)); bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(alice)); - vm.store(address(L2Messenger), key, value); + vm.store(address(l2CrossDomainMessenger), key, value); - vm.prank(address(L2Messenger)); + vm.prank(address(l2CrossDomainMessenger)); vm.expectRevert("CrossDomainOwnable2: caller is not the owner"); setter.set(1); } @@ -69,8 +69,10 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer { vm.expectEmit(true, true, true, true); emit FailedRelayedMessage(hash); - vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); - L2Messenger.relayMessage(Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger))); + l2CrossDomainMessenger.relayMessage( + Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message + ); assertEq(setter.value(), 0); } @@ -81,8 +83,8 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer { // Simulate the L2 execution where the call is coming from // the L1CrossDomainMessenger - vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); - L2Messenger.relayMessage( + vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger))); + l2CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce(1, 1), owner, address(setter), diff --git a/packages/contracts-bedrock/test/CrossDomainOwnable3.t.sol b/packages/contracts-bedrock/test/CrossDomainOwnable3.t.sol index dbe2c9af3b4c..24eab5f55a48 100644 --- a/packages/contracts-bedrock/test/CrossDomainOwnable3.t.sol +++ b/packages/contracts-bedrock/test/CrossDomainOwnable3.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest, Messenger_Initializer } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; // Libraries import { Hashing } from "src/libraries/Hashing.sol"; @@ -23,7 +23,7 @@ contract XDomainSetter3 is CrossDomainOwnable3 { } } -contract CrossDomainOwnable3_Test is Messenger_Initializer { +contract CrossDomainOwnable3_Test is Bridge_Initializer { XDomainSetter3 setter; /// @dev CrossDomainOwnable3.sol transferOwnership event @@ -73,9 +73,9 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer { // set the xDomainMsgSender storage slot bytes32 key = bytes32(uint256(204)); bytes32 value = Bytes32AddressLib.fillLast12Bytes(bob); - vm.store(address(L2Messenger), key, value); + vm.store(address(l2CrossDomainMessenger), key, value); - vm.prank(address(L2Messenger)); + vm.prank(address(l2CrossDomainMessenger)); vm.expectRevert("CrossDomainOwnable3: caller is not the owner"); setter.set(1); } @@ -109,11 +109,13 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer { // It should be a failed message. The revert is caught, // so we cannot expectRevert here. - vm.expectEmit(true, true, true, true, address(L2Messenger)); + vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger)); emit FailedRelayedMessage(hash); - vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); - L2Messenger.relayMessage(Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger))); + l2CrossDomainMessenger.relayMessage( + Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message + ); assertEq(setter.value(), 0); } @@ -212,8 +214,8 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer { // Simulate the L2 execution where the call is coming from // the L1CrossDomainMessenger - vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger))); - L2Messenger.relayMessage( + vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger))); + l2CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce(1, 1), bob, address(setter), diff --git a/packages/contracts-bedrock/test/DelayedVetoable.t.sol b/packages/contracts-bedrock/test/DelayedVetoable.t.sol index 27d0670a5875..93063359cb2e 100644 --- a/packages/contracts-bedrock/test/DelayedVetoable.t.sol +++ b/packages/contracts-bedrock/test/DelayedVetoable.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { CommonTest } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; import { DelayedVetoable } from "src/L1/DelayedVetoable.sol"; contract DelayedVetoable_Init is CommonTest { @@ -146,7 +146,7 @@ contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init { /// @dev Only the initiator can initiate a call. function test_handleCall_unauthorizedInitiation_reverts() external { vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this))); - (bool success,) = address(delayedVetoable).call(NON_ZERO_DATA); + (bool success,) = address(delayedVetoable).call(hex"00001234"); assertTrue(success); } diff --git a/packages/contracts-bedrock/test/DeployerWhitelist.t.sol b/packages/contracts-bedrock/test/DeployerWhitelist.t.sol index a3096fd373f8..19dc879d44a2 100644 --- a/packages/contracts-bedrock/test/DeployerWhitelist.t.sol +++ b/packages/contracts-bedrock/test/DeployerWhitelist.t.sol @@ -2,16 +2,16 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; +import { Test } from "forge-std/Test.sol"; // Target contract import { DeployerWhitelist } from "src/legacy/DeployerWhitelist.sol"; -contract DeployerWhitelist_Test is CommonTest { +contract DeployerWhitelist_Test is Test { DeployerWhitelist list; /// @dev Sets up the test suite. - function setUp() public virtual override { + function setUp() public { list = new DeployerWhitelist(); } diff --git a/packages/contracts-bedrock/test/DisputeGameFactory.t.sol b/packages/contracts-bedrock/test/DisputeGameFactory.t.sol index a745b73fb04c..d9f058d2c558 100644 --- a/packages/contracts-bedrock/test/DisputeGameFactory.t.sol +++ b/packages/contracts-bedrock/test/DisputeGameFactory.t.sol @@ -8,9 +8,9 @@ import { Test } from "forge-std/Test.sol"; import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import { Proxy } from "src/universal/Proxy.sol"; -import { L2OutputOracle_Initializer } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; -contract DisputeGameFactory_Init is L2OutputOracle_Initializer { +contract DisputeGameFactory_Init is CommonTest { DisputeGameFactory factory; FakeClone fakeClone; diff --git a/packages/contracts-bedrock/test/Drippie.t.sol b/packages/contracts-bedrock/test/Drippie.t.sol index 758011448608..c56b9292378a 100644 --- a/packages/contracts-bedrock/test/Drippie.t.sol +++ b/packages/contracts-bedrock/test/Drippie.t.sol @@ -5,7 +5,7 @@ import { Test } from "forge-std/Test.sol"; import { Drippie } from "src/periphery/drippie/Drippie.sol"; import { IDripCheck } from "src/periphery/drippie/IDripCheck.sol"; import { CheckTrue } from "src/periphery/drippie/dripchecks/CheckTrue.sol"; -import { SimpleStorage } from "test/Helpers.sol"; +import { SimpleStorage } from "test/mocks/SimpleStorage.sol"; /// @title TestDrippie /// @notice This is a wrapper contract around Drippie used for testing. diff --git a/packages/contracts-bedrock/test/Encoding.t.sol b/packages/contracts-bedrock/test/Encoding.t.sol index 14ac3c81a0f7..35e9300f834e 100644 --- a/packages/contracts-bedrock/test/Encoding.t.sol +++ b/packages/contracts-bedrock/test/Encoding.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { Types } from "src/libraries/Types.sol"; diff --git a/packages/contracts-bedrock/test/Faucet.t.sol b/packages/contracts-bedrock/test/Faucet.t.sol index 3c4da9c98798..24494edfb1a6 100644 --- a/packages/contracts-bedrock/test/Faucet.t.sol +++ b/packages/contracts-bedrock/test/Faucet.t.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { Faucet } from "src/periphery/faucet/Faucet.sol"; import { AdminFaucetAuthModule } from "src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol"; -import { FaucetHelper } from "test/Helpers.sol"; +import { FaucetHelper } from "test/mocks/FaucetHelper.sol"; contract Faucet_Initializer is Test { event Drip(string indexed authModule, bytes32 indexed userId, uint256 amount, address indexed recipient); diff --git a/packages/contracts-bedrock/test/FaultDisputeGame.t.sol b/packages/contracts-bedrock/test/FaultDisputeGame.t.sol index 40297b6cc8c0..134568776c3a 100644 --- a/packages/contracts-bedrock/test/FaultDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/FaultDisputeGame.t.sol @@ -17,6 +17,7 @@ import { Types } from "src/libraries/Types.sol"; import { LibClock } from "src/dispute/lib/LibClock.sol"; import { LibPosition } from "src/dispute/lib/LibPosition.sol"; import { IBigStepper, IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; +import { AlphabetVM } from "test/mocks/AlphabetVM.sol"; contract FaultDisputeGame_Init is DisputeGameFactory_Init { /// @dev The type of the game being tested. @@ -36,9 +37,9 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init { vm.warp(1690906994); // Propose 2 mock outputs - vm.startPrank(oracle.PROPOSER()); + vm.startPrank(l2OutputOracle.PROPOSER()); for (uint256 i; i < 2; i++) { - oracle.proposeL2Output(bytes32(i + 1), oracle.nextBlockNumber(), blockhash(i), i); + l2OutputOracle.proposeL2Output(bytes32(i + 1), l2OutputOracle.nextBlockNumber(), blockhash(i), i); // Advance 1 block vm.roll(block.number + 1); @@ -51,7 +52,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init { blockOracle.checkpoint(); // Set the extra data for the game creation - extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, block.number - 1); + extraData = abi.encode(l2OutputOracle.SUBMISSION_INTERVAL() * 2, block.number - 1); // Deploy an implementation of the fault game gameImpl = new FaultDisputeGame( @@ -60,7 +61,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init { 4, Duration.wrap(7 days), new AlphabetVM(absolutePrestate), - oracle, + l2OutputOracle, blockOracle ); // Register the game implementation with the factory. @@ -126,7 +127,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { function test_initialize_l1HeadTooOld_reverts() public { // Store a mock block hash for the genesis block. The timestamp will default to 0. vm.store(address(gameImpl.BLOCK_ORACLE()), keccak256(abi.encode(0, 0)), bytes32(uint256(1))); - bytes memory _extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, 0); + bytes memory _extraData = abi.encode(l2OutputOracle.SUBMISSION_INTERVAL() * 2, 0); vm.expectRevert(L1HeadTooOld.selector); factory.create(GAME_TYPE, ROOT_CLAIM, _extraData); @@ -138,8 +139,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// For now, it is critical that the first proposed output root of an OP stack /// chain is done so by an honest party. function test_initialize_firstOutput_reverts() public { + uint256 submissionInterval = l2OutputOracle.submissionInterval(); vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x11)); - factory.create(GAME_TYPE, ROOT_CLAIM, abi.encode(1800, block.number - 1)); + factory.create(GAME_TYPE, ROOT_CLAIM, abi.encode(submissionInterval, block.number - 1)); } /// @dev Tests that the `create` function reverts when the rootClaim does not disagree with the outcome. @@ -158,12 +160,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Starting (FaultDisputeGame.OutputProposal memory startingProp, FaultDisputeGame.OutputProposal memory disputedProp) = gameProxy.proposals(); - Types.OutputProposal memory starting = oracle.getL2Output(startingProp.index); + Types.OutputProposal memory starting = l2OutputOracle.getL2Output(startingProp.index); assertEq(startingProp.index, 0); assertEq(startingProp.l2BlockNumber, starting.l2BlockNumber); assertEq(Hash.unwrap(startingProp.outputRoot), starting.outputRoot); // Disputed - Types.OutputProposal memory disputed = oracle.getL2Output(disputedProp.index); + Types.OutputProposal memory disputed = l2OutputOracle.getL2Output(disputedProp.index); assertEq(disputedProp.index, 1); assertEq(disputedProp.l2BlockNumber, disputed.l2BlockNumber); assertEq(Hash.unwrap(disputedProp.outputRoot), disputed.outputRoot); @@ -1093,37 +1095,3 @@ contract VariableDivergentPlayer is GamePlayer { trace = _trace; } } - -//////////////////////////////////////////////////////////////// -// MOCK VMS // -//////////////////////////////////////////////////////////////// - -contract AlphabetVM is IBigStepper { - Claim internal immutable ABSOLUTE_PRESTATE; - IPreimageOracle public oracle; - - constructor(Claim _absolutePrestate) { - ABSOLUTE_PRESTATE = _absolutePrestate; - oracle = new PreimageOracle(); - } - - /// @inheritdoc IBigStepper - function step(bytes calldata _stateData, bytes calldata, uint256) external view returns (bytes32 postState_) { - uint256 traceIndex; - uint256 claim; - if ((keccak256(_stateData) << 8) == (Claim.unwrap(ABSOLUTE_PRESTATE) << 8)) { - // If the state data is empty, then the absolute prestate is the claim. - traceIndex = 0; - (claim) = abi.decode(_stateData, (uint256)); - } else { - // Otherwise, decode the state data. - (traceIndex, claim) = abi.decode(_stateData, (uint256, uint256)); - traceIndex++; - } - // STF: n -> n + 1 - postState_ = keccak256(abi.encode(traceIndex, claim + 1)); - assembly { - postState_ := or(and(postState_, not(shl(248, 0xFF))), shl(248, 1)) - } - } -} diff --git a/packages/contracts-bedrock/test/FeeVault.t.sol b/packages/contracts-bedrock/test/FeeVault.t.sol index 3b877840935c..98de40421442 100644 --- a/packages/contracts-bedrock/test/FeeVault.t.sol +++ b/packages/contracts-bedrock/test/FeeVault.t.sol @@ -2,49 +2,24 @@ pragma solidity 0.8.15; // Testing utilities -import { Bridge_Initializer } from "test/CommonTest.t.sol"; -import { BaseFeeVault } from "src/L2/BaseFeeVault.sol"; -import { StandardBridge } from "src/universal/StandardBridge.sol"; - -// Libraries -import { Predeploys } from "src/libraries/Predeploys.sol"; - -// Target contract dependencies -import { FeeVault } from "src/universal/FeeVault.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; // Target contract -import { L1FeeVault } from "src/L2/L1FeeVault.sol"; +import { FeeVault } from "src/universal/FeeVault.sol"; // Test the implementations of the FeeVault contract FeeVault_Test is Bridge_Initializer { - BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT)); - L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT)); - - uint256 constant otherMinimumWithdrawalAmount = 10 ether; - - /// @dev Sets up the test suite. - function setUp() public override { - super.setUp(); - vm.etch( - Predeploys.BASE_FEE_VAULT, - address(new BaseFeeVault(alice, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L1)).code - ); - vm.etch( - Predeploys.L1_FEE_VAULT, - address(new L1FeeVault(bob, otherMinimumWithdrawalAmount, FeeVault.WithdrawalNetwork.L2)).code - ); - - vm.label(Predeploys.BASE_FEE_VAULT, "BaseFeeVault"); - vm.label(Predeploys.L1_FEE_VAULT, "L1FeeVault"); + /// @dev Tests that the constructor sets the correct values. + function test_constructor_l1FeeVault_succeeds() external { + assertEq(l1FeeVault.RECIPIENT(), cfg.l1FeeVaultRecipient()); + assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), cfg.l1FeeVaultMinimumWithdrawalAmount()); + assertEq(uint8(l1FeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L2)); } /// @dev Tests that the constructor sets the correct values. - function test_constructor_succeeds() external { - assertEq(baseFeeVault.RECIPIENT(), alice); - assertEq(l1FeeVault.RECIPIENT(), bob); - assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), NON_ZERO_VALUE); - assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), otherMinimumWithdrawalAmount); + function test_constructor_baseFeeVault_succeeds() external { + assertEq(baseFeeVault.RECIPIENT(), cfg.baseFeeVaultRecipient()); + assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), cfg.baseFeeVaultMinimumWithdrawalAmount()); assertEq(uint8(baseFeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L1)); - assertEq(uint8(l1FeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L2)); } } diff --git a/packages/contracts-bedrock/test/GasPriceOracle.t.sol b/packages/contracts-bedrock/test/GasPriceOracle.t.sol index 26e571ecb550..5e9d71e7baa5 100644 --- a/packages/contracts-bedrock/test/GasPriceOracle.t.sol +++ b/packages/contracts-bedrock/test/GasPriceOracle.t.sol @@ -2,22 +2,13 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; - -// Target contract dependencies -import { L1Block } from "src/L2/L1Block.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; - -// Target contract -import { GasPriceOracle } from "src/L2/GasPriceOracle.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; contract GasPriceOracle_Test is CommonTest { event OverheadUpdated(uint256); event ScalarUpdated(uint256); event DecimalsUpdated(uint256); - GasPriceOracle gasOracle; - L1Block l1Block; address depositor; // The initial L1 context values @@ -33,17 +24,9 @@ contract GasPriceOracle_Test is CommonTest { /// @dev Sets up the test suite. function setUp() public virtual override { super.setUp(); - // place the L1Block contract at the predeploy address - vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code); - l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES); depositor = l1Block.DEPOSITOR_ACCOUNT(); - // We are not setting the gas oracle at its predeploy - // address for simplicity purposes. Nothing in this test - // requires it to be at a particular address - gasOracle = new GasPriceOracle(); - vm.prank(depositor); l1Block.setL1BlockValues({ _number: number, @@ -59,43 +42,43 @@ contract GasPriceOracle_Test is CommonTest { /// @dev Tests that `l1BaseFee` is set correctly. function test_l1BaseFee_succeeds() external { - assertEq(gasOracle.l1BaseFee(), basefee); + assertEq(gasPriceOracle.l1BaseFee(), basefee); } /// @dev Tests that `gasPrice` is set correctly. function test_gasPrice_succeeds() external { vm.fee(100); - uint256 gasPrice = gasOracle.gasPrice(); + uint256 gasPrice = gasPriceOracle.gasPrice(); assertEq(gasPrice, 100); } /// @dev Tests that `baseFee` is set correctly. function test_baseFee_succeeds() external { vm.fee(64); - uint256 gasPrice = gasOracle.baseFee(); + uint256 gasPrice = gasPriceOracle.baseFee(); assertEq(gasPrice, 64); } /// @dev Tests that `scalar` is set correctly. function test_scalar_succeeds() external { - assertEq(gasOracle.scalar(), l1FeeScalar); + assertEq(gasPriceOracle.scalar(), l1FeeScalar); } /// @dev Tests that `overhead` is set correctly. function test_overhead_succeeds() external { - assertEq(gasOracle.overhead(), l1FeeOverhead); + assertEq(gasPriceOracle.overhead(), l1FeeOverhead); } /// @dev Tests that `decimals` is set correctly. function test_decimals_succeeds() external { - assertEq(gasOracle.decimals(), 6); - assertEq(gasOracle.DECIMALS(), 6); + assertEq(gasPriceOracle.decimals(), 6); + assertEq(gasPriceOracle.DECIMALS(), 6); } /// @dev Tests that `setGasPrice` reverts since it was removed in bedrock. function test_setGasPrice_doesNotExist_reverts() external { (bool success, bytes memory returndata) = - address(gasOracle).call(abi.encodeWithSignature("setGasPrice(uint256)", 1)); + address(gasPriceOracle).call(abi.encodeWithSignature("setGasPrice(uint256)", 1)); assertEq(success, false); assertEq(returndata, hex""); @@ -104,7 +87,7 @@ contract GasPriceOracle_Test is CommonTest { /// @dev Tests that `setL1BaseFee` reverts since it was removed in bedrock. function test_setL1BaseFee_doesNotExist_reverts() external { (bool success, bytes memory returndata) = - address(gasOracle).call(abi.encodeWithSignature("setL1BaseFee(uint256)", 1)); + address(gasPriceOracle).call(abi.encodeWithSignature("setL1BaseFee(uint256)", 1)); assertEq(success, false); assertEq(returndata, hex""); diff --git a/packages/contracts-bedrock/test/GovernanceToken.t.sol b/packages/contracts-bedrock/test/GovernanceToken.t.sol index ec3c7902af7e..93f0585b3ee0 100644 --- a/packages/contracts-bedrock/test/GovernanceToken.t.sol +++ b/packages/contracts-bedrock/test/GovernanceToken.t.sol @@ -2,41 +2,37 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; - -// Target contract -import { GovernanceToken } from "src/governance/GovernanceToken.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; contract GovernanceToken_Test is CommonTest { - address constant owner = address(0x1234); - address constant rando = address(0x5678); - GovernanceToken internal gov; + address owner; + address rando; /// @dev Sets up the test suite. function setUp() public virtual override { super.setUp(); - vm.prank(owner); - gov = new GovernanceToken(); + owner = governanceToken.owner(); + rando = makeAddr("rando"); } /// @dev Tests that the constructor sets the correct initial state. function test_constructor_succeeds() external { - assertEq(gov.owner(), owner); - assertEq(gov.name(), "Optimism"); - assertEq(gov.symbol(), "OP"); - assertEq(gov.decimals(), 18); - assertEq(gov.totalSupply(), 0); + assertEq(governanceToken.owner(), owner); + assertEq(governanceToken.name(), "Optimism"); + assertEq(governanceToken.symbol(), "OP"); + assertEq(governanceToken.decimals(), 18); + assertEq(governanceToken.totalSupply(), 0); } /// @dev Tests that the owner can successfully call `mint`. function test_mint_fromOwner_succeeds() external { // Mint 100 tokens. vm.prank(owner); - gov.mint(owner, 100); + governanceToken.mint(owner, 100); // Balances have updated correctly. - assertEq(gov.balanceOf(owner), 100); - assertEq(gov.totalSupply(), 100); + assertEq(governanceToken.balanceOf(owner), 100); + assertEq(governanceToken.totalSupply(), 100); } /// @dev Tests that `mint` reverts when called by a non-owner. @@ -44,130 +40,130 @@ contract GovernanceToken_Test is CommonTest { // Mint 100 tokens as rando. vm.prank(rando); vm.expectRevert("Ownable: caller is not the owner"); - gov.mint(owner, 100); + governanceToken.mint(owner, 100); // Balance does not update. - assertEq(gov.balanceOf(owner), 0); - assertEq(gov.totalSupply(), 0); + assertEq(governanceToken.balanceOf(owner), 0); + assertEq(governanceToken.totalSupply(), 0); } /// @dev Tests that the owner can successfully call `burn`. function test_burn_succeeds() external { // Mint 100 tokens to rando. vm.prank(owner); - gov.mint(rando, 100); + governanceToken.mint(rando, 100); // Rando burns their tokens. vm.prank(rando); - gov.burn(50); + governanceToken.burn(50); // Balances have updated correctly. - assertEq(gov.balanceOf(rando), 50); - assertEq(gov.totalSupply(), 50); + assertEq(governanceToken.balanceOf(rando), 50); + assertEq(governanceToken.totalSupply(), 50); } /// @dev Tests that the owner can successfully call `burnFrom`. function test_burnFrom_succeeds() external { // Mint 100 tokens to rando. vm.prank(owner); - gov.mint(rando, 100); + governanceToken.mint(rando, 100); // Rando approves owner to burn 50 tokens. vm.prank(rando); - gov.approve(owner, 50); + governanceToken.approve(owner, 50); // Owner burns 50 tokens from rando. vm.prank(owner); - gov.burnFrom(rando, 50); + governanceToken.burnFrom(rando, 50); // Balances have updated correctly. - assertEq(gov.balanceOf(rando), 50); - assertEq(gov.totalSupply(), 50); + assertEq(governanceToken.balanceOf(rando), 50); + assertEq(governanceToken.totalSupply(), 50); } /// @dev Tests that `transfer` correctly transfers tokens. function test_transfer_succeeds() external { // Mint 100 tokens to rando. vm.prank(owner); - gov.mint(rando, 100); + governanceToken.mint(rando, 100); // Rando transfers 50 tokens to owner. vm.prank(rando); - gov.transfer(owner, 50); + governanceToken.transfer(owner, 50); // Balances have updated correctly. - assertEq(gov.balanceOf(owner), 50); - assertEq(gov.balanceOf(rando), 50); - assertEq(gov.totalSupply(), 100); + assertEq(governanceToken.balanceOf(owner), 50); + assertEq(governanceToken.balanceOf(rando), 50); + assertEq(governanceToken.totalSupply(), 100); } /// @dev Tests that `approve` correctly sets allowances. function test_approve_succeeds() external { // Mint 100 tokens to rando. vm.prank(owner); - gov.mint(rando, 100); + governanceToken.mint(rando, 100); // Rando approves owner to spend 50 tokens. vm.prank(rando); - gov.approve(owner, 50); + governanceToken.approve(owner, 50); // Allowances have updated. - assertEq(gov.allowance(rando, owner), 50); + assertEq(governanceToken.allowance(rando, owner), 50); } /// @dev Tests that `transferFrom` correctly transfers tokens. function test_transferFrom_succeeds() external { // Mint 100 tokens to rando. vm.prank(owner); - gov.mint(rando, 100); + governanceToken.mint(rando, 100); // Rando approves owner to spend 50 tokens. vm.prank(rando); - gov.approve(owner, 50); + governanceToken.approve(owner, 50); // Owner transfers 50 tokens from rando to owner. vm.prank(owner); - gov.transferFrom(rando, owner, 50); + governanceToken.transferFrom(rando, owner, 50); // Balances have updated correctly. - assertEq(gov.balanceOf(owner), 50); - assertEq(gov.balanceOf(rando), 50); - assertEq(gov.totalSupply(), 100); + assertEq(governanceToken.balanceOf(owner), 50); + assertEq(governanceToken.balanceOf(rando), 50); + assertEq(governanceToken.totalSupply(), 100); } /// @dev Tests that `increaseAllowance` correctly increases allowances. function test_increaseAllowance_succeeds() external { // Mint 100 tokens to rando. vm.prank(owner); - gov.mint(rando, 100); + governanceToken.mint(rando, 100); // Rando approves owner to spend 50 tokens. vm.prank(rando); - gov.approve(owner, 50); + governanceToken.approve(owner, 50); // Rando increases allowance by 50 tokens. vm.prank(rando); - gov.increaseAllowance(owner, 50); + governanceToken.increaseAllowance(owner, 50); // Allowances have updated. - assertEq(gov.allowance(rando, owner), 100); + assertEq(governanceToken.allowance(rando, owner), 100); } /// @dev Tests that `decreaseAllowance` correctly decreases allowances. function test_decreaseAllowance_succeeds() external { // Mint 100 tokens to rando. vm.prank(owner); - gov.mint(rando, 100); + governanceToken.mint(rando, 100); // Rando approves owner to spend 100 tokens. vm.prank(rando); - gov.approve(owner, 100); + governanceToken.approve(owner, 100); // Rando decreases allowance by 50 tokens. vm.prank(rando); - gov.decreaseAllowance(owner, 50); + governanceToken.decreaseAllowance(owner, 50); // Allowances have updated. - assertEq(gov.allowance(rando, owner), 50); + assertEq(governanceToken.allowance(rando, owner), 50); } } diff --git a/packages/contracts-bedrock/test/Hashing.t.sol b/packages/contracts-bedrock/test/Hashing.t.sol index fc79c24422bd..98fa7ae485a0 100644 --- a/packages/contracts-bedrock/test/Hashing.t.sol +++ b/packages/contracts-bedrock/test/Hashing.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { Types } from "src/libraries/Types.sol"; diff --git a/packages/contracts-bedrock/test/Helpers.sol b/packages/contracts-bedrock/test/Helpers.sol deleted file mode 100644 index a27da6e2b2fb..000000000000 --- a/packages/contracts-bedrock/test/Helpers.sol +++ /dev/null @@ -1,221 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol"; -import { ERC721 } from "@rari-capital/solmate/src/tokens/ERC721.sol"; -import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import { OptimistInviter } from "src/periphery/op-nft/OptimistInviter.sol"; -import { IERC1271 } from "@openzeppelin/contracts/interfaces/IERC1271.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { ECDSAUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; -import { AdminFaucetAuthModule } from "src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol"; - -contract TestERC20 is ERC20 { - constructor() ERC20("TEST", "TST", 18) { } - - function mint(address to, uint256 value) public { - _mint(to, value); - } -} - -contract TestERC721 is ERC721 { - constructor() ERC721("TEST", "TST") { } - - function mint(address to, uint256 tokenId) public { - _mint(to, tokenId); - } - - function tokenURI(uint256) public pure virtual override returns (string memory) { } -} - -contract CallRecorder { - struct CallInfo { - address sender; - bytes data; - uint256 gas; - uint256 value; - } - - CallInfo public lastCall; - - function record() public payable { - lastCall.sender = msg.sender; - lastCall.data = msg.data; - lastCall.gas = gasleft(); - lastCall.value = msg.value; - } -} - -contract Reverter { - function doRevert() public pure { - revert("Reverter reverted"); - } -} - -contract SimpleStorage { - mapping(bytes32 => bytes32) public db; - - function set(bytes32 _key, bytes32 _value) public payable { - db[_key] = _value; - } - - function get(bytes32 _key) public view returns (bytes32) { - return db[_key]; - } -} - -/// @notice Simple helper contract that helps with testing flow and signature for -/// OptimistInviter contract. Made this a separate contract instead of including -/// in OptimistInviter.t.sol for reusability. -contract OptimistInviterHelper { - /// @notice EIP712 typehash for the ClaimableInvite type. - bytes32 public constant CLAIMABLE_INVITE_TYPEHASH = keccak256("ClaimableInvite(address issuer,bytes32 nonce)"); - - /// @notice EIP712 typehash for the EIP712Domain type that is included as part of the signature. - bytes32 public constant EIP712_DOMAIN_TYPEHASH = - keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); - - /// @notice Address of OptimistInviter contract we are testing. - OptimistInviter public optimistInviter; - - /// @notice OptimistInviter contract name. Used to construct the EIP-712 domain. - string public name; - - /// @notice Keeps track of current nonce to generate new nonces for each invite. - uint256 public currentNonce; - - constructor(OptimistInviter _optimistInviter, string memory _name) { - optimistInviter = _optimistInviter; - name = _name; - } - - /// @notice Returns the hash of the struct ClaimableInvite. - /// @param _claimableInvite ClaimableInvite struct to hash. - /// @return EIP-712 typed struct hash. - function getClaimableInviteStructHash(OptimistInviter.ClaimableInvite memory _claimableInvite) - public - pure - returns (bytes32) - { - return keccak256(abi.encode(CLAIMABLE_INVITE_TYPEHASH, _claimableInvite.issuer, _claimableInvite.nonce)); - } - - /// @notice Returns a bytes32 nonce that should change everytime. In practice, people should use - /// pseudorandom nonces. - /// @return Nonce that should be used as part of ClaimableInvite. - function consumeNonce() public returns (bytes32) { - return bytes32(keccak256(abi.encode(currentNonce++))); - } - - /// @notice Returns a ClaimableInvite with the issuer and current nonce. - /// @param _issuer Issuer to include in the ClaimableInvite. - /// @return ClaimableInvite that can be hashed & signed. - function getClaimableInviteWithNewNonce(address _issuer) public returns (OptimistInviter.ClaimableInvite memory) { - return OptimistInviter.ClaimableInvite(_issuer, consumeNonce()); - } - - /// @notice Computes the EIP712 digest with default correct parameters. - /// @param _claimableInvite ClaimableInvite struct to hash. - /// @return EIP-712 compatible digest. - function getDigest(OptimistInviter.ClaimableInvite calldata _claimableInvite) public view returns (bytes32) { - return getDigestWithEIP712Domain( - _claimableInvite, - bytes(name), - bytes(optimistInviter.EIP712_VERSION()), - block.chainid, - address(optimistInviter) - ); - } - - /// @notice Computes the EIP712 digest with the given domain parameters. - /// Used for testing that different domain parameters fail. - /// @param _claimableInvite ClaimableInvite struct to hash. - /// @param _name Contract name to use in the EIP712 domain. - /// @param _version Contract version to use in the EIP712 domain. - /// @param _chainid Chain ID to use in the EIP712 domain. - /// @param _verifyingContract Address to use in the EIP712 domain. - /// @return EIP-712 compatible digest. - function getDigestWithEIP712Domain( - OptimistInviter.ClaimableInvite calldata _claimableInvite, - bytes memory _name, - bytes memory _version, - uint256 _chainid, - address _verifyingContract - ) - public - pure - returns (bytes32) - { - bytes32 domainSeparator = keccak256( - abi.encode(EIP712_DOMAIN_TYPEHASH, keccak256(_name), keccak256(_version), _chainid, _verifyingContract) - ); - return ECDSA.toTypedDataHash(domainSeparator, getClaimableInviteStructHash(_claimableInvite)); - } -} - -/// @notice Simple ERC1271 wallet that can be used to test the ERC1271 signature checker. -/// @notice https://github.com/OpenZeppelin/openzeppelin-contracts/ -/// blob/master/contracts/mocks/ERC1271WalletMock.sol -contract TestERC1271Wallet is Ownable, IERC1271 { - constructor(address originalOwner) { - transferOwnership(originalOwner); - } - - function isValidSignature(bytes32 hash, bytes memory signature) public view override returns (bytes4 magicValue) { - return ECDSA.recover(hash, signature) == owner() ? this.isValidSignature.selector : bytes4(0); - } -} - -/// @notice Simple helper contract that helps with testing the Faucet contract. -contract FaucetHelper { - /// @notice EIP712 typehash for the Proof type. - bytes32 public constant PROOF_TYPEHASH = keccak256("Proof(address recipient,bytes32 nonce,bytes32 id)"); - - /// @notice EIP712 typehash for the EIP712Domain type that is included as part of the signature. - bytes32 public constant EIP712_DOMAIN_TYPEHASH = - keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); - - /// @notice Keeps track of current nonce to generate new nonces for each drip. - uint256 public currentNonce; - - /// @notice Returns a bytes32 nonce that should change everytime. In practice, people should use - /// pseudorandom nonces. - /// @return Nonce that should be used as part of drip parameters. - function consumeNonce() public returns (bytes32) { - return bytes32(keccak256(abi.encode(currentNonce++))); - } - - /// @notice Returns the hash of the struct Proof. - /// @param _proof Proof struct to hash. - /// @return EIP-712 typed struct hash. - function getProofStructHash(AdminFaucetAuthModule.Proof memory _proof) public pure returns (bytes32) { - return keccak256(abi.encode(PROOF_TYPEHASH, _proof.recipient, _proof.nonce, _proof.id)); - } - - /// @notice Computes the EIP712 digest with the given domain parameters. - /// Used for testing that different domain parameters fail. - /// @param _proof Proof struct to hash. - /// @param _name Contract name to use in the EIP712 domain. - /// @param _version Contract version to use in the EIP712 domain. - /// @param _chainid Chain ID to use in the EIP712 domain. - /// @param _verifyingContract Address to use in the EIP712 domain. - /// @param _verifyingContract Address to use in the EIP712 domain. - /// @param _verifyingContract Address to use in the EIP712 domain. - /// @return EIP-712 compatible digest. - function getDigestWithEIP712Domain( - AdminFaucetAuthModule.Proof memory _proof, - bytes memory _name, - bytes memory _version, - uint256 _chainid, - address _verifyingContract - ) - public - pure - returns (bytes32) - { - bytes32 domainSeparator = keccak256( - abi.encode(EIP712_DOMAIN_TYPEHASH, keccak256(_name), keccak256(_version), _chainid, _verifyingContract) - ); - return ECDSAUpgradeable.toTypedDataHash(domainSeparator, getProofStructHash(_proof)); - } -} diff --git a/packages/contracts-bedrock/test/Initializable.t.sol b/packages/contracts-bedrock/test/Initializable.t.sol index e96989d8f680..a9daa7785a03 100644 --- a/packages/contracts-bedrock/test/Initializable.t.sol +++ b/packages/contracts-bedrock/test/Initializable.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol"; -import { console } from "forge-std/console.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; @@ -13,19 +12,19 @@ import { OptimismPortal } from "src/L1/OptimismPortal.sol"; /// @dev Ensures that the `initialize()` function on contracts cannot be called more than /// once. This contract inherits from `ERC721Bridge_Initializer` because it is the /// deepest contract in the inheritance chain for setting up the system contracts. -contract Initializer_Test is ERC721Bridge_Initializer { +contract Initializer_Test is Bridge_Initializer { function test_cannotReinitializeL1_succeeds() public { vm.expectRevert("Initializable: contract is already initialized"); - L1Messenger.initialize(OptimismPortal(payable(address(0)))); + l1CrossDomainMessenger.initialize(OptimismPortal(payable(address(0)))); vm.expectRevert("Initializable: contract is already initialized"); - L1Bridge.initialize(CrossDomainMessenger(address(0))); + l1StandardBridge.initialize(CrossDomainMessenger(address(0))); vm.expectRevert("Initializable: contract is already initialized"); - oracle.initialize(0, 0, address(0), address(0)); + l2OutputOracle.initialize(0, 0, address(0), address(0)); vm.expectRevert("Initializable: contract is already initialized"); - op.initialize(L2OutputOracle(address(0)), address(0), SystemConfig(address(0)), false); + optimismPortal.initialize(L2OutputOracle(address(0)), address(0), SystemConfig(address(0)), false); vm.expectRevert("Initializable: contract is already initialized"); systemConfig.initialize({ @@ -56,6 +55,6 @@ contract Initializer_Test is ERC721Bridge_Initializer { }); vm.expectRevert("Initializable: contract is already initialized"); - L1NFTBridge.initialize(CrossDomainMessenger(address(0))); + l1ERC721Bridge.initialize(CrossDomainMessenger(address(0))); } } diff --git a/packages/contracts-bedrock/test/L1Block.t.sol b/packages/contracts-bedrock/test/L1Block.t.sol index f44f606a6270..c62a32e446f9 100644 --- a/packages/contracts-bedrock/test/L1Block.t.sol +++ b/packages/contracts-bedrock/test/L1Block.t.sol @@ -2,27 +2,25 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; // Target contract import { L1Block } from "src/L2/L1Block.sol"; contract L1BlockTest is CommonTest { - L1Block lb; address depositor; - bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1)); /// @dev Sets up the test suite. function setUp() public virtual override { super.setUp(); - lb = new L1Block(); - depositor = lb.DEPOSITOR_ACCOUNT(); + + depositor = l1Block.DEPOSITOR_ACCOUNT(); vm.prank(depositor); - lb.setL1BlockValues({ + l1Block.setL1BlockValues({ _number: uint64(1), _timestamp: uint64(2), _basefee: 3, - _hash: NON_ZERO_HASH, + _hash: keccak256(abi.encode(block.number)), _sequenceNumber: uint64(4), _batcherHash: bytes32(0), _l1FeeOverhead: 2, @@ -44,46 +42,46 @@ contract L1BlockTest is CommonTest { external { vm.prank(depositor); - lb.setL1BlockValues(n, t, b, h, s, bt, fo, fs); - assertEq(lb.number(), n); - assertEq(lb.timestamp(), t); - assertEq(lb.basefee(), b); - assertEq(lb.hash(), h); - assertEq(lb.sequenceNumber(), s); - assertEq(lb.batcherHash(), bt); - assertEq(lb.l1FeeOverhead(), fo); - assertEq(lb.l1FeeScalar(), fs); + l1Block.setL1BlockValues(n, t, b, h, s, bt, fo, fs); + assertEq(l1Block.number(), n); + assertEq(l1Block.timestamp(), t); + assertEq(l1Block.basefee(), b); + assertEq(l1Block.hash(), h); + assertEq(l1Block.sequenceNumber(), s); + assertEq(l1Block.batcherHash(), bt); + assertEq(l1Block.l1FeeOverhead(), fo); + assertEq(l1Block.l1FeeScalar(), fs); } /// @dev Tests that `number` returns the correct value. function test_number_succeeds() external { - assertEq(lb.number(), uint64(1)); + assertEq(l1Block.number(), uint64(1)); } /// @dev Tests that `timestamp` returns the correct value. function test_timestamp_succeeds() external { - assertEq(lb.timestamp(), uint64(2)); + assertEq(l1Block.timestamp(), uint64(2)); } /// @dev Tests that `basefee` returns the correct value. function test_basefee_succeeds() external { - assertEq(lb.basefee(), 3); + assertEq(l1Block.basefee(), 3); } /// @dev Tests that `hash` returns the correct value. function test_hash_succeeds() external { - assertEq(lb.hash(), NON_ZERO_HASH); + assertEq(l1Block.hash(), keccak256(abi.encode(block.number))); } /// @dev Tests that `sequenceNumber` returns the correct value. function test_sequenceNumber_succeeds() external { - assertEq(lb.sequenceNumber(), uint64(4)); + assertEq(l1Block.sequenceNumber(), uint64(4)); } /// @dev Tests that `setL1BlockValues` can set max values. function test_updateValues_succeeds() external { vm.prank(depositor); - lb.setL1BlockValues({ + l1Block.setL1BlockValues({ _number: type(uint64).max, _timestamp: type(uint64).max, _basefee: type(uint256).max, diff --git a/packages/contracts-bedrock/test/L1CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L1CrossDomainMessenger.t.sol index 77f966f310d6..bf49d25f5224 100644 --- a/packages/contracts-bedrock/test/L1CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L1CrossDomainMessenger.t.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.15; // Testing utilities -import { Messenger_Initializer, Reverter, ConfigurableCaller } from "test/CommonTest.t.sol"; -import { L2OutputOracle_Initializer } from "test/L2OutputOracle.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; +import { Reverter, ConfigurableCaller } from "test/mocks/Callers.sol"; // Libraries import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; @@ -12,13 +12,9 @@ import { Hashing } from "src/libraries/Hashing.sol"; import { Encoding } from "src/libraries/Encoding.sol"; // Target contract dependencies -import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; import { OptimismPortal } from "src/L1/OptimismPortal.sol"; -// Target contract -import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; - -contract L1CrossDomainMessenger_Test is Messenger_Initializer { +contract L1CrossDomainMessenger_Test is Bridge_Initializer { /// @dev The receiver address address recipient = address(0xabbaacdc); @@ -27,8 +23,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { /// @dev Tests that the version can be decoded from the message nonce. function test_messageVersion_succeeds() external { - (, uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce()); - assertEq(version, L1Messenger.MESSAGE_VERSION()); + (, uint16 version) = Encoding.decodeVersionedNonce(l1CrossDomainMessenger.messageNonce()); + assertEq(version, l1CrossDomainMessenger.MESSAGE_VERSION()); } /// @dev Tests that the sendMessage function is able to send a single message. @@ -37,55 +33,57 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { function test_sendMessage_succeeds() external { // deposit transaction on the optimism portal should be called vm.expectCall( - address(op), + address(optimismPortal), abi.encodeWithSelector( OptimismPortal.depositTransaction.selector, Predeploys.L2_CROSS_DOMAIN_MESSENGER, 0, - L1Messenger.baseGas(hex"ff", 100), + l1CrossDomainMessenger.baseGas(hex"ff", 100), false, - Encoding.encodeCrossDomainMessage(L1Messenger.messageNonce(), alice, recipient, 0, 100, hex"ff") + Encoding.encodeCrossDomainMessage( + l1CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff" + ) ) ); // TransactionDeposited event vm.expectEmit(true, true, true, true); emitTransactionDeposited( - AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)), + AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)), Predeploys.L2_CROSS_DOMAIN_MESSENGER, 0, 0, - L1Messenger.baseGas(hex"ff", 100), + l1CrossDomainMessenger.baseGas(hex"ff", 100), false, - Encoding.encodeCrossDomainMessage(L1Messenger.messageNonce(), alice, recipient, 0, 100, hex"ff") + Encoding.encodeCrossDomainMessage(l1CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff") ); // SentMessage event vm.expectEmit(true, true, true, true); - emit SentMessage(recipient, alice, hex"ff", L1Messenger.messageNonce(), 100); + emit SentMessage(recipient, alice, hex"ff", l1CrossDomainMessenger.messageNonce(), 100); // SentMessageExtension1 event vm.expectEmit(true, true, true, true); emit SentMessageExtension1(alice, 0); vm.prank(alice); - L1Messenger.sendMessage(recipient, hex"ff", uint32(100)); + l1CrossDomainMessenger.sendMessage(recipient, hex"ff", uint32(100)); } /// @dev Tests that the sendMessage function is able to send /// the same message twice. function test_sendMessage_twice_succeeds() external { - uint256 nonce = L1Messenger.messageNonce(); - L1Messenger.sendMessage(recipient, hex"aa", uint32(500_000)); - L1Messenger.sendMessage(recipient, hex"aa", uint32(500_000)); + uint256 nonce = l1CrossDomainMessenger.messageNonce(); + l1CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000)); + l1CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000)); // the nonce increments for each message sent - assertEq(nonce + 2, L1Messenger.messageNonce()); + assertEq(nonce + 2, l1CrossDomainMessenger.messageNonce()); } /// @dev Tests that the xDomainMessageSender reverts when not set. function test_xDomainSender_notSet_reverts() external { vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); - L1Messenger.xDomainMessageSender(); + l1CrossDomainMessenger.xDomainMessageSender(); } /// @dev Tests that the relayMessage function reverts when @@ -95,14 +93,14 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); + vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); // Expect a revert. vm.expectRevert("CrossDomainMessenger: only version 0 or 1 messages are supported at this time"); // Try to relay a v2 message. - vm.prank(address(op)); - L2Messenger.relayMessage( + vm.prank(address(optimismPortal)); + l2CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 2 }), // nonce sender, target, @@ -121,8 +119,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { vm.expectCall(target, hex"1111"); // set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); - vm.prank(address(op)); + vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); + vm.prank(address(optimismPortal)); vm.expectEmit(true, true, true, true); @@ -132,7 +130,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { emit RelayedMessage(hash); - L1Messenger.relayMessage( + l1CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce sender, target, @@ -142,28 +140,28 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // the message hash is in the successfulMessages mapping - assert(L1Messenger.successfulMessages(hash)); + assert(l1CrossDomainMessenger.successfulMessages(hash)); // it is not in the received messages mapping - assertEq(L1Messenger.failedMessages(hash), false); + assertEq(l1CrossDomainMessenger.failedMessages(hash), false); } /// @dev Tests that relayMessage reverts if attempting to relay a message /// sent to an L1 system contract. function test_relayMessage_toSystemContract_reverts() external { // set the target to be the OptimismPortal - address target = address(op); + address target = address(optimismPortal); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; bytes memory message = hex"1111"; - vm.prank(address(op)); + vm.prank(address(optimismPortal)); vm.expectRevert("CrossDomainMessenger: message cannot be replayed"); - L1Messenger.relayMessage( + l1CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, 0, 0, message ); - vm.store(address(op), 0, bytes32(abi.encode(sender))); + vm.store(address(optimismPortal), 0, bytes32(abi.encode(sender))); vm.expectRevert("CrossDomainMessenger: message cannot be replayed"); - L1Messenger.relayMessage( + l1CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, 0, 0, message ); } @@ -176,7 +174,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { bytes memory message = hex"1111"; vm.expectRevert("CrossDomainMessenger: value must be zero unless message is from a system address"); - L1Messenger.relayMessage{ value: 100 }( + l1CrossDomainMessenger.relayMessage{ value: 100 }( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, 0, 0, message ); } @@ -185,18 +183,18 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { /// after a message is relayed. function test_xDomainMessageSender_reset_succeeds() external { vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); - L1Messenger.xDomainMessageSender(); + l1CrossDomainMessenger.xDomainMessageSender(); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; - vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); - vm.prank(address(op)); - L1Messenger.relayMessage( + vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); + vm.prank(address(optimismPortal)); + l1CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), address(0), address(0), 0, 0, hex"" ); vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); - L1Messenger.xDomainMessageSender(); + l1CrossDomainMessenger.xDomainMessageSender(); } /// @dev Tests that relayMessage should successfully call the target contract after @@ -213,11 +211,11 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, value, 0, hex"1111" ); - vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); + vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); vm.etch(target, address(new Reverter()).code); - vm.deal(address(op), value); - vm.prank(address(op)); - L1Messenger.relayMessage{ value: value }( + vm.deal(address(optimismPortal), value); + vm.prank(address(optimismPortal)); + l1CrossDomainMessenger.relayMessage{ value: value }( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce sender, target, @@ -226,10 +224,10 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { hex"1111" ); - assertEq(address(L1Messenger).balance, value); + assertEq(address(l1CrossDomainMessenger).balance, value); assertEq(address(target).balance, 0); - assertEq(L1Messenger.successfulMessages(hash), false); - assertEq(L1Messenger.failedMessages(hash), true); + assertEq(l1CrossDomainMessenger.successfulMessages(hash), false); + assertEq(l1CrossDomainMessenger.failedMessages(hash), true); vm.expectEmit(true, true, true, true); @@ -237,7 +235,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { vm.etch(target, address(0).code); vm.prank(address(sender)); - L1Messenger.relayMessage( + l1CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce sender, target, @@ -246,10 +244,10 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { hex"1111" ); - assertEq(address(L1Messenger).balance, 0); + assertEq(address(l1CrossDomainMessenger).balance, 0); assertEq(address(target).balance, value); - assertEq(L1Messenger.successfulMessages(hash), true); - assertEq(L1Messenger.failedMessages(hash), true); + assertEq(l1CrossDomainMessenger.successfulMessages(hash), true); + assertEq(l1CrossDomainMessenger.failedMessages(hash), true); } /// @dev Tests that relayMessage should successfully call the target contract after @@ -271,7 +269,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); + vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); // Target should be called with expected data. vm.expectCall(target, hex"1111"); @@ -281,8 +279,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { emit RelayedMessage(hash); // Relay the message. - vm.prank(address(op)); - L1Messenger.relayMessage( + vm.prank(address(optimismPortal)); + l1CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce sender, target, @@ -292,8 +290,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Message was successfully relayed. - assertEq(L1Messenger.successfulMessages(hash), true); - assertEq(L1Messenger.failedMessages(hash), false); + assertEq(l1CrossDomainMessenger.successfulMessages(hash), true); + assertEq(l1CrossDomainMessenger.failedMessages(hash), false); } /// @dev Tests that relayMessage should revert if the message is already replayed. @@ -313,20 +311,19 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); - + vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); // Mark legacy message as already relayed. uint256 successfulMessagesSlot = 203; bytes32 oldHash = Hashing.hashCrossDomainMessageV0(target, sender, hex"1111", 0); bytes32 slot = keccak256(abi.encode(oldHash, successfulMessagesSlot)); - vm.store(address(L1Messenger), slot, bytes32(uint256(1))); + vm.store(address(l1CrossDomainMessenger), slot, bytes32(uint256(1))); // Expect revert. vm.expectRevert("CrossDomainMessenger: legacy withdrawal already relayed"); // Relay the message. - vm.prank(address(op)); - L1Messenger.relayMessage( + vm.prank(address(optimismPortal)); + l1CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce sender, target, @@ -336,8 +333,8 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Message was not relayed. - assertEq(L1Messenger.successfulMessages(hash), false); - assertEq(L1Messenger.failedMessages(hash), false); + assertEq(l1CrossDomainMessenger.successfulMessages(hash), false); + assertEq(l1CrossDomainMessenger.failedMessages(hash), false); } /// @dev Tests that relayMessage can be retried after a failure with a legacy message. @@ -358,7 +355,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); + vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); // Turn the target into a Reverter. vm.etch(target, address(new Reverter()).code); @@ -371,9 +368,9 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { emit FailedRelayedMessage(hash); // Relay the message. - vm.deal(address(op), value); - vm.prank(address(op)); - L1Messenger.relayMessage{ value: value }( + vm.deal(address(optimismPortal), value); + vm.prank(address(optimismPortal)); + l1CrossDomainMessenger.relayMessage{ value: value }( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce sender, target, @@ -383,10 +380,10 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Message failed. - assertEq(address(L1Messenger).balance, value); + assertEq(address(l1CrossDomainMessenger).balance, value); assertEq(address(target).balance, 0); - assertEq(L1Messenger.successfulMessages(hash), false); - assertEq(L1Messenger.failedMessages(hash), true); + assertEq(l1CrossDomainMessenger.successfulMessages(hash), false); + assertEq(l1CrossDomainMessenger.failedMessages(hash), true); // Make the target not revert anymore. vm.etch(target, address(0).code); @@ -400,7 +397,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { // Retry the message. vm.prank(address(sender)); - L1Messenger.relayMessage( + l1CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce sender, target, @@ -410,10 +407,10 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Message was successfully relayed. - assertEq(address(L1Messenger).balance, 0); + assertEq(address(l1CrossDomainMessenger).balance, 0); assertEq(address(target).balance, value); - assertEq(L1Messenger.successfulMessages(hash), true); - assertEq(L1Messenger.failedMessages(hash), true); + assertEq(l1CrossDomainMessenger.successfulMessages(hash), true); + assertEq(l1CrossDomainMessenger.failedMessages(hash), true); } /// @dev Tests that relayMessage cannot be retried after success with a legacy message. @@ -434,7 +431,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); + vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); // Target should be called with expected data. vm.expectCall(target, hex"1111"); @@ -444,9 +441,9 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { emit RelayedMessage(hash); // Relay the message. - vm.deal(address(op), value); - vm.prank(address(op)); - L1Messenger.relayMessage{ value: value }( + vm.deal(address(optimismPortal), value); + vm.prank(address(optimismPortal)); + l1CrossDomainMessenger.relayMessage{ value: value }( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce sender, target, @@ -456,17 +453,17 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Message was successfully relayed. - assertEq(address(L1Messenger).balance, 0); + assertEq(address(l1CrossDomainMessenger).balance, 0); assertEq(address(target).balance, value); - assertEq(L1Messenger.successfulMessages(hash), true); - assertEq(L1Messenger.failedMessages(hash), false); + assertEq(l1CrossDomainMessenger.successfulMessages(hash), true); + assertEq(l1CrossDomainMessenger.failedMessages(hash), false); // Expect a revert. vm.expectRevert("CrossDomainMessenger: message cannot be replayed"); // Retry the message. vm.prank(address(sender)); - L1Messenger.relayMessage( + l1CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce sender, target, @@ -494,7 +491,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); + vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); // Turn the target into a Reverter. vm.etch(target, address(new Reverter()).code); @@ -503,9 +500,9 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { vm.expectCall(target, hex"1111"); // Relay the message. - vm.deal(address(op), value); - vm.prank(address(op)); - L1Messenger.relayMessage{ value: value }( + vm.deal(address(optimismPortal), value); + vm.prank(address(optimismPortal)); + l1CrossDomainMessenger.relayMessage{ value: value }( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce sender, target, @@ -515,10 +512,10 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Message failed. - assertEq(address(L1Messenger).balance, value); + assertEq(address(l1CrossDomainMessenger).balance, value); assertEq(address(target).balance, 0); - assertEq(L1Messenger.successfulMessages(hash), false); - assertEq(L1Messenger.failedMessages(hash), true); + assertEq(l1CrossDomainMessenger.successfulMessages(hash), false); + assertEq(l1CrossDomainMessenger.failedMessages(hash), true); // Make the target not revert anymore. vm.etch(target, address(0).code); @@ -532,7 +529,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { // Retry the message vm.prank(address(sender)); - L1Messenger.relayMessage( + l1CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce sender, target, @@ -542,17 +539,17 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ); // Message was successfully relayed. - assertEq(address(L1Messenger).balance, 0); + assertEq(address(l1CrossDomainMessenger).balance, 0); assertEq(address(target).balance, value); - assertEq(L1Messenger.successfulMessages(hash), true); - assertEq(L1Messenger.failedMessages(hash), true); + assertEq(l1CrossDomainMessenger.successfulMessages(hash), true); + assertEq(l1CrossDomainMessenger.failedMessages(hash), true); // Expect a revert. vm.expectRevert("CrossDomainMessenger: message has already been relayed"); // Retry the message again. vm.prank(address(sender)); - L1Messenger.relayMessage( + l1CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce sender, target, diff --git a/packages/contracts-bedrock/test/L1ERC721Bridge.t.sol b/packages/contracts-bedrock/test/L1ERC721Bridge.t.sol index b57c8b7ef70d..db7648dfbbb0 100644 --- a/packages/contracts-bedrock/test/L1ERC721Bridge.t.sol +++ b/packages/contracts-bedrock/test/L1ERC721Bridge.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; // Testing utilities -import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; // Target contract dependencies @@ -21,7 +21,7 @@ contract TestERC721 is ERC721 { } } -contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { +contract L1ERC721Bridge_Test is Bridge_Initializer { TestERC721 internal localToken; TestERC721 internal remoteToken; uint256 internal constant tokenId = 1; @@ -56,26 +56,26 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { // Approve the bridge to transfer the token. vm.prank(alice); - localToken.approve(address(L1NFTBridge), tokenId); + localToken.approve(address(l1ERC721Bridge), tokenId); } /// @dev Tests that the constructor sets the correct values. function test_constructor_succeeds() public { - assertEq(address(L1NFTBridge.MESSENGER()), address(L1Messenger)); - assertEq(address(L1NFTBridge.OTHER_BRIDGE()), Predeploys.L2_ERC721_BRIDGE); - assertEq(address(L1NFTBridge.messenger()), address(L1Messenger)); - assertEq(address(L1NFTBridge.otherBridge()), Predeploys.L2_ERC721_BRIDGE); + assertEq(address(l1ERC721Bridge.MESSENGER()), address(l1CrossDomainMessenger)); + assertEq(address(l1ERC721Bridge.OTHER_BRIDGE()), Predeploys.L2_ERC721_BRIDGE); + assertEq(address(l1ERC721Bridge.messenger()), address(l1CrossDomainMessenger)); + assertEq(address(l1ERC721Bridge.otherBridge()), Predeploys.L2_ERC721_BRIDGE); } /// @dev Tests that the ERC721 can be bridged successfully. function test_bridgeERC721_succeeds() public { // Expect a call to the messenger. vm.expectCall( - address(L1Messenger), + address(l1CrossDomainMessenger), abi.encodeCall( - L1Messenger.sendMessage, + l1CrossDomainMessenger.sendMessage, ( - address(L2NFTBridge), + address(l2ERC721Bridge), abi.encodeCall( L2ERC721Bridge.finalizeBridgeERC721, (address(remoteToken), address(localToken), alice, alice, tokenId, hex"5678") @@ -91,11 +91,11 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); - L1NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); + l1ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); // Token is locked in the bridge. - assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), true); - assertEq(localToken.ownerOf(tokenId), address(L1NFTBridge)); + assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), true); + assertEq(localToken.ownerOf(tokenId), address(l1ERC721Bridge)); } /// @dev Tests that the ERC721 bridge reverts for non externally owned accounts. @@ -104,10 +104,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { vm.etch(alice, hex"01"); vm.prank(alice); vm.expectRevert("ERC721Bridge: account is not externally owned"); - L1NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); + l1ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); // Token is not locked in the bridge. - assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false); + assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(localToken.ownerOf(tokenId), alice); } @@ -116,10 +116,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); vm.expectRevert(); - L1NFTBridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678"); + l1ERC721Bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678"); // Token is not locked in the bridge. - assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false); + assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(localToken.ownerOf(tokenId), alice); } @@ -128,10 +128,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); vm.expectRevert("L1ERC721Bridge: remote token cannot be address(0)"); - L1NFTBridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678"); + l1ERC721Bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678"); // Token is not locked in the bridge. - assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false); + assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(localToken.ownerOf(tokenId), alice); } @@ -140,10 +140,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(bob); vm.expectRevert("ERC721: transfer from incorrect owner"); - L1NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); + l1ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); // Token is not locked in the bridge. - assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false); + assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(localToken.ownerOf(tokenId), alice); } @@ -152,9 +152,9 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { function test_bridgeERC721To_succeeds() external { // Expect a call to the messenger. vm.expectCall( - address(L1Messenger), + address(l1CrossDomainMessenger), abi.encodeCall( - L1Messenger.sendMessage, + l1CrossDomainMessenger.sendMessage, ( address(Predeploys.L2_ERC721_BRIDGE), abi.encodeCall( @@ -172,11 +172,11 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); - L1NFTBridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678"); + l1ERC721Bridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678"); // Token is locked in the bridge. - assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), true); - assertEq(localToken.ownerOf(tokenId), address(L1NFTBridge)); + assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), true); + assertEq(localToken.ownerOf(tokenId), address(l1ERC721Bridge)); } /// @dev Tests that the ERC721 bridge reverts for non externally owned accounts @@ -185,10 +185,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); vm.expectRevert(); - L1NFTBridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex"5678"); + l1ERC721Bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex"5678"); // Token is not locked in the bridge. - assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false); + assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(localToken.ownerOf(tokenId), alice); } @@ -198,10 +198,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); vm.expectRevert("L1ERC721Bridge: remote token cannot be address(0)"); - L1NFTBridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678"); + l1ERC721Bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678"); // Token is not locked in the bridge. - assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false); + assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(localToken.ownerOf(tokenId), alice); } @@ -211,10 +211,10 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(bob); vm.expectRevert("ERC721: transfer from incorrect owner"); - L1NFTBridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678"); + l1ERC721Bridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678"); // Token is not locked in the bridge. - assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false); + assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(localToken.ownerOf(tokenId), alice); } @@ -222,7 +222,7 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { function test_finalizeBridgeERC721_succeeds() external { // Bridge the token. vm.prank(alice); - L1NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); + l1ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); // Expect an event to be emitted. vm.expectEmit(true, true, true, true); @@ -230,15 +230,15 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { // Finalize a withdrawal. vm.mockCall( - address(L1Messenger), - abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector), + address(l1CrossDomainMessenger), + abi.encodeWithSelector(l1CrossDomainMessenger.xDomainMessageSender.selector), abi.encode(Predeploys.L2_ERC721_BRIDGE) ); - vm.prank(address(L1Messenger)); - L1NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); + vm.prank(address(l1CrossDomainMessenger)); + l1ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); // Token is not locked in the bridge. - assertEq(L1NFTBridge.deposits(address(localToken), address(remoteToken), tokenId), false); + assertEq(l1ERC721Bridge.deposits(address(localToken), address(remoteToken), tokenId), false); assertEq(localToken.ownerOf(tokenId), alice); } @@ -248,7 +248,7 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { // Finalize a withdrawal. vm.prank(alice); vm.expectRevert("ERC721Bridge: function can only be called from the other bridge"); - L1NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); + l1ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); } /// @dev Tests that the ERC721 bridge finalize reverts when not called @@ -256,11 +256,13 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external { // Finalize a withdrawal. vm.mockCall( - address(L1Messenger), abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector), abi.encode(alice) + address(l1CrossDomainMessenger), + abi.encodeWithSelector(l1CrossDomainMessenger.xDomainMessageSender.selector), + abi.encode(alice) ); - vm.prank(address(L1Messenger)); + vm.prank(address(l1CrossDomainMessenger)); vm.expectRevert("ERC721Bridge: function can only be called from the other bridge"); - L1NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); + l1ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); } /// @dev Tests that the ERC721 bridge finalize reverts when the local token @@ -268,13 +270,15 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { function test_finalizeBridgeERC721_selfToken_reverts() external { // Finalize a withdrawal. vm.mockCall( - address(L1Messenger), - abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector), + address(l1CrossDomainMessenger), + abi.encodeWithSelector(l1CrossDomainMessenger.xDomainMessageSender.selector), abi.encode(Predeploys.L2_ERC721_BRIDGE) ); - vm.prank(address(L1Messenger)); + vm.prank(address(l1CrossDomainMessenger)); vm.expectRevert("L1ERC721Bridge: local token cannot be self"); - L1NFTBridge.finalizeBridgeERC721(address(L1NFTBridge), address(remoteToken), alice, alice, tokenId, hex"5678"); + l1ERC721Bridge.finalizeBridgeERC721( + address(l1ERC721Bridge), address(remoteToken), alice, alice, tokenId, hex"5678" + ); } /// @dev Tests that the ERC721 bridge finalize reverts when the remote token @@ -282,12 +286,12 @@ contract L1ERC721Bridge_Test is ERC721Bridge_Initializer { function test_finalizeBridgeERC721_notEscrowed_reverts() external { // Finalize a withdrawal. vm.mockCall( - address(L1Messenger), - abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector), + address(l1CrossDomainMessenger), + abi.encodeWithSelector(l1CrossDomainMessenger.xDomainMessageSender.selector), abi.encode(Predeploys.L2_ERC721_BRIDGE) ); - vm.prank(address(L1Messenger)); + vm.prank(address(l1CrossDomainMessenger)); vm.expectRevert("L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge"); - L1NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); + l1ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); } } diff --git a/packages/contracts-bedrock/test/L1StandardBridge.t.sol b/packages/contracts-bedrock/test/L1StandardBridge.t.sol index c8966dd8b62f..8ffc4c0f6714 100644 --- a/packages/contracts-bedrock/test/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L1StandardBridge.t.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.15; // Testing utilities import { stdStorage, StdStorage } from "forge-std/Test.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { Bridge_Initializer } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; @@ -22,20 +22,20 @@ import { OptimismPortal } from "src/L1/OptimismPortal.sol"; contract L1StandardBridge_Getter_Test is Bridge_Initializer { /// @dev Test that the accessors return the correct initialized values. function test_getters_succeeds() external view { - assert(L1Bridge.l2TokenBridge() == address(L2Bridge)); - assert(L1Bridge.OTHER_BRIDGE() == L2Bridge); - assert(L1Bridge.messenger() == L1Messenger); - assert(L1Bridge.MESSENGER() == L1Messenger); + assert(l1StandardBridge.l2TokenBridge() == address(l2StandardBridge)); + assert(l1StandardBridge.OTHER_BRIDGE() == l2StandardBridge); + assert(l1StandardBridge.messenger() == l1CrossDomainMessenger); + assert(l1StandardBridge.MESSENGER() == l1CrossDomainMessenger); } } contract L1StandardBridge_Initialize_Test is Bridge_Initializer { /// @dev Test that the initialize function sets the correct values. function test_initialize_succeeds() external { - assertEq(address(L1Bridge.messenger()), address(L1Messenger)); - assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE); - assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE); - bytes32 slot0 = vm.load(address(L1Bridge), bytes32(uint256(0))); + assertEq(address(l1StandardBridge.messenger()), address(l1CrossDomainMessenger)); + assertEq(address(l1StandardBridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE); + assertEq(address(l2StandardBridge), Predeploys.L2_STANDARD_BRIDGE); + bytes32 slot0 = vm.load(address(l1StandardBridge), bytes32(uint256(0))); assertEq(slot0, bytes32(uint256(Constants.INITIALIZER))); } } @@ -45,29 +45,29 @@ contract L1StandardBridge_Initialize_TestFail is Bridge_Initializer { } contract L1StandardBridge_Receive_Test is Bridge_Initializer { /// @dev Tests receive bridges ETH successfully. function test_receive_succeeds() external { - assertEq(address(op).balance, 0); + assertEq(address(optimismPortal).balance, 0); // The legacy event must be emitted for backwards compatibility - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ETHDepositInitiated(alice, alice, 100, hex""); - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ETHBridgeInitiated(alice, alice, 100, hex""); vm.expectCall( - address(L1Messenger), + address(l1CrossDomainMessenger), abi.encodeWithSelector( CrossDomainMessenger.sendMessage.selector, - address(L2Bridge), + address(l2StandardBridge), abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, alice, 100, hex""), 200_000 ) ); vm.prank(alice, alice); - (bool success,) = address(L1Bridge).call{ value: 100 }(hex""); + (bool success,) = address(l1StandardBridge).call{ value: 100 }(hex""); assertEq(success, true); - assertEq(address(op).balance, 100); + assertEq(address(optimismPortal).balance, 100); } } @@ -77,59 +77,76 @@ contract PreBridgeETH is Bridge_Initializer { /// @dev Asserts the expected calls and events for bridging ETH depending /// on whether the bridge call is legacy or not. function _preBridgeETH(bool isLegacy) internal { - assertEq(address(op).balance, 0); - uint256 nonce = L1Messenger.messageNonce(); + assertEq(address(optimismPortal).balance, 0); + uint256 nonce = l1CrossDomainMessenger.messageNonce(); uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION - address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); + address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); bytes memory message = abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, alice, 500, hex"dead"); if (isLegacy) { vm.expectCall( - address(L1Bridge), 500, abi.encodeWithSelector(L1Bridge.depositETH.selector, 50000, hex"dead") + address(l1StandardBridge), + 500, + abi.encodeWithSelector(l1StandardBridge.depositETH.selector, 50000, hex"dead") ); } else { - vm.expectCall(address(L1Bridge), 500, abi.encodeWithSelector(L1Bridge.bridgeETH.selector, 50000, hex"dead")); + vm.expectCall( + address(l1StandardBridge), + 500, + abi.encodeWithSelector(l1StandardBridge.bridgeETH.selector, 50000, hex"dead") + ); } vm.expectCall( - address(L1Messenger), + address(l1CrossDomainMessenger), 500, - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L2Bridge), message, 50000) + abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 50000) ); bytes memory innerMessage = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, nonce, address(L1Bridge), address(L2Bridge), 500, 50000, message + CrossDomainMessenger.relayMessage.selector, + nonce, + address(l1StandardBridge), + address(l2StandardBridge), + 500, + 50000, + message ); - uint64 baseGas = L1Messenger.baseGas(message, 50000); + uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 50000); vm.expectCall( - address(op), + address(optimismPortal), 500, abi.encodeWithSelector( - OptimismPortal.depositTransaction.selector, address(L2Messenger), 500, baseGas, false, innerMessage + OptimismPortal.depositTransaction.selector, + address(l2CrossDomainMessenger), + 500, + baseGas, + false, + innerMessage ) ); bytes memory opaqueData = abi.encodePacked(uint256(500), uint256(500), baseGas, false, innerMessage); - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ETHDepositInitiated(alice, alice, 500, hex"dead"); - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ETHBridgeInitiated(alice, alice, 500, hex"dead"); // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call - vm.expectEmit(true, true, true, true, address(op)); - emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData); + vm.expectEmit(true, true, true, true, address(optimismPortal)); + emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData); // SentMessage event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L1Messenger)); - emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 50000); + vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger)); + emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 50000); // SentMessageExtension1 event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L1Messenger)); - emit SentMessageExtension1(address(L1Bridge), 500); + vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger)); + emit SentMessageExtension1(address(l1StandardBridge), 500); vm.prank(alice, alice); } @@ -143,8 +160,8 @@ contract L1StandardBridge_DepositETH_Test is PreBridgeETH { /// ETH ends up in the optimismPortal. function test_depositETH_succeeds() external { _preBridgeETH({ isLegacy: true }); - L1Bridge.depositETH{ value: 500 }(50000, hex"dead"); - assertEq(address(op).balance, 500); + l1StandardBridge.depositETH{ value: 500 }(50000, hex"dead"); + assertEq(address(optimismPortal).balance, 500); } } @@ -156,8 +173,8 @@ contract L1StandardBridge_BridgeETH_Test is PreBridgeETH { /// ETH ends up in the optimismPortal. function test_bridgeETH_succeeds() external { _preBridgeETH({ isLegacy: false }); - L1Bridge.bridgeETH{ value: 500 }(50000, hex"dead"); - assertEq(address(op).balance, 500); + l1StandardBridge.bridgeETH{ value: 500 }(50000, hex"dead"); + assertEq(address(optimismPortal).balance, 500); } } @@ -167,7 +184,7 @@ contract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer { vm.etch(alice, address(L1Token).code); vm.expectRevert("StandardBridge: function can only be called from an EOA"); vm.prank(alice); - L1Bridge.depositETH{ value: 1 }(300, hex""); + l1StandardBridge.depositETH{ value: 1 }(300, hex""); } } @@ -175,18 +192,22 @@ contract PreBridgeETHTo is Bridge_Initializer { /// @dev Asserts the expected calls and events for bridging ETH to a different /// address depending on whether the bridge call is legacy or not. function _preBridgeETHTo(bool isLegacy) internal { - assertEq(address(op).balance, 0); - uint256 nonce = L1Messenger.messageNonce(); + assertEq(address(optimismPortal).balance, 0); + uint256 nonce = l1CrossDomainMessenger.messageNonce(); uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION - address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); + address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); if (isLegacy) { vm.expectCall( - address(L1Bridge), 600, abi.encodeWithSelector(L1Bridge.depositETHTo.selector, bob, 60000, hex"dead") + address(l1StandardBridge), + 600, + abi.encodeWithSelector(l1StandardBridge.depositETHTo.selector, bob, 60000, hex"dead") ); } else { vm.expectCall( - address(L1Bridge), 600, abi.encodeWithSelector(L1Bridge.bridgeETHTo.selector, bob, 60000, hex"dead") + address(l1StandardBridge), + 600, + abi.encodeWithSelector(l1StandardBridge.bridgeETHTo.selector, bob, 60000, hex"dead") ); } @@ -196,41 +217,52 @@ contract PreBridgeETHTo is Bridge_Initializer { // the L1 bridge should call // L1CrossDomainMessenger.sendMessage vm.expectCall( - address(L1Messenger), - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L2Bridge), message, 60000) + address(l1CrossDomainMessenger), + abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 60000) ); bytes memory innerMessage = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, nonce, address(L1Bridge), address(L2Bridge), 600, 60000, message + CrossDomainMessenger.relayMessage.selector, + nonce, + address(l1StandardBridge), + address(l2StandardBridge), + 600, + 60000, + message ); - uint64 baseGas = L1Messenger.baseGas(message, 60000); + uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 60000); vm.expectCall( - address(op), + address(optimismPortal), abi.encodeWithSelector( - OptimismPortal.depositTransaction.selector, address(L2Messenger), 600, baseGas, false, innerMessage + OptimismPortal.depositTransaction.selector, + address(l2CrossDomainMessenger), + 600, + baseGas, + false, + innerMessage ) ); bytes memory opaqueData = abi.encodePacked(uint256(600), uint256(600), baseGas, false, innerMessage); - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ETHDepositInitiated(alice, bob, 600, hex"dead"); - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ETHBridgeInitiated(alice, bob, 600, hex"dead"); // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call - vm.expectEmit(true, true, true, true, address(op)); - emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData); + vm.expectEmit(true, true, true, true, address(optimismPortal)); + emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData); // SentMessage event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L1Messenger)); - emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 60000); + vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger)); + emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 60000); // SentMessageExtension1 event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L1Messenger)); - emit SentMessageExtension1(address(L1Bridge), 600); + vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger)); + emit SentMessageExtension1(address(l1StandardBridge), 600); // deposit eth to bob vm.prank(alice, alice); @@ -245,8 +277,8 @@ contract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo { /// ETH ends up in the optimismPortal. function test_depositETHTo_succeeds() external { _preBridgeETHTo({ isLegacy: true }); - L1Bridge.depositETHTo{ value: 600 }(bob, 60000, hex"dead"); - assertEq(address(op).balance, 600); + l1StandardBridge.depositETHTo{ value: 600 }(bob, 60000, hex"dead"); + assertEq(address(optimismPortal).balance, 600); } } @@ -258,8 +290,8 @@ contract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo { /// ETH ends up in the optimismPortal. function test_bridgeETHTo_succeeds() external { _preBridgeETHTo({ isLegacy: false }); - L1Bridge.bridgeETHTo{ value: 600 }(bob, 60000, hex"dead"); - assertEq(address(op).balance, 600); + l1StandardBridge.bridgeETHTo{ value: 600 }(bob, 60000, hex"dead"); + assertEq(address(optimismPortal).balance, 600); } } @@ -280,18 +312,18 @@ contract L1StandardBridge_DepositERC20_Test is Bridge_Initializer { /// Calls depositTransaction on the OptimismPortal. /// Only EOA can call depositERC20. function test_depositERC20_succeeds() external { - uint256 nonce = L1Messenger.messageNonce(); + uint256 nonce = l1CrossDomainMessenger.messageNonce(); uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION - address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); + address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); // Deal Alice's ERC20 State deal(address(L1Token), alice, 100000, true); vm.prank(alice); - L1Token.approve(address(L1Bridge), type(uint256).max); + L1Token.approve(address(l1StandardBridge), type(uint256).max); - // The L1Bridge should transfer alice's tokens to itself + // The l1StandardBridge should transfer alice's tokens to itself vm.expectCall( - address(L1Token), abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 100) + address(L1Token), abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(l1StandardBridge), 100) ); bytes memory message = abi.encodeWithSelector( @@ -300,46 +332,57 @@ contract L1StandardBridge_DepositERC20_Test is Bridge_Initializer { // the L1 bridge should call L1CrossDomainMessenger.sendMessage vm.expectCall( - address(L1Messenger), - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L2Bridge), message, 10000) + address(l1CrossDomainMessenger), + abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 10000) ); bytes memory innerMessage = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, nonce, address(L1Bridge), address(L2Bridge), 0, 10000, message + CrossDomainMessenger.relayMessage.selector, + nonce, + address(l1StandardBridge), + address(l2StandardBridge), + 0, + 10000, + message ); - uint64 baseGas = L1Messenger.baseGas(message, 10000); + uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 10000); vm.expectCall( - address(op), + address(optimismPortal), abi.encodeWithSelector( - OptimismPortal.depositTransaction.selector, address(L2Messenger), 0, baseGas, false, innerMessage + OptimismPortal.depositTransaction.selector, + address(l2CrossDomainMessenger), + 0, + baseGas, + false, + innerMessage ) ); bytes memory opaqueData = abi.encodePacked(uint256(0), uint256(0), baseGas, false, innerMessage); // Should emit both the bedrock and legacy events - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex""); - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex""); // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call - vm.expectEmit(true, true, true, true, address(op)); - emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData); + vm.expectEmit(true, true, true, true, address(optimismPortal)); + emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData); // SentMessage event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L1Messenger)); - emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000); + vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger)); + emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 10000); // SentMessageExtension1 event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L1Messenger)); - emit SentMessageExtension1(address(L1Bridge), 0); + vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger)); + emit SentMessageExtension1(address(l1StandardBridge), 0); vm.prank(alice); - L1Bridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex""); - assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100); + l1StandardBridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex""); + assertEq(l1StandardBridge.deposits(address(L1Token), address(L2Token)), 100); } } @@ -352,7 +395,7 @@ contract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer { vm.expectRevert("StandardBridge: function can only be called from an EOA"); vm.prank(alice, alice); - L1Bridge.depositERC20(address(0), address(0), 100, 100, hex""); + l1StandardBridge.depositERC20(address(0), address(0), 100, 100, hex""); } } @@ -364,65 +407,77 @@ contract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer { /// Calls depositTransaction on the OptimismPortal. /// Contracts can call depositERC20. function test_depositERC20To_succeeds() external { - uint256 nonce = L1Messenger.messageNonce(); + uint256 nonce = l1CrossDomainMessenger.messageNonce(); uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION - address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); + address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); bytes memory message = abi.encodeWithSelector( StandardBridge.finalizeBridgeERC20.selector, address(L2Token), address(L1Token), alice, bob, 1000, hex"" ); bytes memory innerMessage = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, nonce, address(L1Bridge), address(L2Bridge), 0, 10000, message + CrossDomainMessenger.relayMessage.selector, + nonce, + address(l1StandardBridge), + address(l2StandardBridge), + 0, + 10000, + message ); - uint64 baseGas = L1Messenger.baseGas(message, 10000); + uint64 baseGas = l1CrossDomainMessenger.baseGas(message, 10000); bytes memory opaqueData = abi.encodePacked(uint256(0), uint256(0), baseGas, false, innerMessage); deal(address(L1Token), alice, 100000, true); vm.prank(alice); - L1Token.approve(address(L1Bridge), type(uint256).max); + L1Token.approve(address(l1StandardBridge), type(uint256).max); // Should emit both the bedrock and legacy events - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex""); - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex""); // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call - vm.expectEmit(true, true, true, true, address(op)); - emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData); + vm.expectEmit(true, true, true, true, address(optimismPortal)); + emit TransactionDeposited(l1MessengerAliased, address(l2CrossDomainMessenger), version, opaqueData); // SentMessage event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L1Messenger)); - emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000); + vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger)); + emit SentMessage(address(l2StandardBridge), address(l1StandardBridge), message, nonce, 10000); // SentMessageExtension1 event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L1Messenger)); - emit SentMessageExtension1(address(L1Bridge), 0); + vm.expectEmit(true, true, true, true, address(l1CrossDomainMessenger)); + emit SentMessageExtension1(address(l1StandardBridge), 0); // the L1 bridge should call L1CrossDomainMessenger.sendMessage vm.expectCall( - address(L1Messenger), - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L2Bridge), message, 10000) + address(l1CrossDomainMessenger), + abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 10000) ); // The L1 XDM should call OptimismPortal.depositTransaction vm.expectCall( - address(op), + address(optimismPortal), abi.encodeWithSelector( - OptimismPortal.depositTransaction.selector, address(L2Messenger), 0, baseGas, false, innerMessage + OptimismPortal.depositTransaction.selector, + address(l2CrossDomainMessenger), + 0, + baseGas, + false, + innerMessage ) ); vm.expectCall( - address(L1Token), abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 1000) + address(L1Token), + abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(l1StandardBridge), 1000) ); vm.prank(alice); - L1Bridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex""); + l1StandardBridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex""); - assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 1000); + assertEq(l1StandardBridge.deposits(address(L1Token), address(L2Token)), 1000); } } @@ -435,25 +490,25 @@ contract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer { function test_finalizeETHWithdrawal_succeeds() external { uint256 aliceBalance = alice.balance; - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ETHWithdrawalFinalized(alice, alice, 100, hex""); - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ETHBridgeFinalized(alice, alice, 100, hex""); vm.expectCall(alice, hex""); vm.mockCall( - address(L1Bridge.messenger()), + address(l1StandardBridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L1Bridge.OTHER_BRIDGE())) + abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); // ensure that the messenger has ETH to call with - vm.deal(address(L1Bridge.messenger()), 100); - vm.prank(address(L1Bridge.messenger())); - L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex""); + vm.deal(address(l1StandardBridge.messenger()), 100); + vm.prank(address(l1StandardBridge.messenger())); + l1StandardBridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex""); - assertEq(address(L1Bridge.messenger()).balance, 0); + assertEq(address(l1StandardBridge.messenger()).balance, 0); assertEq(aliceBalance + 100, alice.balance); } } @@ -468,32 +523,33 @@ contract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer { /// Emits ERC20WithdrawalFinalized event. /// Only callable by the L2 bridge. function test_finalizeERC20Withdrawal_succeeds() external { - deal(address(L1Token), address(L1Bridge), 100, true); + deal(address(L1Token), address(l1StandardBridge), 100, true); - uint256 slot = stdstore.target(address(L1Bridge)).sig("deposits(address,address)").with_key(address(L1Token)) - .with_key(address(L2Token)).find(); + uint256 slot = stdstore.target(address(l1StandardBridge)).sig("deposits(address,address)").with_key( + address(L1Token) + ).with_key(address(L2Token)).find(); // Give the L1 bridge some ERC20 tokens - vm.store(address(L1Bridge), bytes32(slot), bytes32(uint256(100))); - assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100); + vm.store(address(l1StandardBridge), bytes32(slot), bytes32(uint256(100))); + assertEq(l1StandardBridge.deposits(address(L1Token), address(L2Token)), 100); - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ERC20WithdrawalFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex""); - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ERC20BridgeFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex""); vm.expectCall(address(L1Token), abi.encodeWithSelector(ERC20.transfer.selector, alice, 100)); vm.mockCall( - address(L1Bridge.messenger()), + address(l1StandardBridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L1Bridge.OTHER_BRIDGE())) + abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); - vm.prank(address(L1Bridge.messenger())); - L1Bridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex""); + vm.prank(address(l1StandardBridge.messenger())); + l1StandardBridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex""); - assertEq(L1Token.balanceOf(address(L1Bridge)), 0); + assertEq(L1Token.balanceOf(address(l1StandardBridge)), 0); assertEq(L1Token.balanceOf(address(alice)), 100); } } @@ -502,87 +558,87 @@ contract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer /// @dev Tests that finalizing an ERC20 withdrawal reverts if the caller is not the L2 bridge. function test_finalizeERC20Withdrawal_notMessenger_reverts() external { vm.mockCall( - address(L1Bridge.messenger()), + address(l1StandardBridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L1Bridge.OTHER_BRIDGE())) + abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.prank(address(28)); vm.expectRevert("StandardBridge: function can only be called from the other bridge"); - L1Bridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex""); + l1StandardBridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex""); } /// @dev Tests that finalizing an ERC20 withdrawal reverts if the caller is not the L2 bridge. function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external { vm.mockCall( - address(L1Bridge.messenger()), + address(l1StandardBridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(address(0))) ); - vm.prank(address(L1Bridge.messenger())); + vm.prank(address(l1StandardBridge.messenger())); vm.expectRevert("StandardBridge: function can only be called from the other bridge"); - L1Bridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex""); + l1StandardBridge.finalizeERC20Withdrawal(address(L1Token), address(L2Token), alice, alice, 100, hex""); } } contract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer { /// @dev Tests that finalizing bridged ETH succeeds. function test_finalizeBridgeETH_succeeds() external { - address messenger = address(L1Bridge.messenger()); + address messenger = address(l1StandardBridge.messenger()); vm.mockCall( messenger, abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L1Bridge.OTHER_BRIDGE())) + abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.deal(messenger, 100); vm.prank(messenger); - vm.expectEmit(true, true, true, true, address(L1Bridge)); + vm.expectEmit(true, true, true, true, address(l1StandardBridge)); emit ETHBridgeFinalized(alice, alice, 100, hex""); - L1Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex""); + l1StandardBridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex""); } } contract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer { /// @dev Tests that finalizing bridged ETH reverts if the amount is incorrect. function test_finalizeBridgeETH_incorrectValue_reverts() external { - address messenger = address(L1Bridge.messenger()); + address messenger = address(l1StandardBridge.messenger()); vm.mockCall( messenger, abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L1Bridge.OTHER_BRIDGE())) + abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.deal(messenger, 100); vm.prank(messenger); vm.expectRevert("StandardBridge: amount sent does not match amount required"); - L1Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex""); + l1StandardBridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex""); } /// @dev Tests that finalizing bridged ETH reverts if the destination is the L1 bridge. function test_finalizeBridgeETH_sendToSelf_reverts() external { - address messenger = address(L1Bridge.messenger()); + address messenger = address(l1StandardBridge.messenger()); vm.mockCall( messenger, abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L1Bridge.OTHER_BRIDGE())) + abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.deal(messenger, 100); vm.prank(messenger); vm.expectRevert("StandardBridge: cannot send to self"); - L1Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L1Bridge), 100, hex""); + l1StandardBridge.finalizeBridgeETH{ value: 100 }(alice, address(l1StandardBridge), 100, hex""); } /// @dev Tests that finalizing bridged ETH reverts if the destination is the messenger. function test_finalizeBridgeETH_sendToMessenger_reverts() external { - address messenger = address(L1Bridge.messenger()); + address messenger = address(l1StandardBridge.messenger()); vm.mockCall( messenger, abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L1Bridge.OTHER_BRIDGE())) + abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.deal(messenger, 100); vm.prank(messenger); vm.expectRevert("StandardBridge: cannot send to messenger"); - L1Bridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex""); + l1StandardBridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex""); } } diff --git a/packages/contracts-bedrock/test/L2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L2CrossDomainMessenger.t.sol index ead28756af6d..cbd13e5bfb41 100644 --- a/packages/contracts-bedrock/test/L2CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L2CrossDomainMessenger.t.sol @@ -2,7 +2,8 @@ pragma solidity 0.8.15; // Testing utilities -import { Messenger_Initializer, Reverter, ConfigurableCaller } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; +import { Reverter, ConfigurableCaller } from "test/mocks/Callers.sol"; // Libraries import { Hashing } from "src/libraries/Hashing.sol"; @@ -12,31 +13,27 @@ import { Types } from "src/libraries/Types.sol"; // Target contract dependencies import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; -import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; -// Target contract -import { L2CrossDomainMessenger } from "src/L2/L2CrossDomainMessenger.sol"; - -contract L2CrossDomainMessenger_Test is Messenger_Initializer { +contract L2CrossDomainMessenger_Test is Bridge_Initializer { /// @dev Receiver address for testing address recipient = address(0xabbaacdc); /// @dev Tests that `messageNonce` can be decoded correctly. function test_messageVersion_succeeds() external { - (, uint16 version) = Encoding.decodeVersionedNonce(L2Messenger.messageNonce()); - assertEq(version, L2Messenger.MESSAGE_VERSION()); + (, uint16 version) = Encoding.decodeVersionedNonce(l2CrossDomainMessenger.messageNonce()); + assertEq(version, l2CrossDomainMessenger.MESSAGE_VERSION()); } /// @dev Tests that `sendMessage` executes successfully. function test_sendMessage_succeeds() external { bytes memory xDomainCallData = - Encoding.encodeCrossDomainMessage(L2Messenger.messageNonce(), alice, recipient, 0, 100, hex"ff"); + Encoding.encodeCrossDomainMessage(l2CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff"); vm.expectCall( - address(messagePasser), + address(l2ToL1MessagePasser), abi.encodeWithSelector( L2ToL1MessagePasser.initiateWithdrawal.selector, - address(L1Messenger), - L2Messenger.baseGas(hex"ff", 100), + address(l1CrossDomainMessenger), + l2CrossDomainMessenger.baseGas(hex"ff", 100), xDomainCallData ) ); @@ -44,56 +41,56 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { // MessagePassed event vm.expectEmit(true, true, true, true); emit MessagePassed( - messagePasser.messageNonce(), - address(L2Messenger), - address(L1Messenger), + l2ToL1MessagePasser.messageNonce(), + address(l2CrossDomainMessenger), + address(l1CrossDomainMessenger), 0, - L2Messenger.baseGas(hex"ff", 100), + l2CrossDomainMessenger.baseGas(hex"ff", 100), xDomainCallData, Hashing.hashWithdrawal( Types.WithdrawalTransaction({ - nonce: messagePasser.messageNonce(), - sender: address(L2Messenger), - target: address(L1Messenger), + nonce: l2ToL1MessagePasser.messageNonce(), + sender: address(l2CrossDomainMessenger), + target: address(l1CrossDomainMessenger), value: 0, - gasLimit: L2Messenger.baseGas(hex"ff", 100), + gasLimit: l2CrossDomainMessenger.baseGas(hex"ff", 100), data: xDomainCallData }) ) ); vm.prank(alice); - L2Messenger.sendMessage(recipient, hex"ff", uint32(100)); + l2CrossDomainMessenger.sendMessage(recipient, hex"ff", uint32(100)); } /// @dev Tests that `sendMessage` can be called twice and that /// the nonce increments correctly. function test_sendMessage_twice_succeeds() external { - uint256 nonce = L2Messenger.messageNonce(); - L2Messenger.sendMessage(recipient, hex"aa", uint32(500_000)); - L2Messenger.sendMessage(recipient, hex"aa", uint32(500_000)); + uint256 nonce = l2CrossDomainMessenger.messageNonce(); + l2CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000)); + l2CrossDomainMessenger.sendMessage(recipient, hex"aa", uint32(500_000)); // the nonce increments for each message sent - assertEq(nonce + 2, L2Messenger.messageNonce()); + assertEq(nonce + 2, l2CrossDomainMessenger.messageNonce()); } /// @dev Tests that `sendMessage` reverts if the recipient is the zero address. function test_xDomainSender_senderNotSet_reverts() external { vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); - L2Messenger.xDomainMessageSender(); + l2CrossDomainMessenger.xDomainMessageSender(); } /// @dev Tests that `sendMessage` reverts if the message version is not supported. function test_relayMessage_v2_reverts() external { address target = address(0xabcd); - address sender = address(L1Messenger); - address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); + address sender = address(l1CrossDomainMessenger); + address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); // Expect a revert. vm.expectRevert("CrossDomainMessenger: only version 0 or 1 messages are supported at this time"); // Try to relay a v2 message. vm.prank(caller); - L2Messenger.relayMessage( + l2CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce(0, 2), // nonce sender, target, @@ -106,8 +103,8 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { /// @dev Tests that `relayMessage` executes successfully. function test_relayMessage_succeeds() external { address target = address(0xabcd); - address sender = address(L1Messenger); - address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); + address sender = address(l1CrossDomainMessenger); + address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); vm.expectCall(target, hex"1111"); @@ -120,7 +117,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { emit RelayedMessage(hash); - L2Messenger.relayMessage( + l2CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce(0, 1), // nonce sender, target, @@ -130,36 +127,36 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ); // the message hash is in the successfulMessages mapping - assert(L2Messenger.successfulMessages(hash)); + assert(l2CrossDomainMessenger.successfulMessages(hash)); // it is not in the received messages mapping - assertEq(L2Messenger.failedMessages(hash), false); + assertEq(l2CrossDomainMessenger.failedMessages(hash), false); } /// @dev Tests that `relayMessage` reverts if attempting to relay /// a message sent to an L1 system contract. function test_relayMessage_toSystemContract_reverts() external { - address target = address(messagePasser); - address sender = address(L1Messenger); - address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); + address target = address(l2ToL1MessagePasser); + address sender = address(l1CrossDomainMessenger); + address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); bytes memory message = hex"1111"; vm.prank(caller); vm.expectRevert("CrossDomainMessenger: message cannot be replayed"); - L1Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message); + l1CrossDomainMessenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message); } /// @dev Tests that `relayMessage` correctly resets the `xDomainMessageSender` /// to the original value after a message is relayed. function test_xDomainMessageSender_reset_succeeds() external { vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); - L2Messenger.xDomainMessageSender(); + l2CrossDomainMessenger.xDomainMessageSender(); - address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); + address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); vm.prank(caller); - L2Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), address(0), address(0), 0, 0, hex""); + l2CrossDomainMessenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), address(0), address(0), 0, 0, hex""); vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); - L2Messenger.xDomainMessageSender(); + l2CrossDomainMessenger.xDomainMessageSender(); } /// @dev Tests that `relayMessage` is able to send a successful call @@ -167,8 +164,8 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { /// gets stuck, but the second message succeeds. function test_relayMessage_retry_succeeds() external { address target = address(0xabcd); - address sender = address(L1Messenger); - address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); + address sender = address(l1CrossDomainMessenger); + address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); uint256 value = 100; bytes32 hash = @@ -177,7 +174,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { vm.etch(target, address(new Reverter()).code); vm.deal(address(caller), value); vm.prank(caller); - L2Messenger.relayMessage{ value: value }( + l2CrossDomainMessenger.relayMessage{ value: value }( Encoding.encodeVersionedNonce(0, 1), // nonce sender, target, @@ -186,10 +183,10 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { hex"1111" ); - assertEq(address(L2Messenger).balance, value); + assertEq(address(l2CrossDomainMessenger).balance, value); assertEq(address(target).balance, 0); - assertEq(L2Messenger.successfulMessages(hash), false); - assertEq(L2Messenger.failedMessages(hash), true); + assertEq(l2CrossDomainMessenger.successfulMessages(hash), false); + assertEq(l2CrossDomainMessenger.failedMessages(hash), true); vm.expectEmit(true, true, true, true); @@ -197,7 +194,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { vm.etch(target, address(0).code); vm.prank(address(sender)); - L2Messenger.relayMessage( + l2CrossDomainMessenger.relayMessage( Encoding.encodeVersionedNonce(0, 1), // nonce sender, target, @@ -206,9 +203,9 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { hex"1111" ); - assertEq(address(L2Messenger).balance, 0); + assertEq(address(l2CrossDomainMessenger).balance, 0); assertEq(address(target).balance, value); - assertEq(L2Messenger.successfulMessages(hash), true); - assertEq(L2Messenger.failedMessages(hash), true); + assertEq(l2CrossDomainMessenger.successfulMessages(hash), true); + assertEq(l2CrossDomainMessenger.failedMessages(hash), true); } } diff --git a/packages/contracts-bedrock/test/L2ERC721Bridge.t.sol b/packages/contracts-bedrock/test/L2ERC721Bridge.t.sol index 03567f3beae1..555724a7630f 100644 --- a/packages/contracts-bedrock/test/L2ERC721Bridge.t.sol +++ b/packages/contracts-bedrock/test/L2ERC721Bridge.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; // Testing utilities -import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; // Target contract dependencies import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; @@ -33,7 +33,7 @@ contract TestMintableERC721 is OptimismMintableERC721 { } } -contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { +contract L2ERC721Bridge_Test is Bridge_Initializer { TestMintableERC721 internal localToken; TestERC721 internal remoteToken; uint256 internal constant tokenId = 1; @@ -61,22 +61,22 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { super.setUp(); remoteToken = new TestERC721(); - localToken = new TestMintableERC721(address(L2NFTBridge), address(remoteToken)); + localToken = new TestMintableERC721(address(l2ERC721Bridge), address(remoteToken)); // Mint alice a token. localToken.mint(alice, tokenId); // Approve the bridge to transfer the token. vm.prank(alice); - localToken.approve(address(L2NFTBridge), tokenId); + localToken.approve(address(l2ERC721Bridge), tokenId); } /// @dev Tests that the constructor sets the correct variables. function test_constructor_succeeds() public { - assertEq(address(L2NFTBridge.MESSENGER()), address(L2Messenger)); - assertEq(address(L2NFTBridge.OTHER_BRIDGE()), address(L1NFTBridge)); - assertEq(address(L2NFTBridge.messenger()), address(L2Messenger)); - assertEq(address(L2NFTBridge.otherBridge()), address(L1NFTBridge)); + assertEq(address(l2ERC721Bridge.MESSENGER()), address(l2CrossDomainMessenger)); + assertEq(address(l2ERC721Bridge.OTHER_BRIDGE()), address(l1ERC721Bridge)); + assertEq(address(l2ERC721Bridge.messenger()), address(l2CrossDomainMessenger)); + assertEq(address(l2ERC721Bridge.otherBridge()), address(l1ERC721Bridge)); } /// @dev Tests that `bridgeERC721` correctly bridges a token and @@ -84,11 +84,11 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { function test_bridgeERC721_succeeds() public { // Expect a call to the messenger. vm.expectCall( - address(L2Messenger), + address(l2CrossDomainMessenger), abi.encodeCall( - L2Messenger.sendMessage, + l2CrossDomainMessenger.sendMessage, ( - address(L1NFTBridge), + address(l1ERC721Bridge), abi.encodeCall( L2ERC721Bridge.finalizeBridgeERC721, (address(remoteToken), address(localToken), alice, alice, tokenId, hex"5678") @@ -104,7 +104,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); - L2NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); + l2ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); // Token is burned. vm.expectRevert("ERC721: invalid token ID"); @@ -117,7 +117,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { vm.etch(alice, hex"01"); vm.prank(alice); vm.expectRevert("ERC721Bridge: account is not externally owned"); - L2NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); + l2ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); // Token is not locked in the bridge. assertEq(localToken.ownerOf(tokenId), alice); @@ -128,7 +128,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); vm.expectRevert(); - L2NFTBridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678"); + l2ERC721Bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678"); // Token is not locked in the bridge. assertEq(localToken.ownerOf(tokenId), alice); @@ -139,7 +139,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); vm.expectRevert("L2ERC721Bridge: remote token cannot be address(0)"); - L2NFTBridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678"); + l2ERC721Bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex"5678"); // Token is not locked in the bridge. assertEq(localToken.ownerOf(tokenId), alice); @@ -150,7 +150,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(bob); vm.expectRevert("L2ERC721Bridge: Withdrawal is not being initiated by NFT owner"); - L2NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); + l2ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); // Token is not locked in the bridge. assertEq(localToken.ownerOf(tokenId), alice); @@ -161,11 +161,11 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { function test_bridgeERC721To_succeeds() external { // Expect a call to the messenger. vm.expectCall( - address(L2Messenger), + address(l2CrossDomainMessenger), abi.encodeCall( - L2Messenger.sendMessage, + l2CrossDomainMessenger.sendMessage, ( - address(L1NFTBridge), + address(l1ERC721Bridge), abi.encodeCall( L1ERC721Bridge.finalizeBridgeERC721, (address(remoteToken), address(localToken), alice, bob, tokenId, hex"5678") @@ -181,7 +181,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); - L2NFTBridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678"); + l2ERC721Bridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678"); // Token is burned. vm.expectRevert("ERC721: invalid token ID"); @@ -193,7 +193,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); vm.expectRevert(); - L2NFTBridge.bridgeERC721To(address(0), address(L1NFTBridge), bob, tokenId, 1234, hex"5678"); + l2ERC721Bridge.bridgeERC721To(address(0), address(l1ERC721Bridge), bob, tokenId, 1234, hex"5678"); // Token is not locked in the bridge. assertEq(localToken.ownerOf(tokenId), alice); @@ -204,7 +204,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(alice); vm.expectRevert("L2ERC721Bridge: remote token cannot be address(0)"); - L2NFTBridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678"); + l2ERC721Bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex"5678"); // Token is not locked in the bridge. assertEq(localToken.ownerOf(tokenId), alice); @@ -215,7 +215,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the token. vm.prank(bob); vm.expectRevert("L2ERC721Bridge: Withdrawal is not being initiated by NFT owner"); - L2NFTBridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678"); + l2ERC721Bridge.bridgeERC721To(address(localToken), address(remoteToken), bob, tokenId, 1234, hex"5678"); // Token is not locked in the bridge. assertEq(localToken.ownerOf(tokenId), alice); @@ -225,7 +225,7 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { function test_finalizeBridgeERC721_succeeds() external { // Bridge the token. vm.prank(alice); - L2NFTBridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); + l2ERC721Bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex"5678"); // Expect an event to be emitted. vm.expectEmit(true, true, true, true); @@ -233,12 +233,12 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { // Finalize a withdrawal. vm.mockCall( - address(L2Messenger), - abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector), - abi.encode(L1NFTBridge) + address(l2CrossDomainMessenger), + abi.encodeWithSelector(l2CrossDomainMessenger.xDomainMessageSender.selector), + abi.encode(l1ERC721Bridge) ); - vm.prank(address(L2Messenger)); - L2NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); + vm.prank(address(l2CrossDomainMessenger)); + l2ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); // Token is not locked in the bridge. assertEq(localToken.ownerOf(tokenId), alice); @@ -252,18 +252,18 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { // Bridge the non-compliant token. vm.prank(alice); - L2NFTBridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex"5678"); + l2ERC721Bridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex"5678"); // Attempt to finalize the withdrawal. Should revert because the token does not claim // to be compliant with the `IOptimismMintableERC721` interface. vm.mockCall( - address(L2Messenger), - abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector), - abi.encode(L1NFTBridge) + address(l2CrossDomainMessenger), + abi.encodeWithSelector(l2CrossDomainMessenger.xDomainMessageSender.selector), + abi.encode(l1ERC721Bridge) ); - vm.prank(address(L2Messenger)); + vm.prank(address(l2CrossDomainMessenger)); vm.expectRevert("L2ERC721Bridge: local token interface is not compliant"); - L2NFTBridge.finalizeBridgeERC721( + l2ERC721Bridge.finalizeBridgeERC721( address(address(nonCompliantToken)), address(address(0x01)), alice, alice, tokenId, hex"5678" ); } @@ -273,18 +273,20 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { // Finalize a withdrawal. vm.prank(alice); vm.expectRevert("ERC721Bridge: function can only be called from the other bridge"); - L2NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); + l2ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); } /// @dev Tests that `finalizeBridgeERC721` reverts when not called by the remote bridge. function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external { // Finalize a withdrawal. vm.mockCall( - address(L2Messenger), abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector), abi.encode(alice) + address(l2CrossDomainMessenger), + abi.encodeWithSelector(l2CrossDomainMessenger.xDomainMessageSender.selector), + abi.encode(alice) ); - vm.prank(address(L2Messenger)); + vm.prank(address(l2CrossDomainMessenger)); vm.expectRevert("ERC721Bridge: function can only be called from the other bridge"); - L2NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); + l2ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); } /// @dev Tests that `finalizeBridgeERC721` reverts when the local token is the @@ -292,26 +294,28 @@ contract L2ERC721Bridge_Test is ERC721Bridge_Initializer { function test_finalizeBridgeERC721_selfToken_reverts() external { // Finalize a withdrawal. vm.mockCall( - address(L2Messenger), - abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector), - abi.encode(address(L1NFTBridge)) + address(l2CrossDomainMessenger), + abi.encodeWithSelector(l2CrossDomainMessenger.xDomainMessageSender.selector), + abi.encode(address(l1ERC721Bridge)) ); - vm.prank(address(L2Messenger)); + vm.prank(address(l2CrossDomainMessenger)); vm.expectRevert("L2ERC721Bridge: local token cannot be self"); - L2NFTBridge.finalizeBridgeERC721(address(L2NFTBridge), address(remoteToken), alice, alice, tokenId, hex"5678"); + l2ERC721Bridge.finalizeBridgeERC721( + address(l2ERC721Bridge), address(remoteToken), alice, alice, tokenId, hex"5678" + ); } /// @dev Tests that `finalizeBridgeERC721` reverts when already finalized. function test_finalizeBridgeERC721_alreadyExists_reverts() external { // Finalize a withdrawal. vm.mockCall( - address(L2Messenger), - abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector), - abi.encode(address(L1NFTBridge)) + address(l2CrossDomainMessenger), + abi.encodeWithSelector(l2CrossDomainMessenger.xDomainMessageSender.selector), + abi.encode(address(l1ERC721Bridge)) ); - vm.prank(address(L2Messenger)); + vm.prank(address(l2CrossDomainMessenger)); vm.expectRevert("ERC721: token already minted"); - L2NFTBridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); + l2ERC721Bridge.finalizeBridgeERC721(address(localToken), address(remoteToken), alice, alice, tokenId, hex"5678"); } } diff --git a/packages/contracts-bedrock/test/L2OutputOracle.t.sol b/packages/contracts-bedrock/test/L2OutputOracle.t.sol index 52b87b450aa8..ad523d5bbd3f 100644 --- a/packages/contracts-bedrock/test/L2OutputOracle.t.sol +++ b/packages/contracts-bedrock/test/L2OutputOracle.t.sol @@ -3,7 +3,9 @@ pragma solidity 0.8.15; // Testing utilities import { stdError } from "forge-std/Test.sol"; -import { L2OutputOracle_Initializer, NextImpl, EIP1967Helper } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; +import { NextImpl } from "test/mocks/NextImpl.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Libraries import { Types } from "src/libraries/Types.sol"; @@ -15,26 +17,35 @@ import { Proxy } from "src/universal/Proxy.sol"; // Target contract import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; -contract L2OutputOracle_constructor_Test is L2OutputOracle_Initializer { +contract L2OutputOracle_constructor_Test is CommonTest { /// @dev Tests that constructor sets the initial values correctly. function test_constructor_succeeds() external { - assertEq(oracle.PROPOSER(), proposer); - assertEq(oracle.proposer(), proposer); - assertEq(oracle.CHALLENGER(), owner); - assertEq(oracle.challenger(), owner); - assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval); - assertEq(oracle.submissionInterval(), submissionInterval); - assertEq(oracle.latestBlockNumber(), startingBlockNumber); - assertEq(oracle.startingBlockNumber(), startingBlockNumber); - assertEq(oracle.startingTimestamp(), startingTimestamp); - assertEq(oracle.L2_BLOCK_TIME(), l2BlockTime); - assertEq(oracle.l2BlockTime(), l2BlockTime); - assertEq(oracle.finalizationPeriodSeconds(), finalizationPeriodSeconds); - assertEq(oracle.FINALIZATION_PERIOD_SECONDS(), finalizationPeriodSeconds); + address proposer = cfg.l2OutputOracleProposer(); + address challenger = cfg.l2OutputOracleChallenger(); + uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval(); + uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber(); + uint256 startingTimestamp = cfg.l2OutputOracleStartingTimestamp(); + uint256 l2BlockTime = cfg.l2BlockTime(); + uint256 finalizationPeriodSeconds = cfg.finalizationPeriodSeconds(); + + assertEq(l2OutputOracle.PROPOSER(), proposer); + assertEq(l2OutputOracle.proposer(), proposer); + assertEq(l2OutputOracle.CHALLENGER(), challenger); + assertEq(l2OutputOracle.challenger(), challenger); + assertEq(l2OutputOracle.SUBMISSION_INTERVAL(), submissionInterval); + assertEq(l2OutputOracle.submissionInterval(), submissionInterval); + assertEq(l2OutputOracle.latestBlockNumber(), startingBlockNumber); + assertEq(l2OutputOracle.startingBlockNumber(), startingBlockNumber); + assertEq(l2OutputOracle.startingTimestamp(), startingTimestamp); + assertEq(l2OutputOracle.L2_BLOCK_TIME(), l2BlockTime); + assertEq(l2OutputOracle.l2BlockTime(), l2BlockTime); + assertEq(l2OutputOracle.finalizationPeriodSeconds(), finalizationPeriodSeconds); + assertEq(l2OutputOracle.FINALIZATION_PERIOD_SECONDS(), finalizationPeriodSeconds); } /// @dev Tests that the constructor reverts if the l2BlockTime is invalid. function test_constructor_l2BlockTimeZero_reverts() external { + uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval(); vm.expectRevert("L2OutputOracle: L2 block time must be greater than 0"); new L2OutputOracle({ _submissionInterval: submissionInterval, @@ -45,6 +56,7 @@ contract L2OutputOracle_constructor_Test is L2OutputOracle_Initializer { /// @dev Tests that the constructor reverts if the submissionInterval is zero. function test_constructor_submissionInterval_reverts() external { + uint256 l2BlockTime = cfg.l2BlockTime(); vm.expectRevert("L2OutputOracle: submission interval must be greater than 0"); new L2OutputOracle({ _submissionInterval: 0, @@ -57,9 +69,9 @@ contract L2OutputOracle_constructor_Test is L2OutputOracle_Initializer { function test_initialize_badTimestamp_reverts() external { // Reset the initialized field in the 0th storage slot // so that initialize can be called again. - vm.store(address(oracle), bytes32(uint256(0)), bytes32(uint256(0))); + vm.store(address(l2OutputOracle), bytes32(uint256(0)), bytes32(uint256(0))); vm.expectRevert("L2OutputOracle: starting L2 timestamp must be less than current time"); - oracle.initialize({ + l2OutputOracle.initialize({ _startingBlockNumber: 0, _startingTimestamp: block.timestamp + 1, _proposer: address(0), @@ -68,48 +80,48 @@ contract L2OutputOracle_constructor_Test is L2OutputOracle_Initializer { } } -contract L2OutputOracle_getter_Test is L2OutputOracle_Initializer { +contract L2OutputOracle_getter_Test is CommonTest { bytes32 proposedOutput1 = keccak256(abi.encode(1)); /// @dev Tests that `latestBlockNumber` returns the correct value. function test_latestBlockNumber_succeeds() external { - uint256 proposedNumber = oracle.nextBlockNumber(); + uint256 proposedNumber = l2OutputOracle.nextBlockNumber(); // Roll to after the block number we'll propose warpToProposeTime(proposedNumber); - vm.prank(proposer); - oracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0); - assertEq(oracle.latestBlockNumber(), proposedNumber); + vm.prank(cfg.l2OutputOracleProposer()); + l2OutputOracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0); + assertEq(l2OutputOracle.latestBlockNumber(), proposedNumber); } /// @dev Tests that `getL2Output` returns the correct value. function test_getL2Output_succeeds() external { - uint256 nextBlockNumber = oracle.nextBlockNumber(); - uint256 nextOutputIndex = oracle.nextOutputIndex(); + uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber(); + uint256 nextOutputIndex = l2OutputOracle.nextOutputIndex(); warpToProposeTime(nextBlockNumber); - vm.prank(proposer); - oracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0); + vm.prank(cfg.l2OutputOracleProposer()); + l2OutputOracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0); - Types.OutputProposal memory proposal = oracle.getL2Output(nextOutputIndex); + Types.OutputProposal memory proposal = l2OutputOracle.getL2Output(nextOutputIndex); assertEq(proposal.outputRoot, proposedOutput1); assertEq(proposal.timestamp, block.timestamp); // The block number is larger than the latest proposed output: vm.expectRevert(stdError.indexOOBError); - oracle.getL2Output(nextOutputIndex + 1); + l2OutputOracle.getL2Output(nextOutputIndex + 1); } /// @dev Tests that `getL2OutputIndexAfter` returns the correct value /// when the input is the exact block number of the proposal. function test_getL2OutputIndexAfter_sameBlock_succeeds() external { bytes32 output1 = keccak256(abi.encode(1)); - uint256 nextBlockNumber1 = oracle.nextBlockNumber(); + uint256 nextBlockNumber1 = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber1); - vm.prank(proposer); - oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0); + vm.prank(cfg.l2OutputOracleProposer()); + l2OutputOracle.proposeL2Output(output1, nextBlockNumber1, 0, 0); // Querying with exact same block as proposed returns the proposal. - uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1); + uint256 index1 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber1); assertEq(index1, 0); } @@ -117,88 +129,94 @@ contract L2OutputOracle_getter_Test is L2OutputOracle_Initializer { /// when the input is the previous block number of the proposal. function test_getL2OutputIndexAfter_previousBlock_succeeds() external { bytes32 output1 = keccak256(abi.encode(1)); - uint256 nextBlockNumber1 = oracle.nextBlockNumber(); + uint256 nextBlockNumber1 = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber1); - vm.prank(proposer); - oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0); + vm.prank(cfg.l2OutputOracleProposer()); + l2OutputOracle.proposeL2Output(output1, nextBlockNumber1, 0, 0); // Querying with previous block returns the proposal too. - uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 - 1); + uint256 index1 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber1 - 1); assertEq(index1, 0); } /// @dev Tests that `getL2OutputIndexAfter` returns the correct value. function test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() external { bytes32 output1 = keccak256(abi.encode(1)); - uint256 nextBlockNumber1 = oracle.nextBlockNumber(); + uint256 nextBlockNumber1 = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber1); - vm.prank(proposer); - oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0); + vm.prank(cfg.l2OutputOracleProposer()); + l2OutputOracle.proposeL2Output(output1, nextBlockNumber1, 0, 0); bytes32 output2 = keccak256(abi.encode(2)); - uint256 nextBlockNumber2 = oracle.nextBlockNumber(); + uint256 nextBlockNumber2 = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber2); - vm.prank(proposer); - oracle.proposeL2Output(output2, nextBlockNumber2, 0, 0); + vm.prank(cfg.l2OutputOracleProposer()); + l2OutputOracle.proposeL2Output(output2, nextBlockNumber2, 0, 0); bytes32 output3 = keccak256(abi.encode(3)); - uint256 nextBlockNumber3 = oracle.nextBlockNumber(); + uint256 nextBlockNumber3 = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber3); - vm.prank(proposer); - oracle.proposeL2Output(output3, nextBlockNumber3, 0, 0); + vm.prank(cfg.l2OutputOracleProposer()); + l2OutputOracle.proposeL2Output(output3, nextBlockNumber3, 0, 0); bytes32 output4 = keccak256(abi.encode(4)); - uint256 nextBlockNumber4 = oracle.nextBlockNumber(); + uint256 nextBlockNumber4 = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber4); - vm.prank(proposer); - oracle.proposeL2Output(output4, nextBlockNumber4, 0, 0); + vm.prank(cfg.l2OutputOracleProposer()); + l2OutputOracle.proposeL2Output(output4, nextBlockNumber4, 0, 0); // Querying with a block number between the first and second proposal - uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 + 1); + uint256 index1 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber1 + 1); assertEq(index1, 1); // Querying with a block number between the second and third proposal - uint256 index2 = oracle.getL2OutputIndexAfter(nextBlockNumber2 + 1); + uint256 index2 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber2 + 1); assertEq(index2, 2); // Querying with a block number between the third and fourth proposal - uint256 index3 = oracle.getL2OutputIndexAfter(nextBlockNumber3 + 1); + uint256 index3 = l2OutputOracle.getL2OutputIndexAfter(nextBlockNumber3 + 1); assertEq(index3, 3); } /// @dev Tests that `getL2OutputIndexAfter` reverts when no output exists. function test_getL2OutputIndexAfter_noOutputsExis_reverts() external { vm.expectRevert("L2OutputOracle: cannot get output as no outputs have been proposed yet"); - oracle.getL2OutputIndexAfter(0); + l2OutputOracle.getL2OutputIndexAfter(0); } /// @dev Tests that `nextBlockNumber` returns the correct value. function test_nextBlockNumber_succeeds() external { assertEq( - oracle.nextBlockNumber(), + l2OutputOracle.nextBlockNumber(), // The return value should match this arithmetic - oracle.latestBlockNumber() + oracle.SUBMISSION_INTERVAL() + l2OutputOracle.latestBlockNumber() + l2OutputOracle.SUBMISSION_INTERVAL() ); } /// @dev Tests that `computeL2Timestamp` returns the correct value. function test_computeL2Timestamp_succeeds() external { + uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber(); + uint256 startingTimestamp = cfg.l2OutputOracleStartingTimestamp(); + uint256 l2BlockTime = cfg.l2BlockTime(); + // reverts if timestamp is too low vm.expectRevert(stdError.arithmeticError); - oracle.computeL2Timestamp(startingBlockNumber - 1); + l2OutputOracle.computeL2Timestamp(startingBlockNumber - 1); // check timestamp for the very first block - assertEq(oracle.computeL2Timestamp(startingBlockNumber), startingTimestamp); + assertEq(l2OutputOracle.computeL2Timestamp(startingBlockNumber), startingTimestamp); // check timestamp for the first block after the starting block - assertEq(oracle.computeL2Timestamp(startingBlockNumber + 1), startingTimestamp + l2BlockTime); + assertEq(l2OutputOracle.computeL2Timestamp(startingBlockNumber + 1), startingTimestamp + l2BlockTime); // check timestamp for some other block number - assertEq(oracle.computeL2Timestamp(startingBlockNumber + 96024), startingTimestamp + l2BlockTime * 96024); + assertEq( + l2OutputOracle.computeL2Timestamp(startingBlockNumber + 96024), startingTimestamp + l2BlockTime * 96024 + ); } } -contract L2OutputOracle_proposeL2Output_Test is L2OutputOracle_Initializer { +contract L2OutputOracle_proposeL2Output_Test is CommonTest { /// @dev Test that `proposeL2Output` succeeds for a valid input /// and when a block hash and number are not specified. function test_proposeL2Output_proposeAnotherOutput_succeeds() public { @@ -212,62 +230,62 @@ contract L2OutputOracle_proposeL2Output_Test is L2OutputOracle_Initializer { uint256 prevL1BlockNumber = block.number - 1; bytes32 prevL1BlockHash = blockhash(prevL1BlockNumber); - uint256 nextBlockNumber = oracle.nextBlockNumber(); + uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber); - vm.prank(proposer); - oracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber); + vm.prank(cfg.l2OutputOracleProposer()); + l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber); } /// @dev Tests that `proposeL2Output` reverts when called by a party /// that is not the proposer. function test_proposeL2Output_notProposer_reverts() external { - uint256 nextBlockNumber = oracle.nextBlockNumber(); + uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber); vm.prank(address(128)); vm.expectRevert("L2OutputOracle: only the proposer address can propose new outputs"); - oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0); + l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0); } /// @dev Tests that `proposeL2Output` reverts when given a zero blockhash. function test_proposeL2Output_emptyOutput_reverts() external { bytes32 outputToPropose = bytes32(0); - uint256 nextBlockNumber = oracle.nextBlockNumber(); + uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber); - vm.prank(proposer); + vm.prank(cfg.l2OutputOracleProposer()); vm.expectRevert("L2OutputOracle: L2 output proposal cannot be the zero hash"); - oracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0); + l2OutputOracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0); } /// @dev Tests that `proposeL2Output` reverts when given a block number /// that does not match the next expected block number. function test_proposeL2Output_unexpectedBlockNumber_reverts() external { - uint256 nextBlockNumber = oracle.nextBlockNumber(); + uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber); - vm.prank(proposer); + vm.prank(cfg.l2OutputOracleProposer()); vm.expectRevert("L2OutputOracle: block number must be equal to next expected block number"); - oracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0); + l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0); } /// @dev Tests that `proposeL2Output` reverts when given a block number /// that has a timestamp in the future. function test_proposeL2Output_futureTimetamp_reverts() external { - uint256 nextBlockNumber = oracle.nextBlockNumber(); - uint256 nextTimestamp = oracle.computeL2Timestamp(nextBlockNumber); + uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber(); + uint256 nextTimestamp = l2OutputOracle.computeL2Timestamp(nextBlockNumber); vm.warp(nextTimestamp); - vm.prank(proposer); + vm.prank(cfg.l2OutputOracleProposer()); vm.expectRevert("L2OutputOracle: cannot propose L2 output in the future"); - oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0); + l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0); } /// @dev Tests that `proposeL2Output` reverts when given a block number /// whose hash does not match the given block hash. function test_proposeL2Output_wrongFork_reverts() external { - uint256 nextBlockNumber = oracle.nextBlockNumber(); + uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber); - vm.prank(proposer); + vm.prank(cfg.l2OutputOracleProposer()); vm.expectRevert("L2OutputOracle: block hash does not match the hash at the expected height"); - oracle.proposeL2Output(nonZeroHash, nextBlockNumber, bytes32(uint256(0x01)), block.number - 1); + l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, bytes32(uint256(0x01)), block.number); } /// @dev Tests that `proposeL2Output` reverts when given a block number @@ -280,38 +298,39 @@ contract L2OutputOracle_proposeL2Output_Test is L2OutputOracle_Initializer { uint256 l1BlockNumber = block.number - 1; bytes32 l1BlockHash = blockhash(l1BlockNumber); - uint256 nextBlockNumber = oracle.nextBlockNumber(); + uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber(); warpToProposeTime(nextBlockNumber); - vm.prank(proposer); + vm.prank(cfg.l2OutputOracleProposer()); // This will fail when foundry no longer returns zerod block hashes vm.expectRevert("L2OutputOracle: block hash does not match the hash at the expected height"); - oracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1); + l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1); } } -contract L2OutputOracle_deleteOutputs_Test is L2OutputOracle_Initializer { +contract L2OutputOracle_deleteOutputs_Test is CommonTest { /// @dev Tests that `deleteL2Outputs` succeeds for a single output. function test_deleteOutputs_singleOutput_succeeds() external { proposeAnotherOutput(); proposeAnotherOutput(); - uint256 latestBlockNumber = oracle.latestBlockNumber(); - uint256 latestOutputIndex = oracle.latestOutputIndex(); - Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 1); + uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber(); + uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex(); + Types.OutputProposal memory newLatestOutput = l2OutputOracle.getL2Output(latestOutputIndex - 1); - vm.prank(owner); + vm.prank(l2OutputOracle.challenger()); vm.expectEmit(true, true, false, false); emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex); - oracle.deleteL2Outputs(latestOutputIndex); + l2OutputOracle.deleteL2Outputs(latestOutputIndex); // validate latestBlockNumber has been reduced - uint256 latestBlockNumberAfter = oracle.latestBlockNumber(); - uint256 latestOutputIndexAfter = oracle.latestOutputIndex(); + uint256 latestBlockNumberAfter = l2OutputOracle.latestBlockNumber(); + uint256 latestOutputIndexAfter = l2OutputOracle.latestOutputIndex(); + uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval(); assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter); // validate that the new latest output is as expected. - Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter); + Types.OutputProposal memory proposal = l2OutputOracle.getL2Output(latestOutputIndexAfter); assertEq(newLatestOutput.outputRoot, proposal.outputRoot); assertEq(newLatestOutput.timestamp, proposal.timestamp); } @@ -323,43 +342,44 @@ contract L2OutputOracle_deleteOutputs_Test is L2OutputOracle_Initializer { proposeAnotherOutput(); proposeAnotherOutput(); - uint256 latestBlockNumber = oracle.latestBlockNumber(); - uint256 latestOutputIndex = oracle.latestOutputIndex(); - Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 3); + uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber(); + uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex(); + Types.OutputProposal memory newLatestOutput = l2OutputOracle.getL2Output(latestOutputIndex - 3); - vm.prank(owner); + vm.prank(l2OutputOracle.challenger()); vm.expectEmit(true, true, false, false); emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex - 2); - oracle.deleteL2Outputs(latestOutputIndex - 2); + l2OutputOracle.deleteL2Outputs(latestOutputIndex - 2); // validate latestBlockNumber has been reduced - uint256 latestBlockNumberAfter = oracle.latestBlockNumber(); - uint256 latestOutputIndexAfter = oracle.latestOutputIndex(); + uint256 latestBlockNumberAfter = l2OutputOracle.latestBlockNumber(); + uint256 latestOutputIndexAfter = l2OutputOracle.latestOutputIndex(); + uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval(); assertEq(latestBlockNumber - submissionInterval * 3, latestBlockNumberAfter); // validate that the new latest output is as expected. - Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter); + Types.OutputProposal memory proposal = l2OutputOracle.getL2Output(latestOutputIndexAfter); assertEq(newLatestOutput.outputRoot, proposal.outputRoot); assertEq(newLatestOutput.timestamp, proposal.timestamp); } /// @dev Tests that `deleteL2Outputs` reverts when not called by the challenger. function test_deleteL2Outputs_ifNotChallenger_reverts() external { - uint256 latestBlockNumber = oracle.latestBlockNumber(); + uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber(); vm.expectRevert("L2OutputOracle: only the challenger address can delete outputs"); - oracle.deleteL2Outputs(latestBlockNumber); + l2OutputOracle.deleteL2Outputs(latestBlockNumber); } /// @dev Tests that `deleteL2Outputs` reverts for a non-existant output index. function test_deleteL2Outputs_nonExistent_reverts() external { proposeAnotherOutput(); - uint256 latestBlockNumber = oracle.latestBlockNumber(); + uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber(); - vm.prank(owner); + vm.prank(l2OutputOracle.challenger()); vm.expectRevert("L2OutputOracle: cannot delete outputs after the latest output index"); - oracle.deleteL2Outputs(latestBlockNumber + 1); + l2OutputOracle.deleteL2Outputs(latestBlockNumber + 1); } /// @dev Tests that `deleteL2Outputs` reverts when trying to delete outputs @@ -370,14 +390,14 @@ contract L2OutputOracle_deleteOutputs_Test is L2OutputOracle_Initializer { proposeAnotherOutput(); // Delete the latest two outputs - uint256 latestOutputIndex = oracle.latestOutputIndex(); - vm.prank(owner); - oracle.deleteL2Outputs(latestOutputIndex - 2); + uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex(); + vm.prank(l2OutputOracle.challenger()); + l2OutputOracle.deleteL2Outputs(latestOutputIndex - 2); // Now try to delete the same output again - vm.prank(owner); + vm.prank(l2OutputOracle.challenger()); vm.expectRevert("L2OutputOracle: cannot delete outputs after the latest output index"); - oracle.deleteL2Outputs(latestOutputIndex - 2); + l2OutputOracle.deleteL2Outputs(latestOutputIndex - 2); } /// @dev Tests that `deleteL2Outputs` reverts for finalized outputs. @@ -385,43 +405,48 @@ contract L2OutputOracle_deleteOutputs_Test is L2OutputOracle_Initializer { proposeAnotherOutput(); // Warp past the finalization period + 1 second - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); - uint256 latestOutputIndex = oracle.latestOutputIndex(); + uint256 latestOutputIndex = l2OutputOracle.latestOutputIndex(); // Try to delete a finalized output - vm.prank(owner); + vm.prank(l2OutputOracle.challenger()); vm.expectRevert("L2OutputOracle: cannot delete outputs that have already been finalized"); - oracle.deleteL2Outputs(latestOutputIndex); + l2OutputOracle.deleteL2Outputs(latestOutputIndex); } } -contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { - Proxy internal proxy; - - function setUp() public override { - super.setUp(); - proxy = Proxy(payable(address(oracle))); - } - +contract L2OutputOracleUpgradeable_Test is CommonTest { /// @dev Tests that the proxy is initialized with the correct values. function test_initValuesOnProxy_succeeds() external { - assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval); - assertEq(oracle.submissionInterval(), submissionInterval); - assertEq(oracle.L2_BLOCK_TIME(), l2BlockTime); - assertEq(oracle.l2BlockTime(), l2BlockTime); - assertEq(oracle.startingBlockNumber(), startingBlockNumber); - assertEq(oracle.startingTimestamp(), startingTimestamp); - assertEq(oracle.finalizationPeriodSeconds(), finalizationPeriodSeconds); - assertEq(oracle.PROPOSER(), proposer); - assertEq(oracle.proposer(), proposer); - assertEq(oracle.CHALLENGER(), owner); - assertEq(oracle.challenger(), owner); + address proposer = cfg.l2OutputOracleProposer(); + address challenger = cfg.l2OutputOracleChallenger(); + uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval(); + uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber(); + uint256 startingTimestamp = cfg.l2OutputOracleStartingTimestamp(); + uint256 l2BlockTime = cfg.l2BlockTime(); + uint256 finalizationPeriodSeconds = cfg.finalizationPeriodSeconds(); + + assertEq(l2OutputOracle.SUBMISSION_INTERVAL(), submissionInterval); + assertEq(l2OutputOracle.submissionInterval(), submissionInterval); + assertEq(l2OutputOracle.L2_BLOCK_TIME(), l2BlockTime); + assertEq(l2OutputOracle.l2BlockTime(), l2BlockTime); + assertEq(l2OutputOracle.startingBlockNumber(), startingBlockNumber); + assertEq(l2OutputOracle.startingTimestamp(), startingTimestamp); + assertEq(l2OutputOracle.finalizationPeriodSeconds(), finalizationPeriodSeconds); + assertEq(l2OutputOracle.PROPOSER(), proposer); + assertEq(l2OutputOracle.proposer(), proposer); + assertEq(l2OutputOracle.CHALLENGER(), challenger); + assertEq(l2OutputOracle.challenger(), challenger); } /// @dev Tests that the impl is created with the correct values. function test_initValuesOnImpl_succeeds() external { + L2OutputOracle oracleImpl = L2OutputOracle(mustGetAddress("L2OutputOracle")); + + uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval(); assertEq(submissionInterval, oracleImpl.SUBMISSION_INTERVAL()); + uint256 l2BlockTime = cfg.l2BlockTime(); assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME()); // The values that are set in the initialize function should be all @@ -436,8 +461,10 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { /// @dev Tests that the proxy cannot be initialized twice. function test_initializeProxy_alreadyInitialized_reverts() external { + uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber(); + uint256 startingTimestamp = cfg.l2OutputOracleStartingTimestamp(); vm.expectRevert("Initializable: contract is already initialized"); - L2OutputOracle(payable(proxy)).initialize({ + l2OutputOracle.initialize({ _startingBlockNumber: startingBlockNumber, _startingTimestamp: startingTimestamp, _proposer: address(1), @@ -447,8 +474,11 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { /// @dev Tests that the implementation contract cannot be initialized twice. function test_initializeImpl_alreadyInitialized_reverts() external { + L2OutputOracle oracleImpl = L2OutputOracle(mustGetAddress("L2OutputOracle")); + uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber(); + uint256 startingTimestamp = cfg.l2OutputOracleStartingTimestamp(); vm.expectRevert("Initializable: contract is already initialized"); - L2OutputOracle(oracleImpl).initialize({ + oracleImpl.initialize({ _startingBlockNumber: startingBlockNumber, _startingTimestamp: startingTimestamp, _proposer: address(1), @@ -458,8 +488,9 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { /// @dev Tests that the proxy can be successfully upgraded. function test_upgrading_succeeds() external { + Proxy proxy = Proxy(mustGetAddress("L2OutputOracleProxy")); // Check an unused slot before upgrading. - bytes32 slot21Before = vm.load(address(oracle), bytes32(uint256(21))); + bytes32 slot21Before = vm.load(address(l2OutputOracle), bytes32(uint256(21))); assertEq(bytes32(0), slot21Before); NextImpl nextImpl = new NextImpl(); @@ -470,8 +501,8 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { assertEq(proxy.implementation(), address(nextImpl)); // Verify that the NextImpl contract initialized its values according as expected - bytes32 slot21After = vm.load(address(oracle), bytes32(uint256(21))); - bytes32 slot21Expected = NextImpl(address(oracle)).slot21Init(); + bytes32 slot21After = vm.load(address(l2OutputOracle), bytes32(uint256(21))); + bytes32 slot21Expected = NextImpl(address(l2OutputOracle)).slot21Init(); assertEq(slot21Expected, slot21After); } } diff --git a/packages/contracts-bedrock/test/L2StandardBridge.t.sol b/packages/contracts-bedrock/test/L2StandardBridge.t.sol index be7dd6ff639c..567f2ea9748a 100644 --- a/packages/contracts-bedrock/test/L2StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L2StandardBridge.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.15; // Testing utilities // Target contract is imported by the `Bridge_Initializer` -import { Bridge_Initializer } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { stdStorage, StdStorage } from "forge-std/Test.sol"; import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol"; @@ -23,24 +23,24 @@ contract L2StandardBridge_Test is Bridge_Initializer { /// @dev Tests that the bridge is initialized correctly. function test_initialize_succeeds() external { - assertEq(address(L2Bridge.messenger()), address(L2Messenger)); - assertEq(L1Bridge.l2TokenBridge(), address(L2Bridge)); - assertEq(address(L2Bridge.OTHER_BRIDGE()), address(L1Bridge)); + assertEq(address(l2StandardBridge.messenger()), address(l2CrossDomainMessenger)); + assertEq(l1StandardBridge.l2TokenBridge(), address(l2StandardBridge)); + assertEq(address(l2StandardBridge.OTHER_BRIDGE()), address(l1StandardBridge)); } /// @dev Tests that the bridge receives ETH and successfully initiates a withdrawal. function test_receive_succeeds() external { - assertEq(address(messagePasser).balance, 0); - uint256 nonce = L2Messenger.messageNonce(); + assertEq(address(l2ToL1MessagePasser).balance, 0); + uint256 nonce = l2CrossDomainMessenger.messageNonce(); bytes memory message = abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, alice, 100, hex""); - uint64 baseGas = L2Messenger.baseGas(message, 200_000); + uint64 baseGas = l2CrossDomainMessenger.baseGas(message, 200_000); bytes memory withdrawalData = abi.encodeWithSelector( CrossDomainMessenger.relayMessage.selector, nonce, - address(L2Bridge), - address(L1Bridge), + address(l2StandardBridge), + address(l1StandardBridge), 100, 200_000, message @@ -48,8 +48,8 @@ contract L2StandardBridge_Test is Bridge_Initializer { bytes32 withdrawalHash = Hashing.hashWithdrawal( Types.WithdrawalTransaction({ nonce: nonce, - sender: address(L2Messenger), - target: address(L1Messenger), + sender: address(l2CrossDomainMessenger), + target: address(l1CrossDomainMessenger), value: 100, gasLimit: baseGas, data: withdrawalData @@ -63,24 +63,30 @@ contract L2StandardBridge_Test is Bridge_Initializer { emit ETHBridgeInitiated(alice, alice, 100, hex""); // L2ToL1MessagePasser will emit a MessagePassed event - vm.expectEmit(true, true, true, true, address(messagePasser)); + vm.expectEmit(true, true, true, true, address(l2ToL1MessagePasser)); emit MessagePassed( - nonce, address(L2Messenger), address(L1Messenger), 100, baseGas, withdrawalData, withdrawalHash + nonce, + address(l2CrossDomainMessenger), + address(l1CrossDomainMessenger), + 100, + baseGas, + withdrawalData, + withdrawalHash ); // SentMessage event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L2Messenger)); - emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 200_000); + vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger)); + emit SentMessage(address(l1StandardBridge), address(l2StandardBridge), message, nonce, 200_000); // SentMessageExtension1 event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L2Messenger)); - emit SentMessageExtension1(address(L2Bridge), 100); + vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger)); + emit SentMessageExtension1(address(l2StandardBridge), 100); vm.expectCall( - address(L2Messenger), + address(l2CrossDomainMessenger), abi.encodeWithSelector( CrossDomainMessenger.sendMessage.selector, - address(L1Bridge), + address(l1StandardBridge), message, 200_000 // StandardBridge's RECEIVE_DEFAULT_GAS_LIMIT ) @@ -89,23 +95,26 @@ contract L2StandardBridge_Test is Bridge_Initializer { vm.expectCall( Predeploys.L2_TO_L1_MESSAGE_PASSER, abi.encodeWithSelector( - L2ToL1MessagePasser.initiateWithdrawal.selector, address(L1Messenger), baseGas, withdrawalData + L2ToL1MessagePasser.initiateWithdrawal.selector, + address(l1CrossDomainMessenger), + baseGas, + withdrawalData ) ); vm.prank(alice, alice); - (bool success,) = address(L2Bridge).call{ value: 100 }(hex""); + (bool success,) = address(l2StandardBridge).call{ value: 100 }(hex""); assertEq(success, true); - assertEq(address(messagePasser).balance, 100); + assertEq(address(l2ToL1MessagePasser).balance, 100); } /// @dev Tests that `withdraw` reverts if the amount is not equal to the value sent. function test_withdraw_insufficientValue_reverts() external { - assertEq(address(messagePasser).balance, 0); + assertEq(address(l2ToL1MessagePasser).balance, 0); vm.expectRevert("StandardBridge: bridging ETH must include sufficient ETH value"); vm.prank(alice, alice); - L2Bridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex""); + l2StandardBridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex""); } /// @dev Tests that the legacy `withdraw` interface on the L2StandardBridge @@ -114,7 +123,7 @@ contract L2StandardBridge_Test is Bridge_Initializer { assertTrue(alice.balance >= 100); assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 0); - vm.expectEmit(true, true, true, true, address(L2Bridge)); + vm.expectEmit(true, true, true, true, address(l2StandardBridge)); emit WithdrawalInitiated({ l1Token: address(0), l2Token: Predeploys.LEGACY_ERC20_ETH, @@ -124,11 +133,11 @@ contract L2StandardBridge_Test is Bridge_Initializer { data: hex"" }); - vm.expectEmit(true, true, true, true, address(L2Bridge)); + vm.expectEmit(true, true, true, true, address(l2StandardBridge)); emit ETHBridgeInitiated({ from: alice, to: alice, amount: 100, data: hex"" }); vm.prank(alice, alice); - L2Bridge.withdraw{ value: 100 }({ + l2StandardBridge.withdraw{ value: 100 }({ _l2Token: Predeploys.LEGACY_ERC20_ETH, _amount: 100, _minGasLimit: 1000, @@ -145,19 +154,25 @@ contract PreBridgeERC20 is Bridge_Initializer { // Alice has 100 L2Token deal(_l2Token, alice, 100, true); assertEq(ERC20(_l2Token).balanceOf(alice), 100); - uint256 nonce = L2Messenger.messageNonce(); + uint256 nonce = l2CrossDomainMessenger.messageNonce(); bytes memory message = abi.encodeWithSelector( StandardBridge.finalizeBridgeERC20.selector, address(L1Token), _l2Token, alice, alice, 100, hex"" ); - uint64 baseGas = L2Messenger.baseGas(message, 1000); + uint64 baseGas = l2CrossDomainMessenger.baseGas(message, 1000); bytes memory withdrawalData = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, nonce, address(L2Bridge), address(L1Bridge), 0, 1000, message + CrossDomainMessenger.relayMessage.selector, + nonce, + address(l2StandardBridge), + address(l1StandardBridge), + 0, + 1000, + message ); bytes32 withdrawalHash = Hashing.hashWithdrawal( Types.WithdrawalTransaction({ nonce: nonce, - sender: address(L2Messenger), - target: address(L1Messenger), + sender: address(l2CrossDomainMessenger), + target: address(l1CrossDomainMessenger), value: 0, gasLimit: baseGas, data: withdrawalData @@ -166,28 +181,34 @@ contract PreBridgeERC20 is Bridge_Initializer { if (_isLegacy) { vm.expectCall( - address(L2Bridge), abi.encodeWithSelector(L2Bridge.withdraw.selector, _l2Token, 100, 1000, hex"") + address(l2StandardBridge), + abi.encodeWithSelector(l2StandardBridge.withdraw.selector, _l2Token, 100, 1000, hex"") ); } else { vm.expectCall( - address(L2Bridge), - abi.encodeWithSelector(L2Bridge.bridgeERC20.selector, _l2Token, address(L1Token), 100, 1000, hex"") + address(l2StandardBridge), + abi.encodeWithSelector( + l2StandardBridge.bridgeERC20.selector, _l2Token, address(L1Token), 100, 1000, hex"" + ) ); } vm.expectCall( - address(L2Messenger), - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L1Bridge), message, 1000) + address(l2CrossDomainMessenger), + abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, 1000) ); vm.expectCall( Predeploys.L2_TO_L1_MESSAGE_PASSER, abi.encodeWithSelector( - L2ToL1MessagePasser.initiateWithdrawal.selector, address(L1Messenger), baseGas, withdrawalData + L2ToL1MessagePasser.initiateWithdrawal.selector, + address(l1CrossDomainMessenger), + baseGas, + withdrawalData ) ); - // The L2Bridge should burn the tokens + // The l2StandardBridge should burn the tokens vm.expectCall(_l2Token, abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)); vm.expectEmit(true, true, true, true); @@ -198,16 +219,22 @@ contract PreBridgeERC20 is Bridge_Initializer { vm.expectEmit(true, true, true, true); emit MessagePassed( - nonce, address(L2Messenger), address(L1Messenger), 0, baseGas, withdrawalData, withdrawalHash + nonce, + address(l2CrossDomainMessenger), + address(l1CrossDomainMessenger), + 0, + baseGas, + withdrawalData, + withdrawalHash ); // SentMessage event emitted by the CrossDomainMessenger vm.expectEmit(true, true, true, true); - emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000); + emit SentMessage(address(l1StandardBridge), address(l2StandardBridge), message, nonce, 1000); // SentMessageExtension1 event emitted by the CrossDomainMessenger vm.expectEmit(true, true, true, true); - emit SentMessageExtension1(address(L2Bridge), 0); + emit SentMessageExtension1(address(l2StandardBridge), 0); vm.prank(alice, alice); } @@ -220,7 +247,7 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 { // - calls Withdrawer.initiateWithdrawal function test_withdraw_withdrawingERC20_succeeds() external { _preBridgeERC20({ _isLegacy: true, _l2Token: address(L2Token) }); - L2Bridge.withdraw(address(L2Token), 100, 1000, hex""); + l2StandardBridge.withdraw(address(L2Token), 100, 1000, hex""); assertEq(L2Token.balanceOf(alice), 0); } @@ -231,21 +258,21 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 { // - calls Withdrawer.initiateWithdrawal function test_bridgeERC20_succeeds() external { _preBridgeERC20({ _isLegacy: false, _l2Token: address(L2Token) }); - L2Bridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex""); + l2StandardBridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex""); assertEq(L2Token.balanceOf(alice), 0); } function test_withdrawLegacyERC20_succeeds() external { _preBridgeERC20({ _isLegacy: true, _l2Token: address(LegacyL2Token) }); - L2Bridge.withdraw(address(LegacyL2Token), 100, 1000, hex""); + l2StandardBridge.withdraw(address(LegacyL2Token), 100, 1000, hex""); assertEq(L2Token.balanceOf(alice), 0); } function test_bridgeLegacyERC20_succeeds() external { _preBridgeERC20({ _isLegacy: false, _l2Token: address(LegacyL2Token) }); - L2Bridge.bridgeERC20(address(LegacyL2Token), address(L1Token), 100, 1000, hex""); + l2StandardBridge.bridgeERC20(address(LegacyL2Token), address(L1Token), 100, 1000, hex""); assertEq(L2Token.balanceOf(alice), 0); } @@ -255,7 +282,7 @@ contract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 { deal(address(L2Token), address(this), 100, true); vm.expectRevert("StandardBridge: function can only be called from an EOA"); - L2Bridge.withdraw(address(L2Token), 100, 1000, hex""); + l2StandardBridge.withdraw(address(L2Token), 100, 1000, hex""); } } @@ -265,70 +292,86 @@ contract PreBridgeERC20To is Bridge_Initializer { function _preBridgeERC20To(bool _isLegacy, address _l2Token) internal { deal(_l2Token, alice, 100, true); assertEq(ERC20(L2Token).balanceOf(alice), 100); - uint256 nonce = L2Messenger.messageNonce(); + uint256 nonce = l2CrossDomainMessenger.messageNonce(); bytes memory message = abi.encodeWithSelector( StandardBridge.finalizeBridgeERC20.selector, address(L1Token), _l2Token, alice, bob, 100, hex"" ); - uint64 baseGas = L2Messenger.baseGas(message, 1000); + uint64 baseGas = l2CrossDomainMessenger.baseGas(message, 1000); bytes memory withdrawalData = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, nonce, address(L2Bridge), address(L1Bridge), 0, 1000, message + CrossDomainMessenger.relayMessage.selector, + nonce, + address(l2StandardBridge), + address(l1StandardBridge), + 0, + 1000, + message ); bytes32 withdrawalHash = Hashing.hashWithdrawal( Types.WithdrawalTransaction({ nonce: nonce, - sender: address(L2Messenger), - target: address(L1Messenger), + sender: address(l2CrossDomainMessenger), + target: address(l1CrossDomainMessenger), value: 0, gasLimit: baseGas, data: withdrawalData }) ); - vm.expectEmit(true, true, true, true, address(L2Bridge)); + vm.expectEmit(true, true, true, true, address(l2StandardBridge)); emit WithdrawalInitiated(address(L1Token), _l2Token, alice, bob, 100, hex""); - vm.expectEmit(true, true, true, true, address(L2Bridge)); + vm.expectEmit(true, true, true, true, address(l2StandardBridge)); emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, bob, 100, hex""); - vm.expectEmit(true, true, true, true, address(messagePasser)); + vm.expectEmit(true, true, true, true, address(l2ToL1MessagePasser)); emit MessagePassed( - nonce, address(L2Messenger), address(L1Messenger), 0, baseGas, withdrawalData, withdrawalHash + nonce, + address(l2CrossDomainMessenger), + address(l1CrossDomainMessenger), + 0, + baseGas, + withdrawalData, + withdrawalHash ); // SentMessage event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L2Messenger)); - emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000); + vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger)); + emit SentMessage(address(l1StandardBridge), address(l2StandardBridge), message, nonce, 1000); // SentMessageExtension1 event emitted by the CrossDomainMessenger - vm.expectEmit(true, true, true, true, address(L2Messenger)); - emit SentMessageExtension1(address(L2Bridge), 0); + vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger)); + emit SentMessageExtension1(address(l2StandardBridge), 0); if (_isLegacy) { vm.expectCall( - address(L2Bridge), abi.encodeWithSelector(L2Bridge.withdrawTo.selector, _l2Token, bob, 100, 1000, hex"") + address(l2StandardBridge), + abi.encodeWithSelector(l2StandardBridge.withdrawTo.selector, _l2Token, bob, 100, 1000, hex"") ); } else { vm.expectCall( - address(L2Bridge), + address(l2StandardBridge), abi.encodeWithSelector( - L2Bridge.bridgeERC20To.selector, _l2Token, address(L1Token), bob, 100, 1000, hex"" + l2StandardBridge.bridgeERC20To.selector, _l2Token, address(L1Token), bob, 100, 1000, hex"" ) ); } vm.expectCall( - address(L2Messenger), - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(L1Bridge), message, 1000) + address(l2CrossDomainMessenger), + abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, 1000) ); vm.expectCall( Predeploys.L2_TO_L1_MESSAGE_PASSER, abi.encodeWithSelector( - L2ToL1MessagePasser.initiateWithdrawal.selector, address(L1Messenger), baseGas, withdrawalData + L2ToL1MessagePasser.initiateWithdrawal.selector, + address(l1CrossDomainMessenger), + baseGas, + withdrawalData ) ); - // The L2Bridge should burn the tokens + // The l2StandardBridge should burn the tokens vm.expectCall(address(L2Token), abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)); vm.prank(alice, alice); @@ -340,7 +383,7 @@ contract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To { /// and initiates a withdrawal with `Withdrawer.initiateWithdrawal`. function test_withdrawTo_withdrawingERC20_succeeds() external { _preBridgeERC20To({ _isLegacy: true, _l2Token: address(L2Token) }); - L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex""); + l2StandardBridge.withdrawTo(address(L2Token), bob, 100, 1000, hex""); assertEq(L2Token.balanceOf(alice), 0); } @@ -349,7 +392,7 @@ contract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To { /// and initiates a withdrawal with `Withdrawer.initiateWithdrawal`. function test_bridgeERC20To_succeeds() external { _preBridgeERC20To({ _isLegacy: false, _l2Token: address(L2Token) }); - L2Bridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex""); + l2StandardBridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex""); assertEq(L2Token.balanceOf(alice), 0); } } @@ -361,37 +404,37 @@ contract L2StandardBridge_Bridge_Test is Bridge_Initializer { /// - call `Withdrawer.initiateWithdrawal` if the token pair is not supported function test_finalizeDeposit_depositingERC20_succeeds() external { vm.mockCall( - address(L2Bridge.messenger()), + address(l2StandardBridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L2Bridge.OTHER_BRIDGE())) + abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) ); vm.expectCall(address(L2Token), abi.encodeWithSelector(OptimismMintableERC20.mint.selector, alice, 100)); // Should emit both the bedrock and legacy events - vm.expectEmit(true, true, true, true, address(L2Bridge)); + vm.expectEmit(true, true, true, true, address(l2StandardBridge)); emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex""); - vm.expectEmit(true, true, true, true, address(L2Bridge)); + vm.expectEmit(true, true, true, true, address(l2StandardBridge)); emit ERC20BridgeFinalized(address(L2Token), address(L1Token), alice, alice, 100, hex""); - vm.prank(address(L2Messenger)); - L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex""); + vm.prank(address(l2CrossDomainMessenger)); + l2StandardBridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex""); } /// @dev Tests that `finalizeDeposit` succeeds when depositing ETH. function test_finalizeDeposit_depositingETH_succeeds() external { vm.mockCall( - address(L2Bridge.messenger()), + address(l2StandardBridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L2Bridge.OTHER_BRIDGE())) + abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) ); // Should emit both the bedrock and legacy events - vm.expectEmit(true, true, true, true, address(L2Bridge)); + vm.expectEmit(true, true, true, true, address(l2StandardBridge)); emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex""); - vm.expectEmit(true, true, true, true, address(L2Bridge)); + vm.expectEmit(true, true, true, true, address(l2StandardBridge)); emit ERC20BridgeFinalized( address(L2Token), // localToken address(L1Token), // remoteToken @@ -401,58 +444,58 @@ contract L2StandardBridge_Bridge_Test is Bridge_Initializer { hex"" ); - vm.prank(address(L2Messenger)); - L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex""); + vm.prank(address(l2CrossDomainMessenger)); + l2StandardBridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex""); } /// @dev Tests that `finalizeDeposit` reverts if the amounts do not match. function test_finalizeBridgeETH_incorrectValue_reverts() external { vm.mockCall( - address(L2Bridge.messenger()), + address(l2StandardBridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L2Bridge.OTHER_BRIDGE())) + abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) ); - vm.deal(address(L2Messenger), 100); - vm.prank(address(L2Messenger)); + vm.deal(address(l2CrossDomainMessenger), 100); + vm.prank(address(l2CrossDomainMessenger)); vm.expectRevert("StandardBridge: amount sent does not match amount required"); - L2Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex""); + l2StandardBridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex""); } /// @dev Tests that `finalizeDeposit` reverts if the receipient is the other bridge. function test_finalizeBridgeETH_sendToSelf_reverts() external { vm.mockCall( - address(L2Bridge.messenger()), + address(l2StandardBridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L2Bridge.OTHER_BRIDGE())) + abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) ); - vm.deal(address(L2Messenger), 100); - vm.prank(address(L2Messenger)); + vm.deal(address(l2CrossDomainMessenger), 100); + vm.prank(address(l2CrossDomainMessenger)); vm.expectRevert("StandardBridge: cannot send to self"); - L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Bridge), 100, hex""); + l2StandardBridge.finalizeBridgeETH{ value: 100 }(alice, address(l2StandardBridge), 100, hex""); } /// @dev Tests that `finalizeDeposit` reverts if the receipient is the messenger. function test_finalizeBridgeETH_sendToMessenger_reverts() external { vm.mockCall( - address(L2Bridge.messenger()), + address(l2StandardBridge.messenger()), abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L2Bridge.OTHER_BRIDGE())) + abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) ); - vm.deal(address(L2Messenger), 100); - vm.prank(address(L2Messenger)); + vm.deal(address(l2CrossDomainMessenger), 100); + vm.prank(address(l2CrossDomainMessenger)); vm.expectRevert("StandardBridge: cannot send to messenger"); - L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Messenger), 100, hex""); + l2StandardBridge.finalizeBridgeETH{ value: 100 }(alice, address(l2CrossDomainMessenger), 100, hex""); } } contract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer { /// @dev Tests that `finalizeBridgeETH` succeeds. function test_finalizeBridgeETH_succeeds() external { - address messenger = address(L2Bridge.messenger()); + address messenger = address(l2StandardBridge.messenger()); vm.mockCall( messenger, abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), - abi.encode(address(L2Bridge.OTHER_BRIDGE())) + abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) ); vm.deal(messenger, 100); vm.prank(messenger); @@ -463,6 +506,6 @@ contract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer { vm.expectEmit(true, true, true, true); emit ETHBridgeFinalized(alice, alice, 100, hex""); - L2Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex""); + l2StandardBridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex""); } } diff --git a/packages/contracts-bedrock/test/L2ToL1MessagePasser.t.sol b/packages/contracts-bedrock/test/L2ToL1MessagePasser.t.sol index 9e62c74944b4..0c2c6c8b869a 100644 --- a/packages/contracts-bedrock/test/L2ToL1MessagePasser.t.sol +++ b/packages/contracts-bedrock/test/L2ToL1MessagePasser.t.sol @@ -2,36 +2,13 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { Types } from "src/libraries/Types.sol"; import { Hashing } from "src/libraries/Hashing.sol"; -// Target contract -import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol"; - contract L2ToL1MessagePasserTest is CommonTest { - L2ToL1MessagePasser messagePasser; - - event MessagePassed( - uint256 indexed nonce, - address indexed sender, - address indexed target, - uint256 value, - uint256 gasLimit, - bytes data, - bytes32 withdrawalHash - ); - - event WithdrawerBalanceBurnt(uint256 indexed amount); - - /// @dev Sets up the test suite. - function setUp() public virtual override { - super.setUp(); - messagePasser = new L2ToL1MessagePasser(); - } - /// @dev Tests that `initiateWithdrawal` succeeds and correctly sets the state /// of the message passer for the withdrawal hash. function testFuzz_initiateWithdrawal_succeeds( @@ -43,7 +20,7 @@ contract L2ToL1MessagePasserTest is CommonTest { ) external { - uint256 nonce = messagePasser.messageNonce(); + uint256 nonce = l2ToL1MessagePasser.messageNonce(); bytes32 withdrawalHash = Hashing.hashWithdrawal( Types.WithdrawalTransaction({ @@ -56,70 +33,90 @@ contract L2ToL1MessagePasserTest is CommonTest { }) ); - vm.expectEmit(true, true, true, true); + vm.expectEmit(address(l2ToL1MessagePasser)); emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data, withdrawalHash); vm.deal(_sender, _value); vm.prank(_sender); - messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data); + l2ToL1MessagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data); - assertEq(messagePasser.sentMessages(withdrawalHash), true); + assertEq(l2ToL1MessagePasser.sentMessages(withdrawalHash), true); bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0))); - assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1))); + assertEq(vm.load(address(l2ToL1MessagePasser), slot), bytes32(uint256(1))); } /// @dev Tests that `initiateWithdrawal` succeeds and emits the correct MessagePassed /// log when called by a contract. - function test_initiateWithdrawal_fromContract_succeeds() external { + function testFuzz_initiateWithdrawal_fromContract_succeeds( + address _target, + uint256 _gasLimit, + uint256 _value, + bytes memory _data + ) + external + { bytes32 withdrawalHash = Hashing.hashWithdrawal( - Types.WithdrawalTransaction(messagePasser.messageNonce(), address(this), address(4), 100, 64000, hex"") + Types.WithdrawalTransaction({ + nonce: l2ToL1MessagePasser.messageNonce(), + sender: address(this), + target: _target, + value: _value, + gasLimit: _gasLimit, + data: _data + }) ); - vm.expectEmit(true, true, true, true); - emit MessagePassed(messagePasser.messageNonce(), address(this), address(4), 100, 64000, hex"", withdrawalHash); + vm.expectEmit(address(l2ToL1MessagePasser)); + emit MessagePassed( + l2ToL1MessagePasser.messageNonce(), address(this), _target, _value, _gasLimit, _data, withdrawalHash + ); - vm.deal(address(this), 2 ** 64); - messagePasser.initiateWithdrawal{ value: 100 }(address(4), 64000, hex""); + vm.deal(address(this), _value); + l2ToL1MessagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data); } /// @dev Tests that `initiateWithdrawal` succeeds and emits the correct MessagePassed /// log when called by an EOA. - function test_initiateWithdrawal_fromEOA_succeeds() external { - uint256 gasLimit = 64000; - address target = address(4); - uint256 value = 100; - bytes memory data = hex"ff"; - uint256 nonce = messagePasser.messageNonce(); + function testFuzz_initiateWithdrawal_fromEOA_succeeds( + uint256 _gasLimit, + address _target, + uint256 _value, + bytes memory _data + ) + external + { + uint256 nonce = l2ToL1MessagePasser.messageNonce(); // EOA emulation vm.prank(alice, alice); - vm.deal(alice, 2 ** 64); + vm.deal(alice, _value); bytes32 withdrawalHash = - Hashing.hashWithdrawal(Types.WithdrawalTransaction(nonce, alice, target, value, gasLimit, data)); + Hashing.hashWithdrawal(Types.WithdrawalTransaction(nonce, alice, _target, _value, _gasLimit, _data)); - vm.expectEmit(true, true, true, true); - emit MessagePassed(nonce, alice, target, value, gasLimit, data, withdrawalHash); + vm.expectEmit(address(l2ToL1MessagePasser)); + emit MessagePassed(nonce, alice, _target, _value, _gasLimit, _data, withdrawalHash); - messagePasser.initiateWithdrawal{ value: value }(target, gasLimit, data); + l2ToL1MessagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data }); // the sent messages mapping is filled - assertEq(messagePasser.sentMessages(withdrawalHash), true); + assertEq(l2ToL1MessagePasser.sentMessages(withdrawalHash), true); // the nonce increments - assertEq(nonce + 1, messagePasser.messageNonce()); + assertEq(nonce + 1, l2ToL1MessagePasser.messageNonce()); } /// @dev Tests that `burn` succeeds and destroys the ETH held in the contract. - function test_burn_succeeds() external { - messagePasser.initiateWithdrawal{ value: NON_ZERO_VALUE }(NON_ZERO_ADDRESS, NON_ZERO_GASLIMIT, NON_ZERO_DATA); + function testFuzz_burn_succeeds(uint256 _value, address _target, uint256 _gasLimit, bytes memory _data) external { + vm.deal(address(this), _value); + + l2ToL1MessagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data }); - assertEq(address(messagePasser).balance, NON_ZERO_VALUE); - vm.expectEmit(true, false, false, false); - emit WithdrawerBalanceBurnt(NON_ZERO_VALUE); - messagePasser.burn(); + assertEq(address(l2ToL1MessagePasser).balance, _value); + emit WithdrawerBalanceBurnt(_value); + l2ToL1MessagePasser.burn(); // The Withdrawer should have no balance - assertEq(address(messagePasser).balance, 0); + assertEq(address(l2ToL1MessagePasser).balance, 0); } } diff --git a/packages/contracts-bedrock/test/LegacyERC20ETH.t.sol b/packages/contracts-bedrock/test/LegacyERC20ETH.t.sol index 126fdfe661e2..62e2928f06b9 100644 --- a/packages/contracts-bedrock/test/LegacyERC20ETH.t.sol +++ b/packages/contracts-bedrock/test/LegacyERC20ETH.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; // Target contract dependencies import { Predeploys } from "src/libraries/Predeploys.sol"; diff --git a/packages/contracts-bedrock/test/LegacyMessagePasser.t.sol b/packages/contracts-bedrock/test/LegacyMessagePasser.t.sol index abf841e3e79e..39eb479a3ac0 100644 --- a/packages/contracts-bedrock/test/LegacyMessagePasser.t.sol +++ b/packages/contracts-bedrock/test/LegacyMessagePasser.t.sol @@ -2,27 +2,13 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; - -// Testing contract dependencies -import { Predeploys } from "src/libraries/Predeploys.sol"; - -// Target contract -import { LegacyMessagePasser } from "src/legacy/LegacyMessagePasser.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; contract LegacyMessagePasser_Test is CommonTest { - LegacyMessagePasser messagePasser; - - /// @dev Sets up the test suite. - function setUp() public virtual override { - super.setUp(); - messagePasser = new LegacyMessagePasser(); - } - /// @dev Tests that `passMessageToL1` succeeds. function test_passMessageToL1_succeeds() external { vm.prank(alice); - messagePasser.passMessageToL1(hex"ff"); - assert(messagePasser.sentMessages(keccak256(abi.encodePacked(hex"ff", alice)))); + legacyMessagePasser.passMessageToL1(hex"ff"); + assert(legacyMessagePasser.sentMessages(keccak256(abi.encodePacked(hex"ff", alice)))); } } diff --git a/packages/contracts-bedrock/test/LibPosition.t.sol b/packages/contracts-bedrock/test/LibPosition.t.sol index a60f5e2bafca..20ff04e9fb44 100644 --- a/packages/contracts-bedrock/test/LibPosition.t.sol +++ b/packages/contracts-bedrock/test/LibPosition.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.15; import { Test } from "forge-std/Test.sol"; -import { LibPosition } from "../src/dispute/lib/LibPosition.sol"; +import { LibPosition } from "src/dispute/lib/LibPosition.sol"; import "src/libraries/DisputeTypes.sol"; /// @notice Tests for `LibPosition` diff --git a/packages/contracts-bedrock/test/LivenessGuard.t.sol b/packages/contracts-bedrock/test/LivenessGuard.t.sol index e1f7cdd761b2..2ea2159d25dc 100644 --- a/packages/contracts-bedrock/test/LivenessGuard.t.sol +++ b/packages/contracts-bedrock/test/LivenessGuard.t.sol @@ -47,7 +47,7 @@ contract LivenessGuard_Constructor_Test is LivenessGuard_TestInit { function test_constructor_works() external { address[] memory owners = safeInstance.owners; livenessGuard = new WrappedGuard(safeInstance.safe); - for (uint256 i = 0; i < owners.length; i++) { + for (uint256 i; i < owners.length; i++) { assertEq(livenessGuard.lastLive(owners[i]), initTime); } } @@ -242,7 +242,7 @@ contract LivenessGuard_FuzzOwnerManagement_Test is StdCheats, StdUtils, Liveness (address[] memory ownerAddrs, uint256[] memory ownerkeys) = SafeTestLib.makeAddrsAndKeys("safeTest", initialOwners); // record the private keys for later use - for (uint256 i = 0; i < ownerAddrs.length; i++) { + for (uint256 i; i < ownerAddrs.length; i++) { privateKeys[ownerAddrs[i]] = ownerkeys[i]; } @@ -251,7 +251,7 @@ contract LivenessGuard_FuzzOwnerManagement_Test is StdCheats, StdUtils, Liveness livenessGuard = new WrappedGuard(safeInstance.safe); safeInstance.setGuard(address(livenessGuard)); - for (uint256 i = 0; i < changes.length; i++) { + for (uint256 i; i < changes.length; i++) { vm.warp(block.timestamp + changes[i].timeDelta); OwnerChange memory change = changes[i]; address[] memory currentOwners = safeInstance.safe.getOwners(); @@ -312,16 +312,16 @@ contract LivenessGuard_FuzzOwnerManagement_Test is StdCheats, StdUtils, Liveness // Looks up the private key for each owner uint256[] memory unsortedOwnerPKs = new uint256[](instance.owners.length); - for (uint256 j = 0; j < instance.owners.length; j++) { - unsortedOwnerPKs[j] = privateKeys[instance.owners[j]]; + for (uint256 i; i < instance.owners.length; i++) { + unsortedOwnerPKs[i] = privateKeys[instance.owners[i]]; } // Sort the keys by address and store them in the SafeInstance instance.ownerPKs = SafeTestLib.sortPKsByComputedAddress(unsortedOwnerPKs); // Overwrite the SafeInstances owners array with the computed addresses from the ownerPKs array - for (uint256 k; k < instance.owners.length; k++) { - instance.owners[k] = SafeTestLib.getAddr(instance.ownerPKs[k]); + for (uint256 i; i < instance.owners.length; i++) { + instance.owners[i] = SafeTestLib.getAddr(instance.ownerPKs[i]); } } } diff --git a/packages/contracts-bedrock/test/LivenessModule.t.sol b/packages/contracts-bedrock/test/LivenessModule.t.sol index adc1af45666c..d51ea8fee491 100644 --- a/packages/contracts-bedrock/test/LivenessModule.t.sol +++ b/packages/contracts-bedrock/test/LivenessModule.t.sol @@ -199,7 +199,7 @@ contract LivenessModule_RemoveOwners_TestFail is LivenessModule_TestInit { uint256 numOwners = safeInstance.owners.length; address[] memory ownersToRemove = new address[](numOwners); - for (uint256 i = 0; i < numOwners; i++) { + for (uint256 i; i < numOwners; i++) { ownersToRemove[i] = safeInstance.owners[i]; } address[] memory prevOwners = safeInstance.getPrevOwners(ownersToRemove); @@ -218,7 +218,7 @@ contract LivenessModule_RemoveOwners_TestFail is LivenessModule_TestInit { uint256 numOwners = safeInstance.owners.length - 2; address[] memory ownersToRemove = new address[](numOwners); - for (uint256 i = 0; i < numOwners; i++) { + for (uint256 i; i < numOwners; i++) { ownersToRemove[i] = safeInstance.owners[i]; } address[] memory prevOwners = safeInstance.getPrevOwners(ownersToRemove); @@ -236,7 +236,7 @@ contract LivenessModule_RemoveOwners_TestFail is LivenessModule_TestInit { uint256 numOwners = safeInstance.owners.length - 1; address[] memory ownersToRemove = new address[](numOwners); - for (uint256 i = 0; i < numOwners; i++) { + for (uint256 i; i < numOwners; i++) { ownersToRemove[i] = safeInstance.owners[i]; } address[] memory prevOwners = safeInstance.getPrevOwners(ownersToRemove); @@ -297,7 +297,7 @@ contract LivenessModule_RemoveOwners_Test is LivenessModule_TestInit { uint256 numOwners = safeInstance.owners.length; address[] memory ownersToRemove = new address[](numOwners); - for (uint256 i = 0; i < numOwners; i++) { + for (uint256 i; i < numOwners; i++) { ownersToRemove[i] = safeInstance.owners[i]; } address[] memory prevOwners = safeInstance.getPrevOwners(ownersToRemove); @@ -348,15 +348,12 @@ contract LivenessModule_RemoveOwnersFuzz_Test is LivenessModule_TestInit { // // _numOwners must be at least 4, so that _minOwners can be set to at least 3 by the following bound() call. // Limiting the owner set to 20 helps to keep the runtime of the test reasonable. - console.log("bounding numOwners"); numOwners_ = bound(_numOwners, 4, 20); // _minOwners must be at least 3, otherwise we don't have any range below _minOwners in which to test all of the // ShutDownBehavior options. - console.log("bounding minOwners"); minOwners_ = bound(_minOwners, 3, numOwners_ - 1); // Ensure that _numLiveOwners is less than _numOwners so that we can remove at least one owner. - console.log("bounding numLiveOwners"); numLiveOwners_ = bound(_numLiveOwners, 0, numOwners_ - 1); // The above bounds are a bit tricky, so we assert that the resulting parameters enable us to test all possible @@ -402,20 +399,19 @@ contract LivenessModule_RemoveOwnersFuzz_Test is LivenessModule_TestInit { // Create an array of live owners, and call showLiveness for each of them address[] memory liveOwners = new address[](numLiveOwners); - for (uint256 i = 0; i < numLiveOwners; i++) { + for (uint256 i; i < numLiveOwners; i++) { liveOwners[i] = safeInstance.owners[i]; vm.prank(safeInstance.owners[i]); livenessGuard.showLiveness(); } address[] memory nonLiveOwners = new address[](numOwners - numLiveOwners); - for (uint256 i = 0; i < numOwners - numLiveOwners; i++) { + for (uint256 i; i < numOwners - numLiveOwners; i++) { nonLiveOwners[i] = safeInstance.owners[i + numLiveOwners]; } address[] memory prevOwners; if (numLiveOwners >= minOwners) { - console.log("No shutdown"); // The safe will remain above the minimum number of owners, so we can remove only those owners which are not // live. prevOwners = safeInstance.getPrevOwners(nonLiveOwners); @@ -424,10 +420,10 @@ contract LivenessModule_RemoveOwnersFuzz_Test is LivenessModule_TestInit { // Validate the resulting state of the Safe assertEq(safeInstance.safe.getOwners().length, numLiveOwners); assertEq(safeInstance.safe.getThreshold(), get75PercentThreshold(numLiveOwners)); - for (uint256 i = 0; i < numLiveOwners; i++) { + for (uint256 i; i < numLiveOwners; i++) { assertTrue(safeInstance.safe.isOwner(liveOwners[i])); } - for (uint256 i = 0; i < nonLiveOwners.length; i++) { + for (uint256 i; i < nonLiveOwners.length; i++) { assertFalse(safeInstance.safe.isOwner(nonLiveOwners[i])); } } else { @@ -439,14 +435,10 @@ contract LivenessModule_RemoveOwnersFuzz_Test is LivenessModule_TestInit { // The safe is below the minimum number of owners. // The ShutDownBehavior enum determines how we handle this case. if (shutDownBehavior == ShutDownBehavior.Correct) { - console.log("Correct Shutdown"); // We remove all owners, and transfer ownership to the shutDown owner. // but we need to do remove the non-live owners first, so we reverse the owners array, since // the first owners in the array were the ones to call showLiveness. - // ownersToRemove = new address[](numOwners); - for (uint256 i = 0; i < numOwners; i++) { - // ownersToRemove[numOwners - i - 1] = safeInstance.owners[i]; - // ownersToRemove[i] = safeInstance.owners[numOwners - i - 1]; + for (uint256 i; i < numOwners; i++) { ownersToRemove.push(safeInstance.owners[numOwners - i - 1]); } prevOwners = safeInstance.getPrevOwners(ownersToRemove); @@ -461,14 +453,11 @@ contract LivenessModule_RemoveOwnersFuzz_Test is LivenessModule_TestInit { // trigger that behavior. We initialize that value here then set it in the if statements below. uint256 numOwnersToRemoveinShutDown; if (shutDownBehavior == ShutDownBehavior.DoesNotRemoveAllOwners) { - console.log("Shutdown DoesNotRemoveAllOwners"); // In the DoesNotRemoveAllOwners case, we should have more than 1 of the pre-existing owners // remaining - console.log("bounding numOwnersToRemoveinShutDown"); numOwnersToRemoveinShutDown = bound(_numOwnersToRemoveinShutDown, numOwners - minOwners + 1, numOwners - 2); - uint256 i = 0; - for (i; i < numOwnersToRemoveinShutDown; i++) { + for (uint256 i; i < numOwnersToRemoveinShutDown; i++) { // Add non-live owners to remove first if (i < nonLiveOwners.length) { ownersToRemove.push(nonLiveOwners[i]); @@ -483,11 +472,9 @@ contract LivenessModule_RemoveOwnersFuzz_Test is LivenessModule_TestInit { ); livenessModule.removeOwners(prevOwners, ownersToRemove); } else if (shutDownBehavior == ShutDownBehavior.DoesNotTransferToFallbackOwner) { - console.log("Shutdown DoesNotTransferToFallbackOwner"); // In the DoesNotRemoveAllOwners case, we should have exactly 1 pre-existing owners remaining numOwnersToRemoveinShutDown = numOwners - 1; - uint256 i = 0; - for (i; i < numOwnersToRemoveinShutDown; i++) { + for (uint256 i; i < numOwnersToRemoveinShutDown; i++) { // Add non-live owners to remove first if (i < nonLiveOwners.length) { ownersToRemove.push(nonLiveOwners[i]); @@ -503,8 +490,8 @@ contract LivenessModule_RemoveOwnersFuzz_Test is LivenessModule_TestInit { // For both of the incorrect behaviors, verify no change to the Safe state assertEq(safeInstance.safe.getOwners().length, numOwners); assertEq(safeInstance.safe.getThreshold(), get75PercentThreshold(numOwners)); - for (uint256 j = 0; j < numOwners; j++) { - assertTrue(safeInstance.safe.isOwner(safeInstance.owners[j])); + for (uint256 i; i < numOwners; i++) { + assertTrue(safeInstance.safe.isOwner(safeInstance.owners[i])); } } } diff --git a/packages/contracts-bedrock/test/MIPS.t.sol b/packages/contracts-bedrock/test/MIPS.t.sol index 7f1dfdead49a..f34b453e9c8c 100644 --- a/packages/contracts-bedrock/test/MIPS.t.sol +++ b/packages/contracts-bedrock/test/MIPS.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { CommonTest } from "./CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; import { MIPS } from "src/cannon/MIPS.sol"; import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; import "src/libraries/DisputeTypes.sol"; diff --git a/packages/contracts-bedrock/test/MerkleTrie.t.sol b/packages/contracts-bedrock/test/MerkleTrie.t.sol index 59673f06e2ae..1727940eff7c 100644 --- a/packages/contracts-bedrock/test/MerkleTrie.t.sol +++ b/packages/contracts-bedrock/test/MerkleTrie.t.sol @@ -1,10 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { CommonTest } from "test/CommonTest.t.sol"; +import { Test } from "forge-std/Test.sol"; import { MerkleTrie } from "src/libraries/trie/MerkleTrie.sol"; +import { FFIInterface } from "test/setup/FFIInterface.sol"; + +contract MerkleTrie_get_Test is Test { + FFIInterface ffi; + + function setUp() public { + ffi = new FFIInterface(); + } -contract MerkleTrie_get_Test is CommonTest { function test_get_validProof1_succeeds() external { bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f; bytes memory key = hex"6b6579326262"; diff --git a/packages/contracts-bedrock/test/MintManager.t.sol b/packages/contracts-bedrock/test/MintManager.t.sol index 92fceec0ae1a..00cc791b98c2 100644 --- a/packages/contracts-bedrock/test/MintManager.t.sol +++ b/packages/contracts-bedrock/test/MintManager.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; // Target contract dependencies import { GovernanceToken } from "src/governance/GovernanceToken.sol"; diff --git a/packages/contracts-bedrock/test/OptimismMintableERC20.t.sol b/packages/contracts-bedrock/test/OptimismMintableERC20.t.sol index 40233eded0f8..6bb332473ecd 100644 --- a/packages/contracts-bedrock/test/OptimismMintableERC20.t.sol +++ b/packages/contracts-bedrock/test/OptimismMintableERC20.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Bridge_Initializer } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { ILegacyMintableERC20, IOptimismMintableERC20 } from "src/universal/IOptimismMintableERC20.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; @@ -14,7 +14,7 @@ contract OptimismMintableERC20_Test is Bridge_Initializer { } function test_bridge_succeeds() external { - assertEq(L2Token.bridge(), address(L2Bridge)); + assertEq(L2Token.bridge(), address(l2StandardBridge)); } function test_l1Token_succeeds() external { @@ -22,7 +22,7 @@ contract OptimismMintableERC20_Test is Bridge_Initializer { } function test_l2Bridge_succeeds() external { - assertEq(L2Token.l2Bridge(), address(L2Bridge)); + assertEq(L2Token.l2Bridge(), address(l2StandardBridge)); } function test_legacy_succeeds() external { @@ -31,16 +31,16 @@ contract OptimismMintableERC20_Test is Bridge_Initializer { assertEq(L2Token.remoteToken(), address(L1Token)); assertEq(L2Token.l1Token(), address(L1Token)); // Getters for the bridge - assertEq(L2Token.BRIDGE(), address(L2Bridge)); - assertEq(L2Token.bridge(), address(L2Bridge)); - assertEq(L2Token.l2Bridge(), address(L2Bridge)); + assertEq(L2Token.BRIDGE(), address(l2StandardBridge)); + assertEq(L2Token.bridge(), address(l2StandardBridge)); + assertEq(L2Token.l2Bridge(), address(l2StandardBridge)); } function test_mint_succeeds() external { vm.expectEmit(true, true, true, true); emit Mint(alice, 100); - vm.prank(address(L2Bridge)); + vm.prank(address(l2StandardBridge)); L2Token.mint(alice, 100); assertEq(L2Token.balanceOf(alice), 100); @@ -54,13 +54,13 @@ contract OptimismMintableERC20_Test is Bridge_Initializer { } function test_burn_succeeds() external { - vm.prank(address(L2Bridge)); + vm.prank(address(l2StandardBridge)); L2Token.mint(alice, 100); vm.expectEmit(true, true, true, true); emit Burn(alice, 100); - vm.prank(address(L2Bridge)); + vm.prank(address(l2StandardBridge)); L2Token.burn(alice, 100); assertEq(L2Token.balanceOf(alice), 0); diff --git a/packages/contracts-bedrock/test/OptimismMintableERC20Factory.t.sol b/packages/contracts-bedrock/test/OptimismMintableERC20Factory.t.sol index a09ea0f94df7..c856e721f825 100644 --- a/packages/contracts-bedrock/test/OptimismMintableERC20Factory.t.sol +++ b/packages/contracts-bedrock/test/OptimismMintableERC20Factory.t.sol @@ -2,18 +2,14 @@ pragma solidity 0.8.15; import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; -import { Bridge_Initializer } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; contract OptimismMintableTokenFactory_Test is Bridge_Initializer { event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken); event OptimismMintableERC20Created(address indexed localToken, address indexed remoteToken, address deployer); - function setUp() public override { - super.setUp(); - } - function test_bridge_succeeds() external { - assertEq(address(L2TokenFactory.BRIDGE()), address(L2Bridge)); + assertEq(address(l2OptimismMintableERC20Factory.BRIDGE()), address(l2StandardBridge)); } function test_createStandardL2Token_succeeds() external { @@ -29,7 +25,7 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer { emit OptimismMintableERC20Created(local, remote, alice); vm.prank(alice); - address addr = L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP"); + address addr = l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP"); assertTrue(addr == local); assertTrue(OptimismMintableERC20(local).decimals() == 18); } @@ -45,7 +41,7 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer { emit OptimismMintableERC20Created(local, remote, alice); vm.prank(alice); - address addr = L2TokenFactory.createOptimismMintableERC20WithDecimals(remote, "Beep", "BOOP", 6); + address addr = l2OptimismMintableERC20Factory.createOptimismMintableERC20WithDecimals(remote, "Beep", "BOOP", 6); assertTrue(addr == local); assertTrue(OptimismMintableERC20(local).decimals() == 6); @@ -55,18 +51,18 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer { address remote = address(4); vm.prank(alice); - L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP"); + l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP"); vm.expectRevert(); vm.prank(alice); - L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP"); + l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP"); } function test_createStandardL2Token_remoteIsZero_reverts() external { address remote = address(0); vm.expectRevert("OptimismMintableERC20Factory: must provide remote token address"); - L2TokenFactory.createStandardL2Token(remote, "Beep", "BOOP"); + l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP"); } function calculateTokenAddress( @@ -79,10 +75,12 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer { view returns (address) { - bytes memory constructorArgs = abi.encode(address(L2Bridge), _remote, _name, _symbol, _decimals); + bytes memory constructorArgs = abi.encode(address(l2StandardBridge), _remote, _name, _symbol, _decimals); bytes memory bytecode = abi.encodePacked(type(OptimismMintableERC20).creationCode, constructorArgs); bytes32 salt = keccak256(abi.encode(_remote, _name, _symbol, _decimals)); - bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(L2TokenFactory), salt, keccak256(bytecode))); + bytes32 hash = keccak256( + abi.encodePacked(bytes1(0xff), address(l2OptimismMintableERC20Factory), salt, keccak256(bytecode)) + ); return address(uint160(uint256(hash))); } } diff --git a/packages/contracts-bedrock/test/OptimismMintableERC721.t.sol b/packages/contracts-bedrock/test/OptimismMintableERC721.t.sol index 5aac93b2eb4c..9a9eede4b4d6 100644 --- a/packages/contracts-bedrock/test/OptimismMintableERC721.t.sol +++ b/packages/contracts-bedrock/test/OptimismMintableERC721.t.sol @@ -5,10 +5,10 @@ import { ERC721, IERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol import { IERC721Enumerable } from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; -import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { OptimismMintableERC721, IOptimismMintableERC721 } from "src/universal/OptimismMintableERC721.sol"; -contract OptimismMintableERC721_Test is ERC721Bridge_Initializer { +contract OptimismMintableERC721_Test is Bridge_Initializer { ERC721 internal L1NFT; OptimismMintableERC721 internal L2NFT; @@ -24,7 +24,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer { // Set up the token pair. L1NFT = new ERC721("L1NFT", "L1T"); L2NFT = new OptimismMintableERC721( - address(L2NFTBridge), + address(l2ERC721Bridge), 1, address(L1NFT), "L2NFT", @@ -40,10 +40,10 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer { assertEq(L2NFT.name(), "L2NFT"); assertEq(L2NFT.symbol(), "L2T"); assertEq(L2NFT.remoteToken(), address(L1NFT)); - assertEq(L2NFT.bridge(), address(L2NFTBridge)); + assertEq(L2NFT.bridge(), address(l2ERC721Bridge)); assertEq(L2NFT.remoteChainId(), 1); assertEq(L2NFT.REMOTE_TOKEN(), address(L1NFT)); - assertEq(L2NFT.BRIDGE(), address(L2NFTBridge)); + assertEq(L2NFT.BRIDGE(), address(l2ERC721Bridge)); assertEq(L2NFT.REMOTE_CHAIN_ID(), 1); } @@ -69,7 +69,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer { emit Mint(alice, 1); // Mint the token. - vm.prank(address(L2NFTBridge)); + vm.prank(address(l2ERC721Bridge)); L2NFT.safeMint(alice, 1); // Token should be owned by alice. @@ -85,7 +85,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer { function test_burn_succeeds() external { // Mint the token first. - vm.prank(address(L2NFTBridge)); + vm.prank(address(l2ERC721Bridge)); L2NFT.safeMint(alice, 1); // Expect a transfer event. @@ -97,7 +97,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer { emit Burn(alice, 1); // Burn the token. - vm.prank(address(L2NFTBridge)); + vm.prank(address(l2ERC721Bridge)); L2NFT.burn(alice, 1); // Token should be owned by address(0). @@ -107,7 +107,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer { function test_burn_notBridge_reverts() external { // Mint the token first. - vm.prank(address(L2NFTBridge)); + vm.prank(address(l2ERC721Bridge)); L2NFT.safeMint(alice, 1); // Try to burn the token. @@ -118,7 +118,7 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer { function test_tokenURI_succeeds() external { // Mint the token first. - vm.prank(address(L2NFTBridge)); + vm.prank(address(l2ERC721Bridge)); L2NFT.safeMint(alice, 1); // Token URI should be correct. diff --git a/packages/contracts-bedrock/test/OptimismMintableERC721Factory.t.sol b/packages/contracts-bedrock/test/OptimismMintableERC721Factory.t.sol index ee70e3ff9f3b..d337b58a5b14 100644 --- a/packages/contracts-bedrock/test/OptimismMintableERC721Factory.t.sol +++ b/packages/contracts-bedrock/test/OptimismMintableERC721Factory.t.sol @@ -2,11 +2,11 @@ pragma solidity 0.8.15; import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { OptimismMintableERC721 } from "src/universal/OptimismMintableERC721.sol"; import { OptimismMintableERC721Factory } from "src/universal/OptimismMintableERC721Factory.sol"; -contract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer { +contract OptimismMintableERC721Factory_Test is Bridge_Initializer { OptimismMintableERC721Factory internal factory; event OptimismMintableERC721Created(address indexed localToken, address indexed remoteToken, address deployer); @@ -15,14 +15,14 @@ contract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer { super.setUp(); // Set up the token pair. - factory = new OptimismMintableERC721Factory(address(L2NFTBridge), 1); + factory = new OptimismMintableERC721Factory(address(l2ERC721Bridge), 1); // Label the addresses for nice traces. vm.label(address(factory), "OptimismMintableERC721Factory"); } function test_constructor_succeeds() external { - assertEq(factory.BRIDGE(), address(L2NFTBridge)); + assertEq(factory.BRIDGE(), address(l2ERC721Bridge)); assertEq(factory.REMOTE_CHAIN_ID(), 1); } @@ -49,7 +49,7 @@ contract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer { assertEq(created.name(), "L2Token"); assertEq(created.symbol(), "L2T"); assertEq(created.REMOTE_TOKEN(), remote); - assertEq(created.BRIDGE(), address(L2NFTBridge)); + assertEq(created.BRIDGE(), address(l2ERC721Bridge)); assertEq(created.REMOTE_CHAIN_ID(), 1); } @@ -80,7 +80,7 @@ contract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer { view returns (address) { - bytes memory constructorArgs = abi.encode(address(L2NFTBridge), 1, _remote, _name, _symbol); + bytes memory constructorArgs = abi.encode(address(l2ERC721Bridge), 1, _remote, _name, _symbol); bytes memory bytecode = abi.encodePacked(type(OptimismMintableERC721).creationCode, constructorArgs); bytes32 salt = keccak256(abi.encode(_remote, _name, _symbol)); bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(factory), salt, keccak256(bytecode))); diff --git a/packages/contracts-bedrock/test/OptimismPortal.t.sol b/packages/contracts-bedrock/test/OptimismPortal.t.sol index d116ff17c275..414fc65a8be3 100644 --- a/packages/contracts-bedrock/test/OptimismPortal.t.sol +++ b/packages/contracts-bedrock/test/OptimismPortal.t.sol @@ -3,7 +3,10 @@ pragma solidity 0.8.15; // Testing utilities import { stdError } from "forge-std/Test.sol"; -import { Portal_Initializer, CommonTest, NextImpl } from "test/CommonTest.t.sol"; + +import { CommonTest } from "test/setup/CommonTest.sol"; +import { NextImpl } from "test/mocks/NextImpl.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Libraries import { Types } from "src/libraries/Types.sol"; @@ -16,97 +19,111 @@ import { ResourceMetering } from "src/L1/ResourceMetering.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; - -// Target contract import { OptimismPortal } from "src/L1/OptimismPortal.sol"; -contract OptimismPortal_Test is Portal_Initializer { +contract OptimismPortal_Test is CommonTest { event Paused(address); event Unpaused(address); + address depositor; + + function setUp() public override { + super.setUp(); + depositor = makeAddr("depositor"); + } + /// @dev Tests that the constructor sets the correct values. function test_constructor_succeeds() external { - assertEq(address(op.L2_ORACLE()), address(oracle)); - assertEq(address(op.l2Oracle()), address(oracle)); - assertEq(op.GUARDIAN(), guardian); - assertEq(op.guardian(), guardian); - assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD); - assertEq(op.paused(), false); + address guardian = cfg.portalGuardian(); + assertEq(address(optimismPortal.L2_ORACLE()), address(l2OutputOracle)); + assertEq(address(optimismPortal.l2Oracle()), address(l2OutputOracle)); + assertEq(optimismPortal.GUARDIAN(), guardian); + assertEq(optimismPortal.guardian(), guardian); + assertEq(optimismPortal.l2Sender(), 0x000000000000000000000000000000000000dEaD); + assertEq(optimismPortal.paused(), false); } /// @dev Tests that `pause` successfully pauses /// when called by the GUARDIAN. function test_pause_succeeds() external { - address guardian = op.GUARDIAN(); + address guardian = optimismPortal.GUARDIAN(); - assertEq(op.paused(), false); + assertEq(optimismPortal.paused(), false); - vm.expectEmit(true, true, true, true, address(op)); + vm.expectEmit(address(optimismPortal)); emit Paused(guardian); vm.prank(guardian); - op.pause(); + optimismPortal.pause(); - assertEq(op.paused(), true); + assertEq(optimismPortal.paused(), true); } /// @dev Tests that `pause` reverts when called by a non-GUARDIAN. function test_pause_onlyGuardian_reverts() external { - assertEq(op.paused(), false); + assertEq(optimismPortal.paused(), false); - assertTrue(op.GUARDIAN() != alice); + assertTrue(optimismPortal.GUARDIAN() != alice); vm.expectRevert("OptimismPortal: only guardian can pause"); vm.prank(alice); - op.pause(); + optimismPortal.pause(); - assertEq(op.paused(), false); + assertEq(optimismPortal.paused(), false); } /// @dev Tests that `unpause` successfully unpauses /// when called by the GUARDIAN. function test_unpause_succeeds() external { - address guardian = op.GUARDIAN(); + address guardian = optimismPortal.GUARDIAN(); vm.prank(guardian); - op.pause(); - assertEq(op.paused(), true); + optimismPortal.pause(); + assertEq(optimismPortal.paused(), true); - vm.expectEmit(true, true, true, true, address(op)); + vm.expectEmit(address(optimismPortal)); emit Unpaused(guardian); vm.prank(guardian); - op.unpause(); + optimismPortal.unpause(); - assertEq(op.paused(), false); + assertEq(optimismPortal.paused(), false); } /// @dev Tests that `unpause` reverts when called by a non-GUARDIAN. function test_unpause_onlyGuardian_reverts() external { - address guardian = op.GUARDIAN(); + address guardian = optimismPortal.GUARDIAN(); vm.prank(guardian); - op.pause(); - assertEq(op.paused(), true); + optimismPortal.pause(); + assertEq(optimismPortal.paused(), true); - assertTrue(op.GUARDIAN() != alice); + assertTrue(optimismPortal.GUARDIAN() != alice); vm.expectRevert("OptimismPortal: only guardian can unpause"); vm.prank(alice); - op.unpause(); + optimismPortal.unpause(); - assertEq(op.paused(), true); + assertEq(optimismPortal.paused(), true); } /// @dev Tests that `receive` successdully deposits ETH. - function test_receive_succeeds() external { - vm.expectEmit(true, true, false, true); - emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex""); + function testFuzz_receive_succeeds(uint256 _value) external { + vm.expectEmit(address(optimismPortal)); + emitTransactionDeposited({ + _from: alice, + _to: alice, + _value: _value, + _mint: _value, + _gasLimit: 100_000, + _isCreation: false, + _data: hex"" + }); // give alice money and send as an eoa - vm.deal(alice, 2 ** 64); + vm.deal(alice, _value); vm.prank(alice, alice); - (bool s,) = address(op).call{ value: 100 }(hex""); + (bool s,) = address(optimismPortal).call{ value: _value }(hex""); - assert(s); - assertEq(address(op).balance, 100); + assertTrue(s); + assertEq(address(optimismPortal).balance, _value); } /// @dev Tests that `depositTransaction` reverts when the destination address is non-zero @@ -114,16 +131,16 @@ contract OptimismPortal_Test is Portal_Initializer { function test_depositTransaction_contractCreation_reverts() external { // contract creation must have a target of address(0) vm.expectRevert("OptimismPortal: must send to address(0) when creating a contract"); - op.depositTransaction(address(1), 1, 0, true, hex""); + optimismPortal.depositTransaction(address(1), 1, 0, true, hex""); } /// @dev Tests that `depositTransaction` reverts when the data is too large. /// This places an upper bound on unsafe blocks sent over p2p. function test_depositTransaction_largeData_reverts() external { uint256 size = 120_001; - uint64 gasLimit = op.minimumGasLimit(uint64(size)); + uint64 gasLimit = optimismPortal.minimumGasLimit(uint64(size)); vm.expectRevert("OptimismPortal: data too large"); - op.depositTransaction({ + optimismPortal.depositTransaction({ _to: address(0), _value: 0, _gasLimit: gasLimit, @@ -135,203 +152,171 @@ contract OptimismPortal_Test is Portal_Initializer { /// @dev Tests that `depositTransaction` reverts when the gas limit is too small. function test_depositTransaction_smallGasLimit_reverts() external { vm.expectRevert("OptimismPortal: gas limit too small"); - op.depositTransaction({ _to: address(1), _value: 0, _gasLimit: 0, _isCreation: false, _data: hex"" }); + optimismPortal.depositTransaction({ _to: address(1), _value: 0, _gasLimit: 0, _isCreation: false, _data: hex"" }); } /// @dev Tests that `depositTransaction` succeeds for small, /// but sufficient, gas limits. function testFuzz_depositTransaction_smallGasLimit_succeeds(bytes memory _data, bool _shouldFail) external { - vm.assume(_data.length <= type(uint64).max); - - uint64 gasLimit = op.minimumGasLimit(uint64(_data.length)); + uint64 gasLimit = optimismPortal.minimumGasLimit(uint64(_data.length)); if (_shouldFail) { gasLimit = uint64(bound(gasLimit, 0, gasLimit - 1)); vm.expectRevert("OptimismPortal: gas limit too small"); } - op.depositTransaction({ _to: address(0x40), _value: 0, _gasLimit: gasLimit, _isCreation: false, _data: _data }); + optimismPortal.depositTransaction({ + _to: address(0x40), + _value: 0, + _gasLimit: gasLimit, + _isCreation: false, + _data: _data + }); } /// @dev Tests that `minimumGasLimit` succeeds for small calldata sizes. /// The gas limit should be 21k for 0 calldata and increase linearly /// for larger calldata sizes. function test_minimumGasLimit_succeeds() external { - assertEq(op.minimumGasLimit(0), 21_000); - assertTrue(op.minimumGasLimit(2) > op.minimumGasLimit(1)); - assertTrue(op.minimumGasLimit(3) > op.minimumGasLimit(2)); - } - - /// @dev Tests that `depositTransaction` succeeds for an EOA depositing a tx with 0 value. - function test_depositTransaction_noValueEOA_succeeds() external { - // EOA emulation - vm.prank(address(this), address(this)); - vm.expectEmit(true, true, false, true); - emitTransactionDeposited( - address(this), NON_ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA - ); - - op.depositTransaction(NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); - } - - /// @dev Tests that `depositTransaction` succeeds for a contract depositing a tx with 0 value. - function test_depositTransaction_noValueContract_succeeds() external { - vm.expectEmit(true, true, false, true); - emitTransactionDeposited( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - NON_ZERO_ADDRESS, - ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ); - - op.depositTransaction(NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA); - } - - /// @dev Tests that `depositTransaction` succeeds for an EOA - /// depositing a contract creation with 0 value. - function test_depositTransaction_createWithZeroValueForEOA_succeeds() external { - // EOA emulation - vm.prank(address(this), address(this)); - - vm.expectEmit(true, true, false, true); - emitTransactionDeposited( - address(this), ZERO_ADDRESS, ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA - ); - - op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); + assertEq(optimismPortal.minimumGasLimit(0), 21_000); + assertTrue(optimismPortal.minimumGasLimit(2) > optimismPortal.minimumGasLimit(1)); + assertTrue(optimismPortal.minimumGasLimit(3) > optimismPortal.minimumGasLimit(2)); } - /// @dev Tests that `depositTransaction` succeeds for a contract - /// depositing a contract creation with 0 value. - function test_depositTransaction_createWithZeroValueForContract_succeeds() external { - vm.expectEmit(true, true, false, true); - emitTransactionDeposited( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - ZERO_ADDRESS, - ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA - ); - - op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); - } - - /// @dev Tests that `depositTransaction` succeeds for an EOA depositing a tx with ETH. - function test_depositTransaction_withEthValueFromEOA_succeeds() external { - // EOA emulation - vm.prank(address(this), address(this)); - - vm.expectEmit(true, true, false, true); - emitTransactionDeposited( - address(this), NON_ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA - ); - - op.depositTransaction{ value: NON_ZERO_VALUE }( - NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA - ); - assertEq(address(op).balance, NON_ZERO_VALUE); - } - - /// @dev Tests that `depositTransaction` succeeds for a contract depositing a tx with ETH. - function test_depositTransaction_withEthValueFromContract_succeeds() external { - vm.expectEmit(true, true, false, true); - emitTransactionDeposited( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - NON_ZERO_ADDRESS, - NON_ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - false, - NON_ZERO_DATA - ); - - op.depositTransaction{ value: NON_ZERO_VALUE }( - NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA + /// @dev Tests that `depositTransaction` succeeds for an EOA. + function testFuzz_depositTransaction_eoa_succeeds( + address _to, + uint64 _gasLimit, + uint256 _value, + uint256 _mint, + bool _isCreation, + bytes memory _data + ) + external + { + _gasLimit = uint64( + bound( + _gasLimit, + optimismPortal.minimumGasLimit(uint64(_data.length)), + systemConfig.resourceConfig().maxResourceLimit + ) ); - } + if (_isCreation) _to = address(0); - /// @dev Tests that `depositTransaction` succeeds for an EOA depositing a contract creation with ETH. - function test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() external { // EOA emulation - vm.prank(address(this), address(this)); - - vm.expectEmit(true, true, false, true); - emitTransactionDeposited( - address(this), ZERO_ADDRESS, NON_ZERO_VALUE, ZERO_VALUE, NON_ZERO_GASLIMIT, true, hex"" - ); + vm.expectEmit(address(optimismPortal)); + emitTransactionDeposited({ + _from: depositor, + _to: _to, + _value: _value, + _mint: _mint, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); - op.depositTransaction{ value: NON_ZERO_VALUE }(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, hex""); - assertEq(address(op).balance, NON_ZERO_VALUE); + vm.deal(depositor, _mint); + vm.prank(depositor, depositor); + optimismPortal.depositTransaction{ value: _mint }({ + _to: _to, + _value: _value, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); + assertEq(address(optimismPortal).balance, _mint); } - /// @dev Tests that `depositTransaction` succeeds for a contract depositing a contract creation with ETH. - function test_depositTransaction_withEthValueAndContractContractCreation_succeeds() external { - vm.expectEmit(true, true, false, true); - emitTransactionDeposited( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - ZERO_ADDRESS, - NON_ZERO_VALUE, - ZERO_VALUE, - NON_ZERO_GASLIMIT, - true, - NON_ZERO_DATA + /// @dev Tests that `depositTransaction` succeeds for a contract. + function testFuzz_depositTransaction_contract_succeeds( + address _to, + uint64 _gasLimit, + uint256 _value, + uint256 _mint, + bool _isCreation, + bytes memory _data + ) + external + { + _gasLimit = uint64( + bound( + _gasLimit, + optimismPortal.minimumGasLimit(uint64(_data.length)), + systemConfig.resourceConfig().maxResourceLimit + ) ); + if (_isCreation) _to = address(0); + + vm.expectEmit(address(optimismPortal)); + emitTransactionDeposited({ + _from: AddressAliasHelper.applyL1ToL2Alias(address(this)), + _to: _to, + _value: _value, + _mint: _mint, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); - op.depositTransaction{ value: NON_ZERO_VALUE }(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); - assertEq(address(op).balance, NON_ZERO_VALUE); + vm.deal(address(this), _mint); + vm.prank(address(this)); + optimismPortal.depositTransaction{ value: _mint }({ + _to: _to, + _value: _value, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); + assertEq(address(optimismPortal).balance, _mint); } /// @dev Tests that `isOutputFinalized` succeeds for an EOA depositing a tx with ETH and data. function test_simple_isOutputFinalized_succeeds() external { + uint256 startingBlockNumber = cfg.l2OutputOracleStartingBlockNumber(); + uint256 ts = block.timestamp; vm.mockCall( - address(op.L2_ORACLE()), + address(optimismPortal.L2_ORACLE()), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), abi.encode(Types.OutputProposal(bytes32(uint256(1)), uint128(ts), uint128(startingBlockNumber))) ); // warp to the finalization period - vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS()); - assertEq(op.isOutputFinalized(0), false); + vm.warp(ts + l2OutputOracle.FINALIZATION_PERIOD_SECONDS()); + assertEq(optimismPortal.isOutputFinalized(0), false); // warp past the finalization period - vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS() + 1); - assertEq(op.isOutputFinalized(0), true); + vm.warp(ts + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); + assertEq(optimismPortal.isOutputFinalized(0), true); } /// @dev Tests `isOutputFinalized` for a finalized output. function test_isOutputFinalized_succeeds() external { - uint256 checkpoint = oracle.nextBlockNumber(); - uint256 nextOutputIndex = oracle.nextOutputIndex(); + uint256 checkpoint = l2OutputOracle.nextBlockNumber(); + uint256 nextOutputIndex = l2OutputOracle.nextOutputIndex(); vm.roll(checkpoint); - vm.warp(oracle.computeL2Timestamp(checkpoint) + 1); - vm.prank(oracle.PROPOSER()); - oracle.proposeL2Output(keccak256(abi.encode(2)), checkpoint, 0, 0); + vm.warp(l2OutputOracle.computeL2Timestamp(checkpoint) + 1); + vm.prank(l2OutputOracle.PROPOSER()); + l2OutputOracle.proposeL2Output(keccak256(abi.encode(2)), checkpoint, 0, 0); // warp to the final second of the finalization period - uint256 finalizationHorizon = block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS(); + uint256 finalizationHorizon = block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS(); vm.warp(finalizationHorizon); // The checkpointed block should not be finalized until 1 second from now. - assertEq(op.isOutputFinalized(nextOutputIndex), false); + assertEq(optimismPortal.isOutputFinalized(nextOutputIndex), false); // Nor should a block after it vm.expectRevert(stdError.indexOOBError); - assertEq(op.isOutputFinalized(nextOutputIndex + 1), false); - + assertEq(optimismPortal.isOutputFinalized(nextOutputIndex + 1), false); // warp past the finalization period vm.warp(finalizationHorizon + 1); // It should now be finalized. - assertEq(op.isOutputFinalized(nextOutputIndex), true); + assertEq(optimismPortal.isOutputFinalized(nextOutputIndex), true); // But not the block after it. vm.expectRevert(stdError.indexOOBError); - assertEq(op.isOutputFinalized(nextOutputIndex + 1), false); + assertEq(optimismPortal.isOutputFinalized(nextOutputIndex + 1), false); } } -contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { +contract OptimismPortal_FinalizeWithdrawal_Test is CommonTest { // Reusable default values for a test withdrawal Types.WithdrawalTransaction _defaultTx; @@ -366,21 +351,24 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { messagePasserStorageRoot: _storageRoot, latestBlockhash: bytes32(uint256(0)) }); - _proposedBlockNumber = oracle.nextBlockNumber(); - _proposedOutputIndex = oracle.nextOutputIndex(); + _proposedBlockNumber = l2OutputOracle.nextBlockNumber(); + _proposedOutputIndex = l2OutputOracle.nextOutputIndex(); } /// @dev Setup the system for a ready-to-use state. function setUp() public override { // Configure the oracle to return the output root we've prepared. - vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1); - vm.prank(oracle.PROPOSER()); - oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0); + vm.warp(l2OutputOracle.computeL2Timestamp(_proposedBlockNumber) + 1); + vm.prank(l2OutputOracle.PROPOSER()); + l2OutputOracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0); // Warp beyond the finalization period for the block we've proposed. - vm.warp(oracle.getL2Output(_proposedOutputIndex).timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp( + l2OutputOracle.getL2Output(_proposedOutputIndex).timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + + 1 + ); // Fund the portal so that we can withdraw ETH. - vm.deal(address(op), 0xFFFFFFFF); + vm.deal(address(optimismPortal), 0xFFFFFFFF); } /// @dev Asserts that the reentrant call will revert. @@ -388,18 +376,18 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { vm.expectRevert("OptimismPortal: can only trigger one withdrawal per transaction"); // Arguments here don't matter, as the require check is the first thing that happens. // We assume that this has already been proven. - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); // Assert that the withdrawal was not finalized. - assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx))); + assertFalse(optimismPortal.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx))); } /// @dev Tests that `proveWithdrawalTransaction` reverts when paused. function test_proveWithdrawalTransaction_paused_reverts() external { - vm.prank(op.GUARDIAN()); - op.pause(); + vm.prank(optimismPortal.GUARDIAN()); + optimismPortal.pause(); vm.expectRevert("OptimismPortal: paused"); - op.proveWithdrawalTransaction({ + optimismPortal.proveWithdrawalTransaction({ _tx: _defaultTx, _l2OutputIndex: _proposedOutputIndex, _outputRootProof: _outputRootProof, @@ -409,9 +397,9 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { /// @dev Tests that `proveWithdrawalTransaction` reverts when the target is the portal contract. function test_proveWithdrawalTransaction_onSelfCall_reverts() external { - _defaultTx.target = address(op); + _defaultTx.target = address(optimismPortal); vm.expectRevert("OptimismPortal: you cannot send messages to the portal contract"); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); } /// @dev Tests that `proveWithdrawalTransaction` reverts when @@ -420,7 +408,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // Modify the version to invalidate the withdrawal proof. _outputRootProof.version = bytes32(uint256(1)); vm.expectRevert("OptimismPortal: invalid output root proof"); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); } /// @dev Tests that `proveWithdrawalTransaction` reverts when the withdrawal is missing. @@ -428,7 +416,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // modify the default test values to invalidate the proof. _defaultTx.data = hex"abcd"; vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key"); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); } /// @dev Tests that `proveWithdrawalTransaction` reverts when the withdrawal has already @@ -436,10 +424,10 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { function test_proveWithdrawalTransaction_replayProve_reverts() external { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); vm.expectRevert("OptimismPortal: withdrawal hash has already been proven"); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); } /// @dev Tests that `proveWithdrawalTransaction` succeeds when the withdrawal has already @@ -447,7 +435,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash` // inside of the `provenWithdrawal`s mapping. @@ -460,7 +448,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // Store a different output root within the `provenWithdrawals` mapping without // touching the l2BlockNumber or timestamp. - vm.store(address(op), slot, bytes32(0)); + vm.store(address(optimismPortal), slot, bytes32(0)); // Warp ahead 1 second vm.warp(block.timestamp + 1); @@ -469,10 +457,10 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // our proof with a changed outputRoot vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); // Ensure that the withdrawal was updated within the mapping - (, uint128 timestamp,) = op.provenWithdrawals(_withdrawalHash); + (, uint128 timestamp,) = optimismPortal.provenWithdrawals(_withdrawalHash); assertEq(timestamp, block.timestamp); } @@ -481,7 +469,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { function test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() external { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash` // inside of the `provenWithdrawal`s mapping. @@ -494,15 +482,15 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // Store a dummy output root within the `provenWithdrawals` mapping without touching the // l2BlockNumber or timestamp. - vm.store(address(op), slot, bytes32(0)); + vm.store(address(optimismPortal), slot, bytes32(0)); // Fetch the output proposal at `_proposedOutputIndex` from the L2OutputOracle - Types.OutputProposal memory proposal = op.L2_ORACLE().getL2Output(_proposedOutputIndex); + Types.OutputProposal memory proposal = optimismPortal.L2_ORACLE().getL2Output(_proposedOutputIndex); // Propose the same output root again, creating the same output at a different index + l2BlockNumber. - vm.startPrank(op.L2_ORACLE().PROPOSER()); - op.L2_ORACLE().proposeL2Output( - proposal.outputRoot, op.L2_ORACLE().nextBlockNumber(), blockhash(block.number), block.number + vm.startPrank(optimismPortal.L2_ORACLE().PROPOSER()); + optimismPortal.L2_ORACLE().proposeL2Output( + proposal.outputRoot, optimismPortal.L2_ORACLE().nextBlockNumber(), blockhash(block.number), block.number ); vm.stopPrank(); @@ -513,10 +501,12 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // our proof with a changed outputRoot + a different output index vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex + 1, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction( + _defaultTx, _proposedOutputIndex + 1, _outputRootProof, _withdrawalProof + ); // Ensure that the withdrawal was updated within the mapping - (, uint128 timestamp,) = op.provenWithdrawals(_withdrawalHash); + (, uint128 timestamp,) = optimismPortal.provenWithdrawals(_withdrawalHash); assertEq(timestamp, block.timestamp); } @@ -524,7 +514,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); } /// @dev Tests that `finalizeWithdrawalTransaction` succeeds. @@ -533,23 +523,23 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); vm.expectEmit(true, true, false, true); emit WithdrawalFinalized(_withdrawalHash, true); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); assert(address(bob).balance == bobBalanceBefore + 100); } /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the contract is paused. function test_finalizeWithdrawalTransaction_paused_reverts() external { - vm.prank(op.GUARDIAN()); - op.pause(); + vm.prank(optimismPortal.GUARDIAN()); + optimismPortal.pause(); vm.expectRevert("OptimismPortal: paused"); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); } /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has not been @@ -557,7 +547,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { uint256 bobBalanceBefore = address(bob).balance; vm.expectRevert("OptimismPortal: withdrawal has not been proven yet"); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); assert(address(bob).balance == bobBalanceBefore); } @@ -569,18 +559,18 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); // Mock a call where the resulting output root is anything but the original output root. In // this case we just use bytes32(uint256(1)). vm.mockCall( - address(op.L2_ORACLE()), + address(optimismPortal.L2_ORACLE()), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), abi.encode(bytes32(uint256(1)), _proposedBlockNumber) ); vm.expectRevert("OptimismPortal: proven withdrawal finalization period has not elapsed"); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); assert(address(bob).balance == bobBalanceBefore); } @@ -593,19 +583,21 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // Prove our withdrawal vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); // Warp to after the finalization period - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); // Mock a startingTimestamp change on the L2 Oracle vm.mockCall( - address(op.L2_ORACLE()), abi.encodeWithSignature("startingTimestamp()"), abi.encode(block.timestamp + 1) + address(optimismPortal.L2_ORACLE()), + abi.encodeWithSignature("startingTimestamp()"), + abi.encode(block.timestamp + 1) ); // Attempt to finalize the withdrawal vm.expectRevert("OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp"); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); // Ensure that bob's balance has remained the same assertEq(bobBalanceBefore, address(bob).balance); @@ -619,15 +611,15 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // Prove our withdrawal vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); // Warp to after the finalization period - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); // Mock an outputRoot change on the output proposal before attempting // to finalize the withdrawal. vm.mockCall( - address(op.L2_ORACLE()), + address(optimismPortal.L2_ORACLE()), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), abi.encode( Types.OutputProposal(bytes32(uint256(0)), uint128(block.timestamp), uint128(_proposedBlockNumber)) @@ -636,7 +628,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // Attempt to finalize the withdrawal vm.expectRevert("OptimismPortal: output root proven is not the same as current output root"); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); // Ensure that bob's balance has remained the same assertEq(bobBalanceBefore, address(bob).balance); @@ -650,22 +642,22 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // Prove our withdrawal vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); // Warp to after the finalization period - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); // Mock a timestamp change on the output proposal that has not passed the // finalization period. vm.mockCall( - address(op.L2_ORACLE()), + address(optimismPortal.L2_ORACLE()), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), abi.encode(Types.OutputProposal(_outputRoot, uint128(block.timestamp + 1), uint128(_proposedBlockNumber))) ); // Attempt to finalize the withdrawal vm.expectRevert("OptimismPortal: output proposal finalization period has not elapsed"); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); // Ensure that bob's balance has remained the same assertEq(bobBalanceBefore, address(bob).balance); @@ -678,12 +670,12 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); vm.expectEmit(true, true, true, true); emit WithdrawalFinalized(_withdrawalHash, false); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); assert(address(bob).balance == bobBalanceBefore); } @@ -692,17 +684,17 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { /// has not yet passed. function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external { // Setup the Oracle to return an output with a recent timestamp - uint256 recentTimestamp = block.timestamp - 1000; + uint256 recentTimestamp = block.timestamp - 1; vm.mockCall( - address(op.L2_ORACLE()), + address(optimismPortal.L2_ORACLE()), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), abi.encode(Types.OutputProposal(_outputRoot, uint128(recentTimestamp), uint128(_proposedBlockNumber))) ); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); vm.expectRevert("OptimismPortal: proven withdrawal finalization period has not elapsed"); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); } /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has already been @@ -710,15 +702,15 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { function test_finalizeWithdrawalTransaction_onReplay_reverts() external { vm.expectEmit(true, true, true, true); emit WithdrawalProven(_withdrawalHash, alice, bob); - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); vm.expectEmit(true, true, true, true); emit WithdrawalFinalized(_withdrawalHash, true); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); vm.expectRevert("OptimismPortal: withdrawal has already been finalized"); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); } /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal transaction @@ -746,7 +738,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { }); vm.mockCall( - address(op.L2_ORACLE()), + address(optimismPortal.L2_ORACLE()), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), abi.encode( Types.OutputProposal( @@ -757,11 +749,13 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ) ); - op.proveWithdrawalTransaction(insufficientGasTx, _proposedOutputIndex, outputRootProof, withdrawalProof); + optimismPortal.proveWithdrawalTransaction( + insufficientGasTx, _proposedOutputIndex, outputRootProof, withdrawalProof + ); - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); vm.expectRevert("SafeCall: Not enough gas"); - op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx); + optimismPortal.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx); } /// @dev Tests that `finalizeWithdrawalTransaction` reverts if a sub-call attempts to finalize @@ -791,22 +785,22 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { }); // Setup the Oracle to return the outputRoot we want as well as a finalized timestamp. - uint256 finalizedTimestamp = block.timestamp - oracle.FINALIZATION_PERIOD_SECONDS() - 1; + uint256 finalizedTimestamp = block.timestamp - l2OutputOracle.FINALIZATION_PERIOD_SECONDS() - 1; vm.mockCall( - address(op.L2_ORACLE()), + address(optimismPortal.L2_ORACLE()), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), abi.encode(Types.OutputProposal(outputRoot, uint128(finalizedTimestamp), uint128(_proposedBlockNumber))) ); vm.expectEmit(true, true, true, true); emit WithdrawalProven(withdrawalHash, alice, address(this)); - op.proveWithdrawalTransaction(_testTx, _proposedBlockNumber, outputRootProof, withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_testTx, _proposedBlockNumber, outputRootProof, withdrawalProof); - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); vm.expectCall(address(this), _testTx.data); vm.expectEmit(true, true, true, true); emit WithdrawalFinalized(withdrawalHash, true); - op.finalizeWithdrawalTransaction(_testTx); + optimismPortal.finalizeWithdrawalTransaction(_testTx); // Ensure that bob's balance was not changed by the reentrant call. assert(address(bob).balance == bobBalanceBefore); @@ -823,7 +817,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { external { vm.assume( - _target != address(op) // Cannot call the optimism portal or a contract + _target != address(optimismPortal) // Cannot call the optimism portal or a contract && _target.code.length == 0 // No accounts with code && _target != CONSOLE // The console has no code but behaves like a contract && uint160(_target) > 9 // No precompiles (or zero address) @@ -831,10 +825,10 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // Total ETH supply is currently about 120M ETH. uint256 value = bound(_value, 0, 200_000_000 ether); - vm.deal(address(op), value); + vm.deal(address(optimismPortal), value); uint256 gasLimit = bound(_gasLimit, 0, 50_000_000); - uint256 nonce = messagePasser.messageNonce(); + uint256 nonce = l2ToL1MessagePasser.messageNonce(); // Get a withdrawal transaction and mock proof from the differential testing script. Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({ @@ -867,58 +861,46 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { // Setup the Oracle to return the outputRoot vm.mockCall( - address(oracle), - abi.encodeWithSelector(oracle.getL2Output.selector), + address(l2OutputOracle), + abi.encodeWithSelector(l2OutputOracle.getL2Output.selector), abi.encode(outputRoot, block.timestamp, 100) ); // Prove the withdrawal transaction - op.proveWithdrawalTransaction( + optimismPortal.proveWithdrawalTransaction( _tx, 100, // l2BlockNumber proof, withdrawalProof ); - (bytes32 _root,,) = op.provenWithdrawals(withdrawalHash); + (bytes32 _root,,) = optimismPortal.provenWithdrawals(withdrawalHash); assertTrue(_root != bytes32(0)); // Warp past the finalization period - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); // Finalize the withdrawal transaction vm.expectCallMinGas(_tx.target, _tx.value, uint64(_tx.gasLimit), _tx.data); - op.finalizeWithdrawalTransaction(_tx); - assertTrue(op.finalizedWithdrawals(withdrawalHash)); + optimismPortal.finalizeWithdrawalTransaction(_tx); + assertTrue(optimismPortal.finalizedWithdrawals(withdrawalHash)); } } -contract OptimismPortalUpgradeable_Test is Portal_Initializer { - Proxy internal proxy; - uint64 initialBlockNum; - - /// @dev Sets up the test. - function setUp() public override { - super.setUp(); - initialBlockNum = uint64(block.number); - proxy = Proxy(payable(address(op))); - } - +contract OptimismPortalUpgradeable_Test is CommonTest { /// @dev Tests that the proxy is initialized correctly. function test_params_initValuesOnProxy_succeeds() external { - OptimismPortal p = OptimismPortal(payable(address(proxy))); - - (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = p.params(); - + (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = optimismPortal.params(); ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); + assertEq(prevBaseFee, rcfg.minimumBaseFee); assertEq(prevBoughtGas, 0); - assertEq(prevBlockNum, initialBlockNum); + assertEq(prevBlockNum, block.number); } /// @dev Tests that the proxy cannot be initialized twice. function test_initialize_cannotInitProxy_reverts() external { vm.expectRevert("Initializable: contract is already initialized"); - OptimismPortal(payable(proxy)).initialize({ + optimismPortal.initialize({ _l2Oracle: L2OutputOracle(address(0)), _systemConfig: SystemConfig(address(0)), _guardian: address(0), @@ -928,8 +910,9 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { /// @dev Tests that the implementation cannot be initialized twice. function test_initialize_cannotInitImpl_reverts() external { + address opImpl = mustGetAddress("OptimismPortal"); vm.expectRevert("Initializable: contract is already initialized"); - OptimismPortal(opImpl).initialize({ + OptimismPortal(payable(opImpl)).initialize({ _l2Oracle: L2OutputOracle(address(0)), _systemConfig: SystemConfig(address(0)), _guardian: address(0), @@ -940,21 +923,22 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { /// @dev Tests that the proxy can be upgraded. function test_upgradeToAndCall_upgrading_succeeds() external { // Check an unused slot before upgrading. - bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21))); + bytes32 slot21Before = vm.load(address(optimismPortal), bytes32(uint256(21))); assertEq(bytes32(0), slot21Before); NextImpl nextImpl = new NextImpl(); - vm.startPrank(multisig); + + vm.startPrank(EIP1967Helper.getAdmin(address(optimismPortal))); // The value passed to the initialize must be larger than the last value // that initialize was called with. - proxy.upgradeToAndCall( + Proxy(payable(address(optimismPortal))).upgradeToAndCall( address(nextImpl), abi.encodeWithSelector(NextImpl.initialize.selector, Constants.INITIALIZER + 1) ); - assertEq(proxy.implementation(), address(nextImpl)); + assertEq(Proxy(payable(address(optimismPortal))).implementation(), address(nextImpl)); // Verify that the NextImpl contract initialized its values according as expected - bytes32 slot21After = vm.load(address(op), bytes32(uint256(21))); - bytes32 slot21Expected = NextImpl(address(op)).slot21Init(); + bytes32 slot21After = vm.load(address(optimismPortal), bytes32(uint256(21))); + bytes32 slot21Expected = NextImpl(address(optimismPortal)).slot21Init(); assertEq(slot21Expected, slot21After); } } @@ -962,7 +946,7 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { /// @title OptimismPortalResourceFuzz_Test /// @dev Test various values of the resource metering config to ensure that deposits cannot be /// broken by changing the config. -contract OptimismPortalResourceFuzz_Test is Portal_Initializer { +contract OptimismPortalResourceFuzz_Test is CommonTest { /// @dev The max gas limit observed throughout this test. Setting this too high can cause /// the test to take too long to run. uint256 constant MAX_GAS_LIMIT = 30_000_000; @@ -1016,18 +1000,18 @@ contract OptimismPortalResourceFuzz_Test is Portal_Initializer { // Set the resource params uint256 _prevBlockNum = block.number - _blockDiff; vm.store( - address(op), + address(optimismPortal), bytes32(uint256(1)), bytes32((_prevBlockNum << 192) | (uint256(_prevBoughtGas) << 128) | _prevBaseFee) ); // Ensure that the storage setting is correct - (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = op.params(); + (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = optimismPortal.params(); assertEq(prevBaseFee, _prevBaseFee); assertEq(prevBoughtGas, _prevBoughtGas); assertEq(prevBlockNum, _prevBlockNum); // Do a deposit, should not revert - op.depositTransaction{ gas: MAX_GAS_LIMIT }({ + optimismPortal.depositTransaction{ gas: MAX_GAS_LIMIT }({ _to: address(0x20), _value: 0x40, _gasLimit: _gasLimit, diff --git a/packages/contracts-bedrock/test/Optimist.t.sol b/packages/contracts-bedrock/test/Optimist.t.sol index 0d757e6d0b09..49db8326a11d 100644 --- a/packages/contracts-bedrock/test/Optimist.t.sol +++ b/packages/contracts-bedrock/test/Optimist.t.sol @@ -7,7 +7,7 @@ import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol" import { Optimist } from "src/periphery/op-nft/Optimist.sol"; import { OptimistAllowlist } from "src/periphery/op-nft/OptimistAllowlist.sol"; import { OptimistInviter } from "src/periphery/op-nft/OptimistInviter.sol"; -import { OptimistInviterHelper } from "test/Helpers.sol"; +import { OptimistInviterHelper } from "test/mocks/OptimistInviterHelper.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; diff --git a/packages/contracts-bedrock/test/OptimistAllowlist.t.sol b/packages/contracts-bedrock/test/OptimistAllowlist.t.sol index d7f53ff8c23c..4855802489c3 100644 --- a/packages/contracts-bedrock/test/OptimistAllowlist.t.sol +++ b/packages/contracts-bedrock/test/OptimistAllowlist.t.sol @@ -6,7 +6,7 @@ import { Test } from "forge-std/Test.sol"; import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; import { OptimistAllowlist } from "src/periphery/op-nft/OptimistAllowlist.sol"; import { OptimistInviter } from "src/periphery/op-nft/OptimistInviter.sol"; -import { OptimistInviterHelper } from "test/Helpers.sol"; +import { OptimistInviterHelper } from "test/mocks/OptimistInviterHelper.sol"; import { OptimistConstants } from "src/periphery/op-nft/libraries/OptimistConstants.sol"; contract OptimistAllowlist_Initializer is Test { diff --git a/packages/contracts-bedrock/test/OptimistInviter.t.sol b/packages/contracts-bedrock/test/OptimistInviter.t.sol index 677dceb7d151..53d24105d122 100644 --- a/packages/contracts-bedrock/test/OptimistInviter.t.sol +++ b/packages/contracts-bedrock/test/OptimistInviter.t.sol @@ -7,8 +7,8 @@ import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol" import { OptimistInviter } from "src/periphery/op-nft/OptimistInviter.sol"; import { Optimist } from "src/periphery/op-nft/Optimist.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; -import { TestERC1271Wallet } from "test/Helpers.sol"; -import { OptimistInviterHelper } from "test/Helpers.sol"; +import { TestERC1271Wallet } from "test/mocks/TestERC1271Wallet.sol"; +import { OptimistInviterHelper } from "test/mocks/OptimistInviterHelper.sol"; import { OptimistConstants } from "src/periphery/op-nft/libraries/OptimistConstants.sol"; contract OptimistInviter_Initializer is Test { diff --git a/packages/contracts-bedrock/test/ProtocolVersions.t.sol b/packages/contracts-bedrock/test/ProtocolVersions.t.sol index 814c36ec9639..c8201495e7a9 100644 --- a/packages/contracts-bedrock/test/ProtocolVersions.t.sol +++ b/packages/contracts-bedrock/test/ProtocolVersions.t.sol @@ -2,7 +2,8 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Libraries import { Constants } from "src/libraries/Constants.sol"; @@ -14,44 +15,27 @@ import { Proxy } from "src/universal/Proxy.sol"; import { ProtocolVersions, ProtocolVersion } from "src/L1/ProtocolVersions.sol"; contract ProtocolVersions_Init is CommonTest { - ProtocolVersions protocolVersions; - ProtocolVersions protocolVersionsImpl; - event ConfigUpdate(uint256 indexed version, ProtocolVersions.UpdateType indexed updateType, bytes data); - // Dummy values used to test getters - ProtocolVersion constant required = ProtocolVersion.wrap(0xabcd); - ProtocolVersion constant recommended = ProtocolVersion.wrap(0x1234); + ProtocolVersion required; + ProtocolVersion recommended; function setUp() public virtual override { super.setUp(); - - Proxy proxy = new Proxy(multisig); - protocolVersionsImpl = new ProtocolVersions(); - - vm.prank(multisig); - proxy.upgradeToAndCall( - address(protocolVersionsImpl), - abi.encodeCall( - ProtocolVersions.initialize, - ( - alice, // _owner, - required, - recommended - ) - ) - ); - - protocolVersions = ProtocolVersions(address(proxy)); + required = ProtocolVersion.wrap(cfg.requiredProtocolVersion()); + recommended = ProtocolVersion.wrap(cfg.recommendedProtocolVersion()); } } contract ProtocolVersions_Initialize_Test is ProtocolVersions_Init { /// @dev Tests that initialization sets the correct values. function test_initialize_values_succeeds() external { + ProtocolVersions protocolVersionsImpl = ProtocolVersions(mustGetAddress("ProtocolVersions")); + address owner = cfg.finalSystemOwner(); + assertEq(ProtocolVersion.unwrap(protocolVersions.required()), ProtocolVersion.unwrap(required)); assertEq(ProtocolVersion.unwrap(protocolVersions.recommended()), ProtocolVersion.unwrap(recommended)); - assertEq(protocolVersions.owner(), alice); + assertEq(protocolVersions.owner(), owner); assertEq(ProtocolVersion.unwrap(protocolVersionsImpl.required()), 0); assertEq(ProtocolVersion.unwrap(protocolVersionsImpl.recommended()), 0); @@ -60,6 +44,7 @@ contract ProtocolVersions_Initialize_Test is ProtocolVersions_Init { /// @dev Ensures that the events are emitted during initialization. function test_initialize_events_succeeds() external { + ProtocolVersions protocolVersionsImpl = ProtocolVersions(mustGetAddress("ProtocolVersions")); assertEq(protocolVersionsImpl.owner(), address(0xdEad)); // Wipe out the initialized slot so the proxy can be initialized again @@ -71,7 +56,7 @@ contract ProtocolVersions_Initialize_Test is ProtocolVersions_Init { vm.expectEmit(true, true, true, true, address(protocolVersions)); emit ConfigUpdate(0, ProtocolVersions.UpdateType.RECOMMENDED_PROTOCOL_VERSION, abi.encode(recommended)); - vm.prank(multisig); + vm.prank(EIP1967Helper.getAdmin(address(protocolVersions))); Proxy(payable(address(protocolVersions))).upgradeToAndCall( address(protocolVersionsImpl), abi.encodeCall( diff --git a/packages/contracts-bedrock/test/RLPReader.t.sol b/packages/contracts-bedrock/test/RLPReader.t.sol index 17fe69c817c0..7d4cf189fbe9 100644 --- a/packages/contracts-bedrock/test/RLPReader.t.sol +++ b/packages/contracts-bedrock/test/RLPReader.t.sol @@ -2,10 +2,10 @@ pragma solidity 0.8.15; import { stdError } from "forge-std/Test.sol"; -import { CommonTest } from "test/CommonTest.t.sol"; +import { Test } from "forge-std/Test.sol"; import { RLPReader } from "src/libraries/rlp/RLPReader.sol"; -contract RLPReader_readBytes_Test is CommonTest { +contract RLPReader_readBytes_Test is Test { function test_readBytes_bytestring00_succeeds() external { assertEq(RLPReader.readBytes(hex"00"), hex"00"); } @@ -44,7 +44,7 @@ contract RLPReader_readBytes_Test is CommonTest { } } -contract RLPReader_readList_Test is CommonTest { +contract RLPReader_readList_Test is Test { function test_readList_empty_succeeds() external { RLPReader.RLPItem[] memory list = RLPReader.readList(hex"c0"); assertEq(list.length, 0); diff --git a/packages/contracts-bedrock/test/RLPWriter.t.sol b/packages/contracts-bedrock/test/RLPWriter.t.sol index b1735578ad44..86faffd05fc5 100644 --- a/packages/contracts-bedrock/test/RLPWriter.t.sol +++ b/packages/contracts-bedrock/test/RLPWriter.t.sol @@ -2,9 +2,9 @@ pragma solidity 0.8.15; import { RLPWriter } from "src/libraries/rlp/RLPWriter.sol"; -import { CommonTest } from "test/CommonTest.t.sol"; +import { Test } from "forge-std/Test.sol"; -contract RLPWriter_writeString_Test is CommonTest { +contract RLPWriter_writeString_Test is Test { function test_writeString_empty_succeeds() external { assertEq(RLPWriter.writeString(""), hex"80"); } @@ -49,7 +49,7 @@ contract RLPWriter_writeString_Test is CommonTest { } } -contract RLPWriter_writeUint_Test is CommonTest { +contract RLPWriter_writeUint_Test is Test { function test_writeUint_zero_succeeds() external { assertEq(RLPWriter.writeUint(0x0), hex"80"); } @@ -83,7 +83,7 @@ contract RLPWriter_writeUint_Test is CommonTest { } } -contract RLPWriter_writeList_Test is CommonTest { +contract RLPWriter_writeList_Test is Test { function test_writeList_empty_succeeds() external { assertEq(RLPWriter.writeList(new bytes[](0)), hex"c0"); } diff --git a/packages/contracts-bedrock/test/SafeCall.t.sol b/packages/contracts-bedrock/test/SafeCall.t.sol index 550e7dd982b4..36690e4de376 100644 --- a/packages/contracts-bedrock/test/SafeCall.t.sol +++ b/packages/contracts-bedrock/test/SafeCall.t.sol @@ -2,12 +2,12 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; +import { Test } from "forge-std/Test.sol"; // Target contract import { SafeCall } from "src/libraries/SafeCall.sol"; -contract SafeCall_Test is CommonTest { +contract SafeCall_Test is Test { /// @dev Tests that the `send` function succeeds. function testFuzz_send_succeeds(address from, address to, uint256 gas, uint64 value) external { vm.assume(from.balance == 0); @@ -21,8 +21,7 @@ contract SafeCall_Test is CommonTest { vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67)); // don't call the create2 deployer vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C)); - // don't call the ffi interface - vm.assume(to != address(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f)); + vm.assume(to != address(this)); assertEq(from.balance, 0, "from balance is 0"); vm.deal(from, value); @@ -56,8 +55,7 @@ contract SafeCall_Test is CommonTest { vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67)); // don't call the create2 deployer vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C)); - // don't call the ffi interface - vm.assume(to != address(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f)); + vm.assume(to != address(this)); assertEq(from.balance, 0, "from balance is 0"); vm.deal(from, value); @@ -99,8 +97,7 @@ contract SafeCall_Test is CommonTest { vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67)); // don't call the create2 deployer vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C)); - // don't call the FFIInterface - vm.assume(to != address(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f)); + vm.assume(to != address(this)); assertEq(from.balance, 0, "from balance is 0"); vm.deal(from, value); diff --git a/packages/contracts-bedrock/test/SafeSigners.t.sol b/packages/contracts-bedrock/test/SafeSigners.t.sol index b79386a52238..d94d91382fa3 100644 --- a/packages/contracts-bedrock/test/SafeSigners.t.sol +++ b/packages/contracts-bedrock/test/SafeSigners.t.sol @@ -40,7 +40,7 @@ contract SafeSigners_Test is Test, SafeTestTools { uint256 numSigs = bound(_numSigs, 1, 25); (, uint256[] memory keys) = SafeTestLib.makeAddrsAndKeys("getSigsTest", numSigs); - for (uint256 i = 0; i < keys.length; i++) { + for (uint256 i; i < keys.length; i++) { if (sigType(keys[i]) == SigTypes.Contract) { keys[i] = SafeTestLib.encodeSmartContractWalletAsPK(SafeTestLib.decodeSmartContractWalletAsAddress(keys[i])); @@ -91,7 +91,7 @@ contract SafeSigners_Test is Test, SafeTestTools { // the validation checks that the Safe contract performs on the value of s on contract // signatures. The Safe contract checks that s correctly points to additional data appended // after the signatures, and that the length of the data is within bounds. - for (uint256 i = 0; i < contractSigs; i++) { + for (uint256 i; i < contractSigs; i++) { signatures = bytes.concat(signatures, abi.encode(32, 1)); } diff --git a/packages/contracts-bedrock/test/Semver.t.sol b/packages/contracts-bedrock/test/Semver.t.sol deleted file mode 100644 index 08d0dae64f06..000000000000 --- a/packages/contracts-bedrock/test/Semver.t.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import { CommonTest } from "test/CommonTest.t.sol"; -import { Semver } from "src/universal/Semver.sol"; -import { Proxy } from "src/universal/Proxy.sol"; - -/// @notice Test the Semver contract that is used for semantic versioning -/// of various contracts. -contract Semver_Test is CommonTest { - /// @notice Global semver contract deployed in setUp. This is used in - /// the test cases. - Semver semver; - - /// @notice Deploy a Semver contract - function setUp() public virtual override { - semver = new Semver(7, 8, 0); - } - - /// @notice Test the version getter - function test_version_succeeds() external { - assertEq(semver.version(), "7.8.0"); - } - - /// @notice Since the versions are all immutable, they should - /// be able to be accessed from behind a proxy without needing - /// to initialize the contract. - function test_behindProxy_succeeds() external { - Proxy proxy = new Proxy(alice); - vm.prank(alice); - proxy.upgradeTo(address(semver)); - - assertEq(Semver(address(proxy)).version(), "7.8.0"); - } -} diff --git a/packages/contracts-bedrock/test/SequencerFeeVault.t.sol b/packages/contracts-bedrock/test/SequencerFeeVault.t.sol index 9c6b391a9194..b7836de638df 100644 --- a/packages/contracts-bedrock/test/SequencerFeeVault.t.sol +++ b/packages/contracts-bedrock/test/SequencerFeeVault.t.sol @@ -2,7 +2,8 @@ pragma solidity 0.8.15; // Testing utilities -import { FeeVault_Initializer, Reverter } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; +import { Reverter } from "test/mocks/Callers.sol"; import { StandardBridge } from "src/universal/StandardBridge.sol"; // Libraries @@ -14,127 +15,143 @@ import { FeeVault } from "src/universal/FeeVault.sol"; // Target contract import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol"; -contract SequencerFeeVault_Test is FeeVault_Initializer { +contract SequencerFeeVault_Test is CommonTest { + address recipient; /// @dev Sets up the test suite. + function setUp() public override { super.setUp(); - vm.etch( - Predeploys.SEQUENCER_FEE_WALLET, - address(new SequencerFeeVault(recipient, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L1)).code - ); - vm.label(Predeploys.SEQUENCER_FEE_WALLET, "SequencerFeeVault"); + recipient = cfg.sequencerFeeVaultRecipient(); } /// @dev Tests that the minimum withdrawal amount is correct. function test_minWithdrawalAmount_succeeds() external { - assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), NON_ZERO_VALUE); + assertEq(sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT(), cfg.sequencerFeeVaultMinimumWithdrawalAmount()); } /// @dev Tests that the l1 fee wallet is correct. function test_constructor_succeeds() external { - assertEq(vault.l1FeeWallet(), recipient); + assertEq(sequencerFeeVault.l1FeeWallet(), recipient); } /// @dev Tests that the fee vault is able to receive ETH. function test_receive_succeeds() external { - uint256 balance = address(vault).balance; + uint256 balance = address(sequencerFeeVault).balance; vm.prank(alice); - (bool success,) = address(vault).call{ value: 100 }(hex""); + (bool success,) = address(sequencerFeeVault).call{ value: 100 }(hex""); assertEq(success, true); - assertEq(address(vault).balance, balance + 100); + assertEq(address(sequencerFeeVault).balance, balance + 100); } /// @dev Tests that `withdraw` reverts if the balance is less than the minimum /// withdrawal amount. function test_withdraw_notEnough_reverts() external { - assert(address(vault).balance < vault.MIN_WITHDRAWAL_AMOUNT()); + assert(address(sequencerFeeVault).balance < sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT()); vm.expectRevert("FeeVault: withdrawal amount must be greater than minimum withdrawal amount"); - vault.withdraw(); + sequencerFeeVault.withdraw(); } /// @dev Tests that `withdraw` successfully initiates a withdrawal to L1. function test_withdraw_toL1_succeeds() external { - uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1; - vm.deal(address(vault), amount); + // Set the code with the withdrawal network set to L1 + vm.etch( + Predeploys.SEQUENCER_FEE_WALLET, + address( + new SequencerFeeVault(cfg.sequencerFeeVaultRecipient(), cfg.sequencerFeeVaultMinimumWithdrawalAmount(), FeeVault.WithdrawalNetwork.L1) + ).code + ); + + uint256 amount = sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT() + 1; + vm.deal(address(sequencerFeeVault), amount); // No ether has been withdrawn yet - assertEq(vault.totalProcessed(), 0); + assertEq(sequencerFeeVault.totalProcessed(), 0); vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET)); - emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this)); + emit Withdrawal(address(sequencerFeeVault).balance, sequencerFeeVault.RECIPIENT(), address(this)); vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET)); - emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this), FeeVault.WithdrawalNetwork.L1); + emit Withdrawal( + address(sequencerFeeVault).balance, + sequencerFeeVault.RECIPIENT(), + address(this), + FeeVault.WithdrawalNetwork.L1 + ); // The entire vault's balance is withdrawn vm.expectCall( Predeploys.L2_STANDARD_BRIDGE, - address(vault).balance, - abi.encodeWithSelector(StandardBridge.bridgeETHTo.selector, vault.l1FeeWallet(), 35_000, bytes("")) + address(sequencerFeeVault).balance, + abi.encodeWithSelector( + StandardBridge.bridgeETHTo.selector, sequencerFeeVault.l1FeeWallet(), 35_000, bytes("") + ) ); - vault.withdraw(); + sequencerFeeVault.withdraw(); // The withdrawal was successful - assertEq(vault.totalProcessed(), amount); - assertEq(address(vault).balance, ZERO_VALUE); + assertEq(sequencerFeeVault.totalProcessed(), amount); + assertEq(address(sequencerFeeVault).balance, 0); assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, amount); } } -contract SequencerFeeVault_L2Withdrawal_Test is FeeVault_Initializer { +contract SequencerFeeVault_L2Withdrawal_Test is CommonTest { + address recipient; /// @dev Sets up the test suite. + function setUp() public override { super.setUp(); - vm.etch( - Predeploys.SEQUENCER_FEE_WALLET, - address(new SequencerFeeVault(recipient, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L2)).code - ); - vm.label(Predeploys.SEQUENCER_FEE_WALLET, "SequencerFeeVault"); + recipient = cfg.sequencerFeeVaultRecipient(); } /// @dev Tests that `withdraw` successfully initiates a withdrawal to L2. function test_withdraw_toL2_succeeds() external { - uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1; - vm.deal(address(vault), amount); + uint256 amount = sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT() + 1; + vm.deal(address(sequencerFeeVault), amount); // No ether has been withdrawn yet - assertEq(vault.totalProcessed(), 0); + assertEq(sequencerFeeVault.totalProcessed(), 0); vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET)); - emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this)); + emit Withdrawal(address(sequencerFeeVault).balance, sequencerFeeVault.RECIPIENT(), address(this)); vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET)); - emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this), FeeVault.WithdrawalNetwork.L2); + emit Withdrawal( + address(sequencerFeeVault).balance, + sequencerFeeVault.RECIPIENT(), + address(this), + FeeVault.WithdrawalNetwork.L2 + ); // The entire vault's balance is withdrawn - vm.expectCall(recipient, address(vault).balance, bytes("")); + vm.expectCall(recipient, address(sequencerFeeVault).balance, bytes("")); - vault.withdraw(); + sequencerFeeVault.withdraw(); // The withdrawal was successful - assertEq(vault.totalProcessed(), amount); - assertEq(address(vault).balance, ZERO_VALUE); + assertEq(sequencerFeeVault.totalProcessed(), amount); + assertEq(address(sequencerFeeVault).balance, 0); assertEq(recipient.balance, amount); } /// @dev Tests that `withdraw` fails if the Recipient reverts. This also serves to simulate /// a situation where insufficient gas is provided to the RECIPIENT. function test_withdraw_toL2recipientReverts_fails() external { - uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT(); + uint256 amount = sequencerFeeVault.MIN_WITHDRAWAL_AMOUNT(); - vm.deal(address(vault), amount); + vm.deal(address(sequencerFeeVault), amount); // No ether has been withdrawn yet - assertEq(vault.totalProcessed(), 0); + assertEq(sequencerFeeVault.totalProcessed(), 0); // Ensure the RECIPIENT reverts - vm.etch(vault.RECIPIENT(), type(Reverter).runtimeCode); + vm.etch(sequencerFeeVault.RECIPIENT(), type(Reverter).runtimeCode); // The entire vault's balance is withdrawn - vm.expectCall(recipient, address(vault).balance, bytes("")); + vm.expectCall(recipient, address(sequencerFeeVault).balance, bytes("")); vm.expectRevert("FeeVault: failed to send ETH to L2 fee recipient"); - vault.withdraw(); - assertEq(vault.totalProcessed(), 0); + sequencerFeeVault.withdraw(); + assertEq(sequencerFeeVault.totalProcessed(), 0); } } diff --git a/packages/contracts-bedrock/test/StandardBridge.t.sol b/packages/contracts-bedrock/test/StandardBridge.t.sol index 000d2334ae34..0f437fead82f 100644 --- a/packages/contracts-bedrock/test/StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/StandardBridge.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; import { StandardBridge } from "src/universal/StandardBridge.sol"; -import { CommonTest } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; import { OptimismMintableERC20, ILegacyMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; diff --git a/packages/contracts-bedrock/test/SystemConfig.t.sol b/packages/contracts-bedrock/test/SystemConfig.t.sol index b6cb18cf7d7c..0b09b768c686 100644 --- a/packages/contracts-bedrock/test/SystemConfig.t.sol +++ b/packages/contracts-bedrock/test/SystemConfig.t.sol @@ -2,10 +2,11 @@ pragma solidity 0.8.15; // Testing utilities -import { CommonTest } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { Constants } from "src/libraries/Constants.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Target contract dependencies import { ResourceMetering } from "src/L1/ResourceMetering.sol"; @@ -15,89 +16,59 @@ import { Proxy } from "src/universal/Proxy.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; contract SystemConfig_Init is CommonTest { - SystemConfig sysConf; - SystemConfig systemConfigImpl; - event ConfigUpdate(uint256 indexed version, SystemConfig.UpdateType indexed updateType, bytes data); +} - // Dummy addresses used to test getters - address constant batchInbox = address(0x18); - address constant l1CrossDomainMessenger = address(0x20); - address constant l1ERC721Bridge = address(0x21); - address constant l1StandardBridge = address(0x22); - address constant l2OutputOracle = address(0x23); - address constant optimismPortal = address(0x24); - address constant optimismMintableERC20Factory = address(0x25); - uint256 constant overhead = 2100; - uint256 constant scalar = 1000000; - bytes32 constant batcherHash = bytes32(hex"abcd"); - uint64 constant gasLimit = 30_000_000; - address constant unsafeBlockSigner = address(1); +contract SystemConfig_Initialize_Test is SystemConfig_Init { + address batchInbox; + address owner; + uint256 overhead; + uint256 scalar; + bytes32 batcherHash; + uint64 gasLimit; + address unsafeBlockSigner; + address systemConfigImpl; + address optimismMintableERC20Factory; function setUp() public virtual override { super.setUp(); - - Proxy proxy = new Proxy(multisig); - systemConfigImpl = new SystemConfig(); - - vm.prank(multisig); - proxy.upgradeToAndCall( - address(systemConfigImpl), - abi.encodeCall( - SystemConfig.initialize, - ( - alice, // _owner, - overhead, // _overhead, - scalar, // _scalar, - batcherHash, // _batcherHash - gasLimit, // _gasLimit, - unsafeBlockSigner, // _unsafeBlockSigner, - Constants.DEFAULT_RESOURCE_CONFIG(), // _config, - 0, // _startBlock - batchInbox, // _batchInbox - SystemConfig.Addresses({ // _addresses - l1CrossDomainMessenger: l1CrossDomainMessenger, - l1ERC721Bridge: l1ERC721Bridge, - l1StandardBridge: l1StandardBridge, - l2OutputOracle: l2OutputOracle, - optimismPortal: optimismPortal, - optimismMintableERC20Factory: optimismMintableERC20Factory - }) - ) - ) - ); - - sysConf = SystemConfig(address(proxy)); + batchInbox = cfg.batchInboxAddress(); + owner = cfg.finalSystemOwner(); + overhead = cfg.gasPriceOracleOverhead(); + scalar = cfg.gasPriceOracleScalar(); + batcherHash = bytes32(uint256(uint160(cfg.batchSenderAddress()))); + gasLimit = uint64(cfg.l2GenesisBlockGasLimit()); + unsafeBlockSigner = cfg.p2pSequencerAddress(); + systemConfigImpl = mustGetAddress("SystemConfig"); + optimismMintableERC20Factory = mustGetAddress("OptimismMintableERC20FactoryProxy"); } -} -contract SystemConfig_Initialize_Test is SystemConfig_Init { /// @dev Tests that initailization sets the correct values. function test_initialize_values_succeeds() external { - assertEq(sysConf.l1CrossDomainMessenger(), l1CrossDomainMessenger); - assertEq(sysConf.l1ERC721Bridge(), l1ERC721Bridge); - assertEq(sysConf.l1StandardBridge(), l1StandardBridge); - assertEq(sysConf.l2OutputOracle(), l2OutputOracle); - assertEq(sysConf.optimismPortal(), optimismPortal); - assertEq(sysConf.optimismMintableERC20Factory(), optimismMintableERC20Factory); - assertEq(sysConf.batchInbox(), batchInbox); - assertEq(sysConf.owner(), alice); - assertEq(sysConf.overhead(), overhead); - assertEq(sysConf.scalar(), scalar); - assertEq(sysConf.batcherHash(), batcherHash); - assertEq(sysConf.gasLimit(), gasLimit); - assertEq(sysConf.unsafeBlockSigner(), unsafeBlockSigner); + assertEq(systemConfig.l1CrossDomainMessenger(), address(l1CrossDomainMessenger)); + assertEq(systemConfig.l1ERC721Bridge(), address(l1ERC721Bridge)); + assertEq(systemConfig.l1StandardBridge(), address(l1StandardBridge)); + assertEq(systemConfig.l2OutputOracle(), address(l2OutputOracle)); + assertEq(systemConfig.optimismPortal(), address(optimismPortal)); + assertEq(systemConfig.optimismMintableERC20Factory(), optimismMintableERC20Factory); + assertEq(systemConfig.batchInbox(), batchInbox); + assertEq(systemConfig.owner(), owner); + assertEq(systemConfig.overhead(), overhead); + assertEq(systemConfig.scalar(), scalar); + assertEq(systemConfig.batcherHash(), batcherHash); + assertEq(systemConfig.gasLimit(), gasLimit); + assertEq(systemConfig.unsafeBlockSigner(), unsafeBlockSigner); // Depends on start block being set to 0 in `initialize` - assertEq(sysConf.startBlock(), block.number); + assertEq(systemConfig.startBlock(), block.number); // Depends on `initialize` being called with defaults - ResourceMetering.ResourceConfig memory cfg = Constants.DEFAULT_RESOURCE_CONFIG(); - ResourceMetering.ResourceConfig memory actual = sysConf.resourceConfig(); - assertEq(actual.maxResourceLimit, cfg.maxResourceLimit); - assertEq(actual.elasticityMultiplier, cfg.elasticityMultiplier); - assertEq(actual.baseFeeMaxChangeDenominator, cfg.baseFeeMaxChangeDenominator); - assertEq(actual.minimumBaseFee, cfg.minimumBaseFee); - assertEq(actual.systemTxMaxGas, cfg.systemTxMaxGas); - assertEq(actual.maximumBaseFee, cfg.maximumBaseFee); + ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); + ResourceMetering.ResourceConfig memory actual = systemConfig.resourceConfig(); + assertEq(actual.maxResourceLimit, rcfg.maxResourceLimit); + assertEq(actual.elasticityMultiplier, rcfg.elasticityMultiplier); + assertEq(actual.baseFeeMaxChangeDenominator, rcfg.baseFeeMaxChangeDenominator); + assertEq(actual.minimumBaseFee, rcfg.minimumBaseFee); + assertEq(actual.systemTxMaxGas, rcfg.systemTxMaxGas); + assertEq(actual.maximumBaseFee, rcfg.maximumBaseFee); } /// @dev Ensures that the start block override can be used to set the start block. @@ -105,15 +76,17 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { uint256 startBlock = 100; // Wipe out the initialized slot so the proxy can be initialized again - vm.store(address(sysConf), bytes32(0), bytes32(0)); + vm.store(address(systemConfig), bytes32(0), bytes32(0)); - assertEq(sysConf.startBlock(), block.number); + assertEq(systemConfig.startBlock(), block.number); // the startBlock slot is 106, wipe it out - vm.store(address(sysConf), bytes32(uint256(106)), bytes32(0)); - assertEq(sysConf.startBlock(), 0); + vm.store(address(systemConfig), bytes32(uint256(106)), bytes32(0)); + assertEq(systemConfig.startBlock(), 0); + + address admin = address(uint160(uint256(vm.load(address(systemConfig), Constants.PROXY_OWNER_ADDRESS)))); + vm.prank(admin); - vm.prank(multisig); - Proxy(payable(address(sysConf))).upgradeToAndCall( + Proxy(payable(address(systemConfig))).upgradeToAndCall( address(systemConfigImpl), abi.encodeCall( SystemConfig.initialize, @@ -128,31 +101,31 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { startBlock, // _startBlock batchInbox, // _batchInbox SystemConfig.Addresses({ // _addresses - l1CrossDomainMessenger: l1CrossDomainMessenger, - l1ERC721Bridge: l1ERC721Bridge, - l1StandardBridge: l1StandardBridge, - l2OutputOracle: l2OutputOracle, - optimismPortal: optimismPortal, + l1CrossDomainMessenger: address(l1CrossDomainMessenger), + l1ERC721Bridge: address(l1ERC721Bridge), + l1StandardBridge: address(l1StandardBridge), + l2OutputOracle: address(l2OutputOracle), + optimismPortal: address(optimismPortal), optimismMintableERC20Factory: optimismMintableERC20Factory }) ) ) ); - assertEq(sysConf.startBlock(), startBlock); + assertEq(systemConfig.startBlock(), startBlock); } /// @dev Tests that initialization with start block already set is a noop. function test_initialize_startBlockNoop_reverts() external { // wipe out initialized slot so we can initialize again - vm.store(address(sysConf), bytes32(0), bytes32(0)); + vm.store(address(systemConfig), bytes32(0), bytes32(0)); // the startBlock slot is 106, set it to something non zero - vm.store(address(sysConf), bytes32(uint256(106)), bytes32(uint256(0xff))); + vm.store(address(systemConfig), bytes32(uint256(106)), bytes32(uint256(0xff))); // Initialize with a non zero start block, should see a revert - vm.prank(multisig); + vm.prank(EIP1967Helper.getAdmin(address(systemConfig))); // The call to initialize reverts due to: "SystemConfig: cannot override an already set start block" // but the proxy revert message bubbles up. - Proxy(payable(address(sysConf))).upgradeToAndCall( + Proxy(payable(address(systemConfig))).upgradeToAndCall( address(systemConfigImpl), abi.encodeCall( SystemConfig.initialize, @@ -167,11 +140,11 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { 1, // _startBlock batchInbox, // _batchInbox SystemConfig.Addresses({ // _addresses - l1CrossDomainMessenger: l1CrossDomainMessenger, - l1ERC721Bridge: l1ERC721Bridge, - l1StandardBridge: l1StandardBridge, - l2OutputOracle: l2OutputOracle, - optimismPortal: optimismPortal, + l1CrossDomainMessenger: address(l1CrossDomainMessenger), + l1ERC721Bridge: address(l1ERC721Bridge), + l1StandardBridge: address(l1StandardBridge), + l2OutputOracle: address(l2OutputOracle), + optimismPortal: address(optimismPortal), optimismMintableERC20Factory: optimismMintableERC20Factory }) ) @@ -180,29 +153,31 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { // It was initialized with 1 but it was already set so the override // should be ignored. - uint256 startBlock = sysConf.startBlock(); + uint256 startBlock = systemConfig.startBlock(); assertEq(startBlock, 0xff); } /// @dev Ensures that the events are emitted during initialization. function test_initialize_events_succeeds() external { // Wipe out the initialized slot so the proxy can be initialized again - vm.store(address(sysConf), bytes32(0), bytes32(0)); - vm.store(address(sysConf), bytes32(uint256(106)), bytes32(0)); - assertEq(sysConf.startBlock(), 0); + vm.store(address(systemConfig), bytes32(0), bytes32(0)); + vm.store(address(systemConfig), bytes32(uint256(106)), bytes32(0)); + assertEq(systemConfig.startBlock(), 0); // The order depends here - vm.expectEmit(true, true, true, true, address(sysConf)); + vm.expectEmit(true, true, true, true, address(systemConfig)); emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(batcherHash)); - vm.expectEmit(true, true, true, true, address(sysConf)); + vm.expectEmit(true, true, true, true, address(systemConfig)); emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_CONFIG, abi.encode(overhead, scalar)); - vm.expectEmit(true, true, true, true, address(sysConf)); + vm.expectEmit(true, true, true, true, address(systemConfig)); emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(gasLimit)); - vm.expectEmit(true, true, true, true, address(sysConf)); + vm.expectEmit(true, true, true, true, address(systemConfig)); emit ConfigUpdate(0, SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER, abi.encode(unsafeBlockSigner)); - vm.prank(multisig); - Proxy(payable(address(sysConf))).upgradeToAndCall( + address admin = address(uint160(uint256(vm.load(address(systemConfig), Constants.PROXY_OWNER_ADDRESS)))); + vm.prank(admin); + + Proxy(payable(address(systemConfig))).upgradeToAndCall( address(systemConfigImpl), abi.encodeCall( SystemConfig.initialize, @@ -217,11 +192,11 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { 0, // _startBlock batchInbox, // _batchInbox SystemConfig.Addresses({ // _addresses - l1CrossDomainMessenger: l1CrossDomainMessenger, - l1ERC721Bridge: l1ERC721Bridge, - l1StandardBridge: l1StandardBridge, - l2OutputOracle: l2OutputOracle, - optimismPortal: optimismPortal, + l1CrossDomainMessenger: address(l1CrossDomainMessenger), + l1ERC721Bridge: address(l1ERC721Bridge), + l1StandardBridge: address(l1StandardBridge), + l2OutputOracle: address(l2OutputOracle), + optimismPortal: address(optimismPortal), optimismMintableERC20Factory: optimismMintableERC20Factory }) ) @@ -233,15 +208,19 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { contract SystemConfig_Initialize_TestFail is SystemConfig_Init { /// @dev Tests that initialization reverts if the gas limit is too low. function test_initialize_lowGasLimit_reverts() external { - uint64 minimumGasLimit = sysConf.minimumGasLimit(); + address systemConfigImpl = mustGetAddress("SystemConfig"); + uint64 minimumGasLimit = systemConfig.minimumGasLimit(); // Wipe out the initialized slot so the proxy can be initialized again - vm.store(address(sysConf), bytes32(0), bytes32(0)); - vm.prank(multisig); + vm.store(address(systemConfig), bytes32(0), bytes32(0)); + + address admin = address(uint160(uint256(vm.load(address(systemConfig), Constants.PROXY_OWNER_ADDRESS)))); + vm.prank(admin); + // The call to initialize reverts due to: "SystemConfig: gas limit too low" // but the proxy revert message bubbles up. vm.expectRevert("Proxy: delegatecall to new implementation contract failed"); - Proxy(payable(address(sysConf))).upgradeToAndCall( + Proxy(payable(address(systemConfig))).upgradeToAndCall( address(systemConfigImpl), abi.encodeCall( SystemConfig.initialize, @@ -273,32 +252,32 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { /// @dev Tests that `setBatcherHash` reverts if the caller is not the owner. function test_setBatcherHash_notOwner_reverts() external { vm.expectRevert("Ownable: caller is not the owner"); - sysConf.setBatcherHash(bytes32(hex"")); + systemConfig.setBatcherHash(bytes32(hex"")); } /// @dev Tests that `setGasConfig` reverts if the caller is not the owner. function test_setGasConfig_notOwner_reverts() external { vm.expectRevert("Ownable: caller is not the owner"); - sysConf.setGasConfig(0, 0); + systemConfig.setGasConfig(0, 0); } /// @dev Tests that `setGasLimit` reverts if the caller is not the owner. function test_setGasLimit_notOwner_reverts() external { vm.expectRevert("Ownable: caller is not the owner"); - sysConf.setGasLimit(0); + systemConfig.setGasLimit(0); } /// @dev Tests that `setUnsafeBlockSigner` reverts if the caller is not the owner. function test_setUnsafeBlockSigner_notOwner_reverts() external { vm.expectRevert("Ownable: caller is not the owner"); - sysConf.setUnsafeBlockSigner(address(0x20)); + systemConfig.setUnsafeBlockSigner(address(0x20)); } /// @dev Tests that `setResourceConfig` reverts if the caller is not the owner. 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); + systemConfig.setResourceConfig(config); } /// @dev Tests that `setResourceConfig` reverts if the min base fee @@ -312,9 +291,9 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { minimumBaseFee: 2 gwei, maximumBaseFee: 1 gwei }); - vm.prank(sysConf.owner()); + vm.prank(systemConfig.owner()); vm.expectRevert("SystemConfig: min base fee must be less than max base"); - sysConf.setResourceConfig(config); + systemConfig.setResourceConfig(config); } /// @dev Tests that `setResourceConfig` reverts if the baseFeeMaxChangeDenominator @@ -328,14 +307,14 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { minimumBaseFee: 1 gwei, maximumBaseFee: 2 gwei }); - vm.prank(sysConf.owner()); + vm.prank(systemConfig.owner()); vm.expectRevert("SystemConfig: denominator must be larger than 1"); - sysConf.setResourceConfig(config); + systemConfig.setResourceConfig(config); } /// @dev Tests that `setResourceConfig` reverts if the gas limit is too low. function test_setResourceConfig_lowGasLimit_reverts() external { - uint64 gasLimit = sysConf.gasLimit(); + uint64 gasLimit = systemConfig.gasLimit(); ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ maxResourceLimit: uint32(gasLimit), @@ -345,9 +324,9 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { minimumBaseFee: 1 gwei, maximumBaseFee: 2 gwei }); - vm.prank(sysConf.owner()); + vm.prank(systemConfig.owner()); vm.expectRevert("SystemConfig: gas limit too low"); - sysConf.setResourceConfig(config); + systemConfig.setResourceConfig(config); } /// @dev Tests that `setResourceConfig` reverts if the elasticity multiplier @@ -361,9 +340,9 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { minimumBaseFee: 1 gwei, maximumBaseFee: 2 gwei }); - vm.prank(sysConf.owner()); + vm.prank(systemConfig.owner()); vm.expectRevert("SystemConfig: precision loss with target resource limit"); - sysConf.setResourceConfig(config); + systemConfig.setResourceConfig(config); } } @@ -373,9 +352,9 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { vm.expectEmit(true, true, true, true); emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash)); - vm.prank(sysConf.owner()); - sysConf.setBatcherHash(newBatcherHash); - assertEq(sysConf.batcherHash(), newBatcherHash); + vm.prank(systemConfig.owner()); + systemConfig.setBatcherHash(newBatcherHash); + assertEq(systemConfig.batcherHash(), newBatcherHash); } /// @dev Tests that `setGasConfig` updates the overhead and scalar successfully. @@ -383,23 +362,23 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { vm.expectEmit(true, true, true, true); emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_CONFIG, abi.encode(newOverhead, newScalar)); - vm.prank(sysConf.owner()); - sysConf.setGasConfig(newOverhead, newScalar); - assertEq(sysConf.overhead(), newOverhead); - assertEq(sysConf.scalar(), newScalar); + vm.prank(systemConfig.owner()); + systemConfig.setGasConfig(newOverhead, newScalar); + assertEq(systemConfig.overhead(), newOverhead); + assertEq(systemConfig.scalar(), newScalar); } /// @dev Tests that `setGasLimit` updates the gas limit successfully. function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external { - uint64 minimumGasLimit = sysConf.minimumGasLimit(); + uint64 minimumGasLimit = systemConfig.minimumGasLimit(); newGasLimit = uint64(bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(type(uint64).max))); vm.expectEmit(true, true, true, true); emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit)); - vm.prank(sysConf.owner()); - sysConf.setGasLimit(newGasLimit); - assertEq(sysConf.gasLimit(), newGasLimit); + vm.prank(systemConfig.owner()); + systemConfig.setGasLimit(newGasLimit); + assertEq(systemConfig.gasLimit(), newGasLimit); } /// @dev Tests that `setUnsafeBlockSigner` updates the block signer successfully. @@ -407,8 +386,8 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { vm.expectEmit(true, true, true, true); emit ConfigUpdate(0, SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER, abi.encode(newUnsafeSigner)); - vm.prank(sysConf.owner()); - sysConf.setUnsafeBlockSigner(newUnsafeSigner); - assertEq(sysConf.unsafeBlockSigner(), newUnsafeSigner); + vm.prank(systemConfig.owner()); + systemConfig.setUnsafeBlockSigner(newUnsafeSigner); + assertEq(systemConfig.unsafeBlockSigner(), newUnsafeSigner); } } diff --git a/packages/contracts-bedrock/test/Transactor.t.sol b/packages/contracts-bedrock/test/Transactor.t.sol index 70c02e53d813..af6ce0fba1ca 100644 --- a/packages/contracts-bedrock/test/Transactor.t.sol +++ b/packages/contracts-bedrock/test/Transactor.t.sol @@ -3,8 +3,7 @@ pragma solidity 0.8.15; // Testing utilities import { Test } from "forge-std/Test.sol"; -import { CallRecorder } from "test/Helpers.sol"; -import { Reverter } from "test/Helpers.sol"; +import { CallRecorder, Reverter } from "test/mocks/Callers.sol"; import { Transactor } from "src/periphery/Transactor.sol"; contract Transactor_Initializer is Test { diff --git a/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol index 6eef617f5095..a2a1bf2e0d55 100644 --- a/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol @@ -5,12 +5,13 @@ import { StdUtils } from "forge-std/StdUtils.sol"; import { Vm } from "forge-std/Vm.sol"; import { OptimismPortal } from "src/L1/OptimismPortal.sol"; import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; -import { Messenger_Initializer } from "test/CommonTest.t.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { Types } from "src/libraries/Types.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Constants } from "src/libraries/Constants.sol"; import { Encoding } from "src/libraries/Encoding.sol"; import { Hashing } from "src/libraries/Hashing.sol"; +import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; contract RelayActor is StdUtils { // Storage slot of the l2Sender @@ -88,7 +89,7 @@ contract RelayActor is StdUtils { } } -contract XDM_MinGasLimits is Messenger_Initializer { +contract XDM_MinGasLimits is Bridge_Initializer { RelayActor actor; function init(bool doFail) public virtual { @@ -96,10 +97,10 @@ contract XDM_MinGasLimits is Messenger_Initializer { super.setUp(); // Deploy a relay actor - actor = new RelayActor(op, L1Messenger, vm, doFail); + actor = new RelayActor(optimismPortal, l1CrossDomainMessenger, vm, doFail); // Give the portal some ether to send to `relayMessage` - vm.deal(address(op), type(uint128).max); + vm.deal(address(optimismPortal), type(uint128).max); // Target the `RelayActor` contract targetContract(address(actor)); @@ -138,9 +139,9 @@ contract XDM_MinGasLimits_Succeeds is XDM_MinGasLimits { for (uint256 i = 0; i < length; ++i) { bytes32 hash = actor.hashes(i); // The message hash is set in the successfulMessages mapping - assertTrue(L1Messenger.successfulMessages(hash)); + assertTrue(l1CrossDomainMessenger.successfulMessages(hash)); // The message hash is not set in the failedMessages mapping - assertFalse(L1Messenger.failedMessages(hash)); + assertFalse(l1CrossDomainMessenger.failedMessages(hash)); } assertFalse(actor.reverted()); } @@ -171,9 +172,9 @@ contract XDM_MinGasLimits_Reverts is XDM_MinGasLimits { for (uint256 i = 0; i < length; ++i) { bytes32 hash = actor.hashes(i); // The message hash is not set in the successfulMessages mapping - assertFalse(L1Messenger.successfulMessages(hash)); + assertFalse(l1CrossDomainMessenger.successfulMessages(hash)); // The message hash is set in the failedMessages mapping - assertTrue(L1Messenger.failedMessages(hash)); + assertTrue(l1CrossDomainMessenger.failedMessages(hash)); } assertFalse(actor.reverted()); } diff --git a/packages/contracts-bedrock/test/invariants/L2OutputOracle.t.sol b/packages/contracts-bedrock/test/invariants/L2OutputOracle.t.sol index 79d637fca9d6..c688ef419617 100644 --- a/packages/contracts-bedrock/test/invariants/L2OutputOracle.t.sol +++ b/packages/contracts-bedrock/test/invariants/L2OutputOracle.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { L2OutputOracle_Initializer } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; import { Vm } from "forge-std/Vm.sol"; @@ -29,14 +29,14 @@ contract L2OutputOracle_Proposer { } } -contract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_Initializer { +contract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is CommonTest { L2OutputOracle_Proposer internal actor; function setUp() public override { super.setUp(); // Create a proposer actor. - actor = new L2OutputOracle_Proposer(oracle, vm); + actor = new L2OutputOracle_Proposer(l2OutputOracle, vm); // Set the target contract to the proposer actor. targetContract(address(actor)); @@ -57,6 +57,6 @@ contract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_In /// correspond to a block number that is less than the current output. function invariant_monotonicBlockNumIncrease() external { // Assert that the block number of proposals must monotonically increase. - assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber()); + assertTrue(l2OutputOracle.nextBlockNumber() >= l2OutputOracle.latestBlockNumber()); } } diff --git a/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol b/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol index af38e6536bb8..009a6a9daca1 100644 --- a/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol +++ b/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol @@ -11,8 +11,8 @@ import { SystemConfig } from "src/L1/SystemConfig.sol"; import { ResourceMetering } from "src/L1/ResourceMetering.sol"; import { Constants } from "src/libraries/Constants.sol"; -import { Portal_Initializer } from "test/CommonTest.t.sol"; -import { EIP1967Helper } from "test/CommonTest.t.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { Types } from "src/libraries/Types.sol"; contract OptimismPortal_Depositor is StdUtils, ResourceMetering { @@ -74,7 +74,7 @@ contract OptimismPortal_Depositor is StdUtils, ResourceMetering { } } -contract OptimismPortal_Invariant_Harness is Portal_Initializer { +contract OptimismPortal_Invariant_Harness is CommonTest { // Reusable default values for a test withdrawal Types.WithdrawalTransaction _defaultTx; @@ -109,28 +109,31 @@ contract OptimismPortal_Invariant_Harness is Portal_Initializer { messagePasserStorageRoot: _storageRoot, latestBlockhash: bytes32(uint256(0)) }); - _proposedBlockNumber = oracle.nextBlockNumber(); - _proposedOutputIndex = oracle.nextOutputIndex(); + _proposedBlockNumber = l2OutputOracle.nextBlockNumber(); + _proposedOutputIndex = l2OutputOracle.nextOutputIndex(); // Configure the oracle to return the output root we've prepared. - vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1); - vm.prank(oracle.PROPOSER()); - oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0); + vm.warp(l2OutputOracle.computeL2Timestamp(_proposedBlockNumber) + 1); + vm.prank(l2OutputOracle.PROPOSER()); + l2OutputOracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0); // Warp beyond the finalization period for the block we've proposed. - vm.warp(oracle.getL2Output(_proposedOutputIndex).timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp( + l2OutputOracle.getL2Output(_proposedOutputIndex).timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + + 1 + ); // Fund the portal so that we can withdraw ETH. - vm.deal(address(op), 0xFFFFFFFF); + vm.deal(address(optimismPortal), 0xFFFFFFFF); } } -contract OptimismPortal_Deposit_Invariant is Portal_Initializer { +contract OptimismPortal_Deposit_Invariant is CommonTest { OptimismPortal_Depositor internal actor; function setUp() public override { super.setUp(); // Create a deposit actor. - actor = new OptimismPortal_Depositor(vm, op); + actor = new OptimismPortal_Depositor(vm, optimismPortal); targetContract(address(actor)); @@ -155,12 +158,12 @@ contract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness { super.setUp(); // Prove the withdrawal transaction - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); // Set the target contract to the portal proxy - targetContract(address(op)); + targetContract(address(optimismPortal)); // Exclude the proxy admin from the senders so that the proxy cannot be upgraded - excludeSender(EIP1967Helper.getAdmin(address(op))); + excludeSender(EIP1967Helper.getAdmin(address(optimismPortal))); } /// @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization @@ -170,7 +173,7 @@ contract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness { /// until after the finalization period has elapsed. function invariant_cannotFinalizeBeforePeriodHasPassed() external { vm.expectRevert("OptimismPortal: proven withdrawal finalization period has not elapsed"); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); } } @@ -179,18 +182,18 @@ contract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness super.setUp(); // Prove the withdrawal transaction - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); // Warp past the finalization period. - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); // Finalize the withdrawal transaction. - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); // Set the target contract to the portal proxy - targetContract(address(op)); + targetContract(address(optimismPortal)); // Exclude the proxy admin from the senders so that the proxy cannot be upgraded - excludeSender(EIP1967Helper.getAdmin(address(op))); + excludeSender(EIP1967Helper.getAdmin(address(optimismPortal))); } /// @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal @@ -200,7 +203,7 @@ contract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness /// allows a withdrawal to be finalized twice. function invariant_cannotFinalizeTwice() external { vm.expectRevert("OptimismPortal: withdrawal has already been finalized"); - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); } } @@ -209,15 +212,15 @@ contract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant super.setUp(); // Prove the withdrawal transaction - op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); + optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof); // Warp past the finalization period. - vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1); + vm.warp(block.timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS() + 1); // Set the target contract to the portal proxy - targetContract(address(op)); + targetContract(address(optimismPortal)); // Exclude the proxy admin from the senders so that the proxy cannot be upgraded - excludeSender(EIP1967Helper.getAdmin(address(op))); + excludeSender(EIP1967Helper.getAdmin(address(optimismPortal))); } /// @custom:invariant A withdrawal should **always** be able to be finalized @@ -230,7 +233,7 @@ contract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant function invariant_canAlwaysFinalize() external { uint256 bobBalanceBefore = address(bob).balance; - op.finalizeWithdrawalTransaction(_defaultTx); + optimismPortal.finalizeWithdrawalTransaction(_defaultTx); assertEq(address(bob).balance, bobBalanceBefore + _defaultTx.value); } diff --git a/packages/contracts-bedrock/test/mocks/AlphabetVM.sol b/packages/contracts-bedrock/test/mocks/AlphabetVM.sol new file mode 100644 index 000000000000..b73c5924b9bb --- /dev/null +++ b/packages/contracts-bedrock/test/mocks/AlphabetVM.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import { IBigStepper, IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; +import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; +import "src/libraries/DisputeTypes.sol"; + +/// @title AlphabetVM +/// @dev A mock VM for the purpose of testing the dispute game infrastructure. +contract AlphabetVM is IBigStepper { + Claim internal immutable ABSOLUTE_PRESTATE; + IPreimageOracle public oracle; + + constructor(Claim _absolutePrestate) { + ABSOLUTE_PRESTATE = _absolutePrestate; + oracle = new PreimageOracle(); + } + + /// @inheritdoc IBigStepper + function step(bytes calldata _stateData, bytes calldata, uint256) external view returns (bytes32 postState_) { + uint256 traceIndex; + uint256 claim; + if ((keccak256(_stateData) << 8) == (Claim.unwrap(ABSOLUTE_PRESTATE) << 8)) { + // If the state data is empty, then the absolute prestate is the claim. + traceIndex = 0; + (claim) = abi.decode(_stateData, (uint256)); + } else { + // Otherwise, decode the state data. + (traceIndex, claim) = abi.decode(_stateData, (uint256, uint256)); + traceIndex++; + } + // STF: n -> n + 1 + postState_ = keccak256(abi.encode(traceIndex, claim + 1)); + assembly { + postState_ := or(and(postState_, not(shl(248, 0xFF))), shl(248, 1)) + } + } +} diff --git a/packages/contracts-bedrock/test/mocks/Callers.sol b/packages/contracts-bedrock/test/mocks/Callers.sol new file mode 100644 index 000000000000..aa7a2dc8b228 --- /dev/null +++ b/packages/contracts-bedrock/test/mocks/Callers.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract CallRecorder { + struct CallInfo { + address sender; + bytes data; + uint256 gas; + uint256 value; + } + + CallInfo public lastCall; + + function record() public payable { + lastCall.sender = msg.sender; + lastCall.data = msg.data; + lastCall.gas = gasleft(); + lastCall.value = msg.value; + } +} + +/// @dev Useful for testing reentrancy guards +contract CallerCaller { + event WhatHappened(bool success, bytes returndata); + + fallback() external { + (bool success, bytes memory returndata) = msg.sender.call(msg.data); + emit WhatHappened(success, returndata); + assembly { + switch success + case 0 { revert(add(returndata, 0x20), mload(returndata)) } + default { return(add(returndata, 0x20), mload(returndata)) } + } + } +} + +/// @dev Used for testing the `CrossDomainMessenger`'s per-message reentrancy guard. +contract ConfigurableCaller { + bool doRevert = true; + address target; + bytes payload; + + event WhatHappened(bool success, bytes returndata); + + /// @notice Call the configured target with the configured payload OR revert. + function call() external { + if (doRevert) { + revert("ConfigurableCaller: revert"); + } else { + (bool success, bytes memory returndata) = address(target).call(payload); + emit WhatHappened(success, returndata); + assembly { + switch success + case 0 { revert(add(returndata, 0x20), mload(returndata)) } + default { return(add(returndata, 0x20), mload(returndata)) } + } + } + } + + /// @notice Set whether or not to have `call` revert. + function setDoRevert(bool _doRevert) external { + doRevert = _doRevert; + } + + /// @notice Set the target for the call made in `call`. + function setTarget(address _target) external { + target = _target; + } + + /// @notice Set the payload for the call made in `call`. + function setPayload(bytes calldata _payload) external { + payload = _payload; + } + + /// @notice Fallback function that reverts if `doRevert` is true. + /// Otherwise, it does nothing. + fallback() external { + if (doRevert) { + revert("ConfigurableCaller: revert"); + } + } +} + +/// @dev Any call will revert +contract Reverter { + function doRevert() public pure { + revert("Reverter reverted"); + } + + fallback() external { + revert(); + } +} diff --git a/packages/contracts-bedrock/test/mocks/EIP1967Helper.sol b/packages/contracts-bedrock/test/mocks/EIP1967Helper.sol new file mode 100644 index 000000000000..31002b65517a --- /dev/null +++ b/packages/contracts-bedrock/test/mocks/EIP1967Helper.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Vm } from "forge-std/Vm.sol"; +import { Constants } from "src/libraries/Constants.sol"; + +/// @title EIP1967Helper +/// @dev Testing library to help with reading EIP 1967 variables from state +library EIP1967Helper { + Vm internal constant vm = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); + + function getAdmin(address _proxy) internal view returns (address) { + return address(uint160(uint256(vm.load(address(_proxy), Constants.PROXY_OWNER_ADDRESS)))); + } + + function getImplementation(address _proxy) internal view returns (address) { + return address(uint160(uint256(vm.load(address(_proxy), Constants.PROXY_IMPLEMENTATION_ADDRESS)))); + } +} diff --git a/packages/contracts-bedrock/test/mocks/FaucetHelper.sol b/packages/contracts-bedrock/test/mocks/FaucetHelper.sol new file mode 100644 index 000000000000..e9023e2d93e8 --- /dev/null +++ b/packages/contracts-bedrock/test/mocks/FaucetHelper.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ECDSAUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; +import { AdminFaucetAuthModule } from "src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol"; + +/// @notice Simple helper contract that helps with testing the Faucet contract. +contract FaucetHelper { + /// @notice EIP712 typehash for the Proof type. + bytes32 public constant PROOF_TYPEHASH = keccak256("Proof(address recipient,bytes32 nonce,bytes32 id)"); + + /// @notice EIP712 typehash for the EIP712Domain type that is included as part of the signature. + bytes32 public constant EIP712_DOMAIN_TYPEHASH = + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); + + /// @notice Keeps track of current nonce to generate new nonces for each drip. + uint256 public currentNonce; + + /// @notice Returns a bytes32 nonce that should change everytime. In practice, people should use + /// pseudorandom nonces. + /// @return Nonce that should be used as part of drip parameters. + function consumeNonce() public returns (bytes32) { + return bytes32(keccak256(abi.encode(currentNonce++))); + } + + /// @notice Returns the hash of the struct Proof. + /// @param _proof Proof struct to hash. + /// @return EIP-712 typed struct hash. + function getProofStructHash(AdminFaucetAuthModule.Proof memory _proof) public pure returns (bytes32) { + return keccak256(abi.encode(PROOF_TYPEHASH, _proof.recipient, _proof.nonce, _proof.id)); + } + + /// @notice Computes the EIP712 digest with the given domain parameters. + /// Used for testing that different domain parameters fail. + /// @param _proof Proof struct to hash. + /// @param _name Contract name to use in the EIP712 domain. + /// @param _version Contract version to use in the EIP712 domain. + /// @param _chainid Chain ID to use in the EIP712 domain. + /// @param _verifyingContract Address to use in the EIP712 domain. + /// @param _verifyingContract Address to use in the EIP712 domain. + /// @param _verifyingContract Address to use in the EIP712 domain. + /// @return EIP-712 compatible digest. + function getDigestWithEIP712Domain( + AdminFaucetAuthModule.Proof memory _proof, + bytes memory _name, + bytes memory _version, + uint256 _chainid, + address _verifyingContract + ) + public + pure + returns (bytes32) + { + bytes32 domainSeparator = keccak256( + abi.encode(EIP712_DOMAIN_TYPEHASH, keccak256(_name), keccak256(_version), _chainid, _verifyingContract) + ); + return ECDSAUpgradeable.toTypedDataHash(domainSeparator, getProofStructHash(_proof)); + } +} diff --git a/packages/contracts-bedrock/test/mocks/NextImpl.sol b/packages/contracts-bedrock/test/mocks/NextImpl.sol new file mode 100644 index 000000000000..3d857cfdc2d0 --- /dev/null +++ b/packages/contracts-bedrock/test/mocks/NextImpl.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +/// @title NextImpl +/// @dev Used for testing a future upgrade beyond the current implementations. +// We include some variables so that we can sanity check accessing storage values after an upgrade. +contract NextImpl is Initializable { + // Initializable occupies the zero-th slot. + bytes32 slot1; + bytes32[19] __gap; + bytes32 slot21; + bytes32 public constant slot21Init = bytes32(hex"1337"); + + function initialize(uint8 _init) public reinitializer(_init) { + // Slot21 is unused by an of our upgradeable contracts. + // This is used to verify that we can access this value after an upgrade. + slot21 = slot21Init; + } +} diff --git a/packages/contracts-bedrock/test/mocks/OptimistInviterHelper.sol b/packages/contracts-bedrock/test/mocks/OptimistInviterHelper.sol new file mode 100644 index 000000000000..ebc2289f9c10 --- /dev/null +++ b/packages/contracts-bedrock/test/mocks/OptimistInviterHelper.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { OptimistInviter } from "src/periphery/op-nft/OptimistInviter.sol"; +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; + +/// @notice Simple helper contract that helps with testing flow and signature for +/// OptimistInviter contract. Made this a separate contract instead of including +/// in OptimistInviter.t.sol for reusability. +contract OptimistInviterHelper { + /// @notice EIP712 typehash for the ClaimableInvite type. + bytes32 public constant CLAIMABLE_INVITE_TYPEHASH = keccak256("ClaimableInvite(address issuer,bytes32 nonce)"); + + /// @notice EIP712 typehash for the EIP712Domain type that is included as part of the signature. + bytes32 public constant EIP712_DOMAIN_TYPEHASH = + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); + + /// @notice Address of OptimistInviter contract we are testing. + OptimistInviter public optimistInviter; + + /// @notice OptimistInviter contract name. Used to construct the EIP-712 domain. + string public name; + + /// @notice Keeps track of current nonce to generate new nonces for each invite. + uint256 public currentNonce; + + constructor(OptimistInviter _optimistInviter, string memory _name) { + optimistInviter = _optimistInviter; + name = _name; + } + + /// @notice Returns the hash of the struct ClaimableInvite. + /// @param _claimableInvite ClaimableInvite struct to hash. + /// @return EIP-712 typed struct hash. + function getClaimableInviteStructHash(OptimistInviter.ClaimableInvite memory _claimableInvite) + public + pure + returns (bytes32) + { + return keccak256(abi.encode(CLAIMABLE_INVITE_TYPEHASH, _claimableInvite.issuer, _claimableInvite.nonce)); + } + + /// @notice Returns a bytes32 nonce that should change everytime. In practice, people should use + /// pseudorandom nonces. + /// @return Nonce that should be used as part of ClaimableInvite. + function consumeNonce() public returns (bytes32) { + return bytes32(keccak256(abi.encode(currentNonce++))); + } + + /// @notice Returns a ClaimableInvite with the issuer and current nonce. + /// @param _issuer Issuer to include in the ClaimableInvite. + /// @return ClaimableInvite that can be hashed & signed. + function getClaimableInviteWithNewNonce(address _issuer) public returns (OptimistInviter.ClaimableInvite memory) { + return OptimistInviter.ClaimableInvite(_issuer, consumeNonce()); + } + + /// @notice Computes the EIP712 digest with default correct parameters. + /// @param _claimableInvite ClaimableInvite struct to hash. + /// @return EIP-712 compatible digest. + function getDigest(OptimistInviter.ClaimableInvite calldata _claimableInvite) public view returns (bytes32) { + return getDigestWithEIP712Domain( + _claimableInvite, + bytes(name), + bytes(optimistInviter.EIP712_VERSION()), + block.chainid, + address(optimistInviter) + ); + } + + /// @notice Computes the EIP712 digest with the given domain parameters. + /// Used for testing that different domain parameters fail. + /// @param _claimableInvite ClaimableInvite struct to hash. + /// @param _name Contract name to use in the EIP712 domain. + /// @param _version Contract version to use in the EIP712 domain. + /// @param _chainid Chain ID to use in the EIP712 domain. + /// @param _verifyingContract Address to use in the EIP712 domain. + /// @return EIP-712 compatible digest. + function getDigestWithEIP712Domain( + OptimistInviter.ClaimableInvite calldata _claimableInvite, + bytes memory _name, + bytes memory _version, + uint256 _chainid, + address _verifyingContract + ) + public + pure + returns (bytes32) + { + bytes32 domainSeparator = keccak256( + abi.encode(EIP712_DOMAIN_TYPEHASH, keccak256(_name), keccak256(_version), _chainid, _verifyingContract) + ); + return ECDSA.toTypedDataHash(domainSeparator, getClaimableInviteStructHash(_claimableInvite)); + } +} diff --git a/packages/contracts-bedrock/test/mocks/SimpleStorage.sol b/packages/contracts-bedrock/test/mocks/SimpleStorage.sol new file mode 100644 index 000000000000..218505b24c05 --- /dev/null +++ b/packages/contracts-bedrock/test/mocks/SimpleStorage.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract SimpleStorage { + mapping(bytes32 => bytes32) public db; + + function set(bytes32 _key, bytes32 _value) public payable { + db[_key] = _value; + } + + function get(bytes32 _key) public view returns (bytes32) { + return db[_key]; + } +} diff --git a/packages/contracts-bedrock/test/mocks/TestERC1271Wallet.sol b/packages/contracts-bedrock/test/mocks/TestERC1271Wallet.sol new file mode 100644 index 000000000000..c04ed608b7d7 --- /dev/null +++ b/packages/contracts-bedrock/test/mocks/TestERC1271Wallet.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { IERC1271 } from "@openzeppelin/contracts/interfaces/IERC1271.sol"; +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; + +/// @notice Simple ERC1271 wallet that can be used to test the ERC1271 signature checker. +/// @notice https://github.com/OpenZeppelin/openzeppelin-contracts/ +/// blob/master/contracts/mocks/ERC1271WalletMock.sol +contract TestERC1271Wallet is Ownable, IERC1271 { + constructor(address originalOwner) { + transferOwnership(originalOwner); + } + + function isValidSignature(bytes32 hash, bytes memory signature) public view override returns (bytes4 magicValue) { + return ECDSA.recover(hash, signature) == owner() ? this.isValidSignature.selector : bytes4(0); + } +} diff --git a/packages/contracts-bedrock/test/mocks/TestERC20.sol b/packages/contracts-bedrock/test/mocks/TestERC20.sol new file mode 100644 index 000000000000..0c6603ce401f --- /dev/null +++ b/packages/contracts-bedrock/test/mocks/TestERC20.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol"; + +contract TestERC20 is ERC20 { + constructor() ERC20("TEST", "TST", 18) { } + + function mint(address to, uint256 value) public { + _mint(to, value); + } +} diff --git a/packages/contracts-bedrock/test/mocks/TestERC721.sol b/packages/contracts-bedrock/test/mocks/TestERC721.sol new file mode 100644 index 000000000000..294b4a93c7e5 --- /dev/null +++ b/packages/contracts-bedrock/test/mocks/TestERC721.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ERC721 } from "@rari-capital/solmate/src/tokens/ERC721.sol"; + +contract TestERC721 is ERC721 { + constructor() ERC721("TEST", "TST") { } + + function mint(address to, uint256 tokenId) public { + _mint(to, tokenId); + } + + function tokenURI(uint256) public pure virtual override returns (string memory) { } +} diff --git a/packages/contracts-bedrock/test/safe-tools/SafeTestTools.sol b/packages/contracts-bedrock/test/safe-tools/SafeTestTools.sol index f4ff521ff0c9..93b33fbab2a9 100644 --- a/packages/contracts-bedrock/test/safe-tools/SafeTestTools.sol +++ b/packages/contracts-bedrock/test/safe-tools/SafeTestTools.sol @@ -212,17 +212,10 @@ library SafeTestLib { address[] memory _ownersList ) internal - view - returns ( - // pure - address prevOwner_ - ) + pure + returns (address prevOwner_) { - // console.log("getPrevOwnerFromList"); - for (uint256 i = 0; i < _ownersList.length; i++) { - // console.log(i); - // console.log(_owner); - // console.log("_ownersList[i]:", _ownersList[i]); + for (uint256 i; i < _ownersList.length; i++) { if (_ownersList[i] != _owner) continue; if (i == 0) { prevOwner_ = SENTINEL_OWNERS; @@ -230,8 +223,6 @@ library SafeTestLib { } prevOwner_ = _ownersList[i - 1]; } - - console.log("prevOwner_:", prevOwner_); } /// @dev Given an array of owners to remove, this function will return an array of the previous owners @@ -250,7 +241,7 @@ library SafeTestLib { OwnerSimulator ownerSimulator = new OwnerSimulator(instance.owners, 1); prevOwners_ = new address[](_ownersToRemove.length); address[] memory currentOwners; - for (uint256 i = 0; i < _ownersToRemove.length; i++) { + for (uint256 i; i < _ownersToRemove.length; i++) { currentOwners = ownerSimulator.getOwners(); prevOwners_[i] = SafeTestLib.getPrevOwnerFromList(_ownersToRemove[i], currentOwners); diff --git a/packages/contracts-bedrock/test/setup/Bridge_Initializer.sol b/packages/contracts-bedrock/test/setup/Bridge_Initializer.sol new file mode 100644 index 000000000000..6b931712935e --- /dev/null +++ b/packages/contracts-bedrock/test/setup/Bridge_Initializer.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { CommonTest } from "test/setup/CommonTest.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; +import { LegacyMintableERC20 } from "src/legacy/LegacyMintableERC20.sol"; + +/// @title Bridge_Initializer +/// @dev This contract extends the CommonTest contract with token deployments +/// meant to be used with the bridge contracts. +contract Bridge_Initializer is CommonTest { + ERC20 L1Token; + ERC20 BadL1Token; + OptimismMintableERC20 L2Token; + LegacyMintableERC20 LegacyL2Token; + ERC20 NativeL2Token; + ERC20 BadL2Token; + OptimismMintableERC20 RemoteL1Token; + + function setUp() public virtual override { + super.setUp(); + + L1Token = new ERC20("Native L1 Token", "L1T"); + + LegacyL2Token = new LegacyMintableERC20({ + _l2Bridge: address(l2StandardBridge), + _l1Token: address(L1Token), + _name: string.concat("LegacyL2-", L1Token.name()), + _symbol: string.concat("LegacyL2-", L1Token.symbol()) + }); + vm.label(address(LegacyL2Token), "LegacyMintableERC20"); + + // Deploy the L2 ERC20 now + L2Token = OptimismMintableERC20( + l2OptimismMintableERC20Factory.createStandardL2Token( + address(L1Token), + string(abi.encodePacked("L2-", L1Token.name())), + string(abi.encodePacked("L2-", L1Token.symbol())) + ) + ); + + BadL2Token = OptimismMintableERC20( + l2OptimismMintableERC20Factory.createStandardL2Token( + address(1), + string(abi.encodePacked("L2-", L1Token.name())), + string(abi.encodePacked("L2-", L1Token.symbol())) + ) + ); + + NativeL2Token = new ERC20("Native L2 Token", "L2T"); + + RemoteL1Token = OptimismMintableERC20( + l1OptimismMintableERC20Factory.createStandardL2Token( + address(NativeL2Token), + string(abi.encodePacked("L1-", NativeL2Token.name())), + string(abi.encodePacked("L1-", NativeL2Token.symbol())) + ) + ); + + BadL1Token = OptimismMintableERC20( + l1OptimismMintableERC20Factory.createStandardL2Token( + address(1), + string(abi.encodePacked("L1-", NativeL2Token.name())), + string(abi.encodePacked("L1-", NativeL2Token.symbol())) + ) + ); + } +} diff --git a/packages/contracts-bedrock/test/setup/CommonTest.sol b/packages/contracts-bedrock/test/setup/CommonTest.sol new file mode 100644 index 000000000000..74f040aa1da6 --- /dev/null +++ b/packages/contracts-bedrock/test/setup/CommonTest.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Test } from "forge-std/Test.sol"; +import { Setup } from "test/setup/Setup.sol"; +import { Events } from "test/setup/Events.sol"; +import { FFIInterface } from "test/setup/FFIInterface.sol"; + +/// @title CommonTest +/// @dev An extenstion to `Test` that sets up the optimism smart contracts. +contract CommonTest is Setup, Test, Events { + address alice = address(128); + address bob = address(256); + + bytes32 constant nonZeroHash = keccak256(abi.encode("NON_ZERO")); + + FFIInterface ffi; + + function setUp() public virtual override { + vm.deal(alice, type(uint64).max); + vm.deal(bob, type(uint64).max); + + vm.label(alice, "alice"); + vm.label(bob, "bob"); + + Setup.setUp(); + ffi = new FFIInterface(); + + // Make sure the base fee is non zero + vm.fee(1 gwei); + + // Set sane initialize block numbers + vm.warp(cfg.l2OutputOracleStartingTimestamp() + 1); + vm.roll(cfg.l2OutputOracleStartingBlockNumber() + 1); + + // Deploy L1 + Setup.L1(); + // Deploy L2 + Setup.L2({ cfg: cfg }); + } + + /// @dev Helper function that wraps `TransactionDeposited` event. + /// The magic `0` is the version. + function emitTransactionDeposited( + address _from, + address _to, + uint256 _mint, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + internal + { + emit TransactionDeposited(_from, _to, 0, abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data)); + } + + // @dev Advance the evm's time to meet the L2OutputOracle's requirements for proposeL2Output + function warpToProposeTime(uint256 _nextBlockNumber) public { + vm.warp(l2OutputOracle.computeL2Timestamp(_nextBlockNumber) + 1); + } + + /// @dev Helper function to propose an output. + function proposeAnotherOutput() public { + bytes32 proposedOutput2 = keccak256(abi.encode()); + uint256 nextBlockNumber = l2OutputOracle.nextBlockNumber(); + uint256 nextOutputIndex = l2OutputOracle.nextOutputIndex(); + warpToProposeTime(nextBlockNumber); + uint256 proposedNumber = l2OutputOracle.latestBlockNumber(); + + uint256 submissionInterval = cfg.l2OutputOracleSubmissionInterval(); + // Ensure the submissionInterval is enforced + assertEq(nextBlockNumber, proposedNumber + submissionInterval); + + vm.roll(nextBlockNumber + 1); + + vm.expectEmit(true, true, true, true); + emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp); + + address proposer = cfg.l2OutputOracleProposer(); + vm.prank(proposer); + l2OutputOracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0); + } +} diff --git a/packages/contracts-bedrock/test/setup/Events.sol b/packages/contracts-bedrock/test/setup/Events.sol new file mode 100644 index 000000000000..a9d6d62979c9 --- /dev/null +++ b/packages/contracts-bedrock/test/setup/Events.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { FeeVault } from "src/universal/FeeVault.sol"; + +/// @title Events +/// @dev Contains various events that are tested against. This contract needs to +/// exist until we either modularize the implementations or use a newer version of +/// solc that allows for referencing events from other contracts. +contract Events { + /// @dev OpenZeppelin Ownable.sol transferOwnership event + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); + + event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); + event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); + + event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit); + event SentMessageExtension1(address indexed sender, uint256 value); + event MessagePassed( + uint256 indexed nonce, + address indexed sender, + address indexed target, + uint256 value, + uint256 gasLimit, + bytes data, + bytes32 withdrawalHash + ); + event WithdrawerBalanceBurnt(uint256 indexed amount); + event RelayedMessage(bytes32 indexed msgHash); + event FailedRelayedMessage(bytes32 indexed msgHash); + event TransactionDeposited( + address indexed from, + address indexed to, + uint256 mint, + uint256 value, + uint64 gasLimit, + bool isCreation, + bytes data + ); + event WhatHappened(bool success, bytes returndata); + + event OutputProposed( + bytes32 indexed outputRoot, uint256 indexed l2OutputIndex, uint256 indexed l2BlockNumber, uint256 l1Timestamp + ); + + event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex); + + event Withdrawal(uint256 value, address to, address from); + event Withdrawal(uint256 value, address to, address from, FeeVault.WithdrawalNetwork withdrawalNetwork); + + event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes data); + + event ETHWithdrawalFinalized(address indexed from, address indexed to, uint256 amount, bytes data); + + event ERC20DepositInitiated( + address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data + ); + + event ERC20WithdrawalFinalized( + address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data + ); + + event WithdrawalInitiated( + address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data + ); + + event DepositFinalized( + address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data + ); + + event DepositFailed( + address indexed l1Token, address indexed l2Token, address indexed from, address to, uint256 amount, bytes data + ); + + event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes data); + + event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes data); + + event ERC20BridgeInitiated( + address indexed localToken, + address indexed remoteToken, + address indexed from, + address to, + uint256 amount, + bytes data + ); + + event ERC20BridgeFinalized( + address indexed localToken, + address indexed remoteToken, + address indexed from, + address to, + uint256 amount, + bytes data + ); +} diff --git a/packages/contracts-bedrock/test/setup/FFIInterface.sol b/packages/contracts-bedrock/test/setup/FFIInterface.sol new file mode 100644 index 000000000000..93727a035d73 --- /dev/null +++ b/packages/contracts-bedrock/test/setup/FFIInterface.sol @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Types } from "src/libraries/Types.sol"; +import { Vm } from "forge-std/Vm.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; + +/// @title FFIInterface +contract FFIInterface { + Vm internal constant vm = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); + + function getProveWithdrawalTransactionInputs(Types.WithdrawalTransaction memory _tx) + external + returns (bytes32, bytes32, bytes32, bytes32, bytes[] memory) + { + string[] memory cmds = new string[](9); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "getProveWithdrawalTransactionInputs"; + cmds[3] = vm.toString(_tx.nonce); + cmds[4] = vm.toString(_tx.sender); + cmds[5] = vm.toString(_tx.target); + cmds[6] = vm.toString(_tx.value); + cmds[7] = vm.toString(_tx.gasLimit); + cmds[8] = vm.toString(_tx.data); + + bytes memory result = vm.ffi(cmds); + ( + bytes32 stateRoot, + bytes32 storageRoot, + bytes32 outputRoot, + bytes32 withdrawalHash, + bytes[] memory withdrawalProof + ) = abi.decode(result, (bytes32, bytes32, bytes32, bytes32, bytes[])); + + return (stateRoot, storageRoot, outputRoot, withdrawalHash, withdrawalProof); + } + + function hashCrossDomainMessage( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes memory _data + ) + external + returns (bytes32) + { + string[] memory cmds = new string[](9); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "hashCrossDomainMessage"; + cmds[3] = vm.toString(_nonce); + cmds[4] = vm.toString(_sender); + cmds[5] = vm.toString(_target); + cmds[6] = vm.toString(_value); + cmds[7] = vm.toString(_gasLimit); + cmds[8] = vm.toString(_data); + + bytes memory result = vm.ffi(cmds); + return abi.decode(result, (bytes32)); + } + + function hashWithdrawal( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes memory _data + ) + external + returns (bytes32) + { + string[] memory cmds = new string[](9); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "hashWithdrawal"; + cmds[3] = vm.toString(_nonce); + cmds[4] = vm.toString(_sender); + cmds[5] = vm.toString(_target); + cmds[6] = vm.toString(_value); + cmds[7] = vm.toString(_gasLimit); + cmds[8] = vm.toString(_data); + + bytes memory result = vm.ffi(cmds); + return abi.decode(result, (bytes32)); + } + + function hashOutputRootProof( + bytes32 _version, + bytes32 _stateRoot, + bytes32 _messagePasserStorageRoot, + bytes32 _latestBlockhash + ) + external + returns (bytes32) + { + string[] memory cmds = new string[](7); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "hashOutputRootProof"; + cmds[3] = Strings.toHexString(uint256(_version)); + cmds[4] = Strings.toHexString(uint256(_stateRoot)); + cmds[5] = Strings.toHexString(uint256(_messagePasserStorageRoot)); + cmds[6] = Strings.toHexString(uint256(_latestBlockhash)); + + bytes memory result = vm.ffi(cmds); + return abi.decode(result, (bytes32)); + } + + function hashDepositTransaction( + address _from, + address _to, + uint256 _mint, + uint256 _value, + uint64 _gas, + bytes memory _data, + uint64 _logIndex + ) + external + returns (bytes32) + { + string[] memory cmds = new string[](11); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "hashDepositTransaction"; + cmds[3] = "0x0000000000000000000000000000000000000000000000000000000000000000"; + cmds[4] = vm.toString(_logIndex); + cmds[5] = vm.toString(_from); + cmds[6] = vm.toString(_to); + cmds[7] = vm.toString(_mint); + cmds[8] = vm.toString(_value); + cmds[9] = vm.toString(_gas); + cmds[10] = vm.toString(_data); + + bytes memory result = vm.ffi(cmds); + return abi.decode(result, (bytes32)); + } + + function encodeDepositTransaction(Types.UserDepositTransaction calldata txn) external returns (bytes memory) { + string[] memory cmds = new string[](12); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "encodeDepositTransaction"; + cmds[3] = vm.toString(txn.from); + cmds[4] = vm.toString(txn.to); + cmds[5] = vm.toString(txn.value); + cmds[6] = vm.toString(txn.mint); + cmds[7] = vm.toString(txn.gasLimit); + cmds[8] = vm.toString(txn.isCreation); + cmds[9] = vm.toString(txn.data); + cmds[10] = vm.toString(txn.l1BlockHash); + cmds[11] = vm.toString(txn.logIndex); + + bytes memory result = vm.ffi(cmds); + return abi.decode(result, (bytes)); + } + + function encodeCrossDomainMessage( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes memory _data + ) + external + returns (bytes memory) + { + string[] memory cmds = new string[](9); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "encodeCrossDomainMessage"; + cmds[3] = vm.toString(_nonce); + cmds[4] = vm.toString(_sender); + cmds[5] = vm.toString(_target); + cmds[6] = vm.toString(_value); + cmds[7] = vm.toString(_gasLimit); + cmds[8] = vm.toString(_data); + + bytes memory result = vm.ffi(cmds); + return abi.decode(result, (bytes)); + } + + function decodeVersionedNonce(uint256 nonce) external returns (uint256, uint256) { + string[] memory cmds = new string[](4); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "decodeVersionedNonce"; + cmds[3] = vm.toString(nonce); + + bytes memory result = vm.ffi(cmds); + return abi.decode(result, (uint256, uint256)); + } + + function getMerkleTrieFuzzCase(string memory variant) + external + returns (bytes32, bytes memory, bytes memory, bytes[] memory) + { + string[] memory cmds = new string[](6); + cmds[0] = "./scripts/go-ffi/go-ffi"; + cmds[1] = "trie"; + cmds[2] = variant; + + return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[])); + } + + function getCannonMemoryProof(uint32 pc, uint32 insn) external returns (bytes32, bytes memory) { + string[] memory cmds = new string[](5); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "cannonMemoryProof"; + cmds[3] = vm.toString(pc); + cmds[4] = vm.toString(insn); + bytes memory result = vm.ffi(cmds); + (bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes)); + return (memRoot, proof); + } + + function getCannonMemoryProof( + uint32 pc, + uint32 insn, + uint32 memAddr, + uint32 memVal + ) + external + returns (bytes32, bytes memory) + { + string[] memory cmds = new string[](7); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "cannonMemoryProof"; + cmds[3] = vm.toString(pc); + cmds[4] = vm.toString(insn); + cmds[5] = vm.toString(memAddr); + cmds[6] = vm.toString(memVal); + bytes memory result = vm.ffi(cmds); + (bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes)); + return (memRoot, proof); + } +} diff --git a/packages/contracts-bedrock/test/setup/Setup.sol b/packages/contracts-bedrock/test/setup/Setup.sol new file mode 100644 index 000000000000..2e4dae080c63 --- /dev/null +++ b/packages/contracts-bedrock/test/setup/Setup.sol @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { L2CrossDomainMessenger } from "src/L2/L2CrossDomainMessenger.sol"; +import { L2StandardBridge } from "src/L2/L2StandardBridge.sol"; +import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol"; +import { L2ERC721Bridge } from "src/L2/L2ERC721Bridge.sol"; +import { BaseFeeVault } from "src/L2/BaseFeeVault.sol"; +import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol"; +import { L1FeeVault } from "src/L2/L1FeeVault.sol"; +import { GasPriceOracle } from "src/L2/GasPriceOracle.sol"; +import { L1Block } from "src/L2/L1Block.sol"; +import { LegacyMessagePasser } from "src/legacy/LegacyMessagePasser.sol"; +import { GovernanceToken } from "src/governance/GovernanceToken.sol"; +import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; +import { LegacyERC20ETH } from "src/legacy/LegacyERC20ETH.sol"; +import { StandardBridge } from "src/universal/StandardBridge.sol"; +import { FeeVault } from "src/universal/FeeVault.sol"; +import { OptimismPortal } from "src/L1/OptimismPortal.sol"; +import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; +import { DeployConfig } from "scripts/DeployConfig.s.sol"; +import { Deploy } from "scripts/Deploy.s.sol"; +import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; +import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; +import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; +import { AddressManager } from "src/legacy/AddressManager.sol"; +import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; +import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; + +/// @title Setup +/// @dev This contact is responsible for setting up the contracts in state. It currently +/// sets the L2 contracts directly at the predeploy addresses instead of setting them +/// up behind proxies. In the future we will migrate to importing the genesis JSON +/// file that is created to set up the L2 contracts instead of setting them up manually. +contract Setup is Deploy { + OptimismPortal optimismPortal; + L2OutputOracle l2OutputOracle; + SystemConfig systemConfig; + L1StandardBridge l1StandardBridge; + L1CrossDomainMessenger l1CrossDomainMessenger; + AddressManager addressManager; + L1ERC721Bridge l1ERC721Bridge; + OptimismMintableERC20Factory l1OptimismMintableERC20Factory; + ProtocolVersions protocolVersions; + + L2CrossDomainMessenger l2CrossDomainMessenger = + L2CrossDomainMessenger(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER)); + L2StandardBridge l2StandardBridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)); + L2ToL1MessagePasser l2ToL1MessagePasser = L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)); + OptimismMintableERC20Factory l2OptimismMintableERC20Factory = + OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY); + L2ERC721Bridge l2ERC721Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE); + BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT)); + SequencerFeeVault sequencerFeeVault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET)); + L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT)); + GasPriceOracle gasPriceOracle = GasPriceOracle(Predeploys.GAS_PRICE_ORACLE); + L1Block l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES); + LegacyMessagePasser legacyMessagePasser = LegacyMessagePasser(Predeploys.LEGACY_MESSAGE_PASSER); + GovernanceToken governanceToken = GovernanceToken(Predeploys.GOVERNANCE_TOKEN); + LegacyERC20ETH legacyERC20ETH = LegacyERC20ETH(Predeploys.LEGACY_ERC20_ETH); + + function setUp() public virtual override { + Deploy.setUp(); + } + + /// @dev Sets up the L1 contracts. + function L1() public { + // Set the deterministic deployer in state to ensure that it is there + vm.etch( + 0x4e59b44847b379578588920cA78FbF26c0B4956C, + hex"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3" + ); + + Deploy.run(); + + optimismPortal = OptimismPortal(mustGetAddress("OptimismPortalProxy")); + l2OutputOracle = L2OutputOracle(mustGetAddress("L2OutputOracleProxy")); + systemConfig = SystemConfig(mustGetAddress("SystemConfigProxy")); + l1StandardBridge = L1StandardBridge(mustGetAddress("L1StandardBridgeProxy")); + l1CrossDomainMessenger = L1CrossDomainMessenger(mustGetAddress("L1CrossDomainMessengerProxy")); + addressManager = AddressManager(mustGetAddress("AddressManager")); + l1ERC721Bridge = L1ERC721Bridge(mustGetAddress("L1ERC721BridgeProxy")); + l1OptimismMintableERC20Factory = + OptimismMintableERC20Factory(mustGetAddress("OptimismMintableERC20FactoryProxy")); + protocolVersions = ProtocolVersions(mustGetAddress("ProtocolVersionsProxy")); + + vm.label(address(l2OutputOracle), "L2OutputOracle"); + vm.label(mustGetAddress("L2OutputOracleProxy"), "L2OutputOracleProxy"); + vm.label(address(optimismPortal), "OptimismPortal"); + vm.label(mustGetAddress("OptimismPortalProxy"), "OptimismPortalProxy"); + vm.label(address(systemConfig), "SystemConfig"); + vm.label(mustGetAddress("SystemConfigProxy"), "SystemConfigProxy"); + vm.label(address(l1StandardBridge), "L1StandardBridge"); + vm.label(mustGetAddress("L1StandardBridgeProxy"), "L1StandardBridgeProxy"); + vm.label(address(l1CrossDomainMessenger), "L1CrossDomainMessenger"); + vm.label(mustGetAddress("L1CrossDomainMessengerProxy"), "L1CrossDomainMessengerProxy"); + vm.label(address(addressManager), "AddressManager"); + vm.label(address(l1ERC721Bridge), "L1ERC721Bridge"); + vm.label(mustGetAddress("L1ERC721BridgeProxy"), "L1ERC721BridgeProxy"); + vm.label(address(l1OptimismMintableERC20Factory), "OptimismMintableERC20Factory"); + vm.label(mustGetAddress("OptimismMintableERC20FactoryProxy"), "OptimismMintableERC20FactoryProxy"); + vm.label(address(protocolVersions), "ProtocolVersions"); + vm.label(mustGetAddress("ProtocolVersionsProxy"), "ProtocolVersionsProxy"); + vm.label(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)), "L1CrossDomainMessenger_aliased"); + } + + /// @dev Sets up the L2 contracts. Depends on `L1()` being called first. + function L2(DeployConfig cfg) public { + // Set up L2. There are currently no proxies set in the L2 initialization. + vm.etch( + address(l2CrossDomainMessenger), address(new L2CrossDomainMessenger(address(l1CrossDomainMessenger))).code + ); + l2CrossDomainMessenger.initialize(); + + vm.etch(address(l2ToL1MessagePasser), address(new L2ToL1MessagePasser()).code); + + vm.etch( + address(l2StandardBridge), address(new L2StandardBridge(StandardBridge(payable(l1StandardBridge)))).code + ); + l2StandardBridge.initialize(); + + vm.etch(address(l2OptimismMintableERC20Factory), address(new OptimismMintableERC20Factory()).code); + l2OptimismMintableERC20Factory.initialize(address(l2StandardBridge)); + + vm.etch(address(legacyERC20ETH), address(new LegacyERC20ETH()).code); + + vm.etch(address(l2ERC721Bridge), address(new L2ERC721Bridge(address(l1ERC721Bridge))).code); + l2ERC721Bridge.initialize(); + + vm.etch( + address(sequencerFeeVault), + address( + new SequencerFeeVault(cfg.sequencerFeeVaultRecipient(), cfg.sequencerFeeVaultMinimumWithdrawalAmount(), FeeVault.WithdrawalNetwork.L2) + ).code + ); + vm.etch( + address(baseFeeVault), + address( + new BaseFeeVault(cfg.baseFeeVaultRecipient(), cfg.baseFeeVaultMinimumWithdrawalAmount(), FeeVault.WithdrawalNetwork.L1) + ).code + ); + vm.etch( + address(l1FeeVault), + address( + new L1FeeVault(cfg.l1FeeVaultRecipient(), cfg.l1FeeVaultMinimumWithdrawalAmount(), FeeVault.WithdrawalNetwork.L2) + ).code + ); + + vm.etch(address(l1Block), address(new L1Block()).code); + + vm.etch(address(gasPriceOracle), address(new GasPriceOracle()).code); + + vm.etch(address(legacyMessagePasser), address(new LegacyMessagePasser()).code); + + vm.etch(address(governanceToken), address(new GovernanceToken()).code); + // Set the ERC20 token name and symbol + vm.store( + address(governanceToken), + bytes32(uint256(3)), + bytes32(0x4f7074696d69736d000000000000000000000000000000000000000000000010) + ); + vm.store( + address(governanceToken), + bytes32(uint256(4)), + bytes32(0x4f50000000000000000000000000000000000000000000000000000000000004) + ); + + // Set the governance token's owner to be the final system owner + address finalSystemOwner = cfg.finalSystemOwner(); + vm.prank(governanceToken.owner()); + governanceToken.transferOwnership(finalSystemOwner); + + vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, "OptimismMintableERC20Factory"); + vm.label(Predeploys.LEGACY_ERC20_ETH, "LegacyERC20ETH"); + vm.label(Predeploys.L2_STANDARD_BRIDGE, "L2StandardBridge"); + vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L2CrossDomainMessenger"); + vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, "L2ToL1MessagePasser"); + vm.label(Predeploys.SEQUENCER_FEE_WALLET, "SequencerFeeVault"); + vm.label(Predeploys.L2_ERC721_BRIDGE, "L2ERC721Bridge"); + vm.label(Predeploys.BASE_FEE_VAULT, "BaseFeeVault"); + vm.label(Predeploys.L1_FEE_VAULT, "L1FeeVault"); + vm.label(Predeploys.L1_BLOCK_ATTRIBUTES, "L1Block"); + vm.label(Predeploys.GAS_PRICE_ORACLE, "GasPriceOracle"); + vm.label(Predeploys.LEGACY_MESSAGE_PASSER, "LegacyMessagePasser"); + vm.label(Predeploys.GOVERNANCE_TOKEN, "GovernanceToken"); + } +} diff --git a/packages/contracts-ts/package.json b/packages/contracts-ts/package.json index 9cd089f4c3fe..0873431b421d 100644 --- a/packages/contracts-ts/package.json +++ b/packages/contracts-ts/package.json @@ -54,7 +54,7 @@ "@vitest/coverage-istanbul": "^0.34.6", "@wagmi/cli": "^1.5.2", "@wagmi/core": "^1.4.5", - "abitype": "^0.10.1", + "abitype": "^0.10.2", "glob": "^10.3.10", "isomorphic-fetch": "^3.0.0", "jest-dom": "link:@types/@testing-library/jest-dom", @@ -82,6 +82,6 @@ "change-case": "4.1.2", "react": "^18.2.0", "react-dom": "^18.2.0", - "viem": "^1.18.0" + "viem": "^1.18.4" } } diff --git a/packages/fee-estimation/package.json b/packages/fee-estimation/package.json index 6cbc34b80625..25d229db84a6 100644 --- a/packages/fee-estimation/package.json +++ b/packages/fee-estimation/package.json @@ -38,13 +38,13 @@ "@testing-library/jest-dom": "^6.1.4", "@testing-library/react-hooks": "^8.0.1", "@vitest/coverage-istanbul": "^0.34.6", - "abitype": "^0.10.1", + "abitype": "^0.10.2", "isomorphic-fetch": "^3.0.0", "jest-dom": "link:@types/@testing-library/jest-dom", "jsdom": "^22.1.0", "tsup": "^7.2.0", "typescript": "^5.2.2", - "viem": "^1.18.0", + "viem": "^1.18.4", "vite": "^4.5.0", "vitest": "^0.34.2" }, diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 8588f45b2590..b1cd2122d1ce 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -48,15 +48,15 @@ "chai-as-promised": "^7.1.1", "ethereum-waffle": "^4.0.10", "ethers": "^5.7.2", - "hardhat": "^2.18.3", + "hardhat": "^2.19.0", "hardhat-deploy": "^0.11.43", "isomorphic-fetch": "^3.0.0", "mocha": "^10.2.0", "nyc": "^15.1.0", "ts-node": "^10.9.1", - "typedoc": "^0.25.2", + "typedoc": "^0.25.3", "typescript": "^5.2.2", - "viem": "^1.18.0", + "viem": "^1.18.4", "vitest": "^0.34.2", "zod": "^3.22.4" }, @@ -65,7 +65,7 @@ "@eth-optimism/contracts-bedrock": "workspace:*", "@eth-optimism/core-utils": "workspace:*", "lodash": "^4.17.21", - "merkletreejs": "^0.3.10", + "merkletreejs": "^0.3.11", "rlp": "^2.2.7" }, "peerDependencies": { diff --git a/packages/web3js-plugin/package.json b/packages/web3js-plugin/package.json index d64bbb6179b0..5743c09969ab 100644 --- a/packages/web3js-plugin/package.json +++ b/packages/web3js-plugin/package.json @@ -37,13 +37,13 @@ "@vitest/coverage-istanbul": "^0.34.6", "tsup": "^7.2.0", "typescript": "^5.2.2", - "viem": "^1.18.0", + "viem": "^1.18.4", "vite": "^4.5.0", "vitest": "^0.34.1", "zod": "^3.22.4" }, "dependencies": { - "@ethereumjs/rlp": "^5.0.0", + "@ethereumjs/rlp": "^5.0.1", "web3-eth": "^4.0.3", "web3-eth-accounts": "^4.0.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d22a34b39e22..91d29d94158a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,11 +39,11 @@ importers: specifier: ^20.8.9 version: 20.8.9 '@typescript-eslint/eslint-plugin': - specifier: ^6.9.0 - version: 6.9.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0)(typescript@5.2.2) + specifier: ^6.9.1 + version: 6.9.1(@typescript-eslint/parser@6.9.1)(eslint@8.52.0)(typescript@5.2.2) '@typescript-eslint/parser': - specifier: ^6.9.0 - version: 6.9.0(eslint@8.52.0)(typescript@5.2.2) + specifier: ^6.9.1 + version: 6.9.1(eslint@8.52.0)(typescript@5.2.2) chai: specifier: ^4.3.10 version: 4.3.10 @@ -64,7 +64,7 @@ importers: version: 16.0.3(eslint-plugin-import@2.29.0)(eslint-plugin-node@11.1.0)(eslint-plugin-promise@5.2.0)(eslint@8.52.0) eslint-plugin-import: specifier: ^2.29.0 - version: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0) + version: 2.29.0(@typescript-eslint/parser@6.9.1)(eslint@8.52.0) eslint-plugin-jsdoc: specifier: ^35.1.2 version: 35.5.1(eslint@8.52.0) @@ -84,8 +84,8 @@ importers: specifier: ^7.24.0 version: 7.33.2(eslint@8.52.0) eslint-plugin-unicorn: - specifier: ^48.0.1 - version: 48.0.1(eslint@8.52.0) + specifier: ^49.0.0 + version: 49.0.0(eslint@8.52.0) husky: specifier: ^8.0.3 version: 8.0.3 @@ -180,13 +180,13 @@ importers: version: 5.7.0 '@nomiclabs/hardhat-ethers': specifier: ^2.2.3 - version: 2.2.3(ethers@5.7.2)(hardhat@2.18.3) + version: 2.2.3(ethers@5.7.2)(hardhat@2.19.0) '@nomiclabs/hardhat-waffle': specifier: ^2.0.6 - version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.5)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.18.3) + version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.5)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.19.0) hardhat: - specifier: ^2.18.3 - version: 2.18.3(ts-node@10.9.1)(typescript@5.2.2) + specifier: ^2.19.0 + version: 2.19.0(ts-node@10.9.1)(typescript@5.2.2) ts-node: specifier: ^10.9.1 version: 10.9.1(@types/node@20.8.9)(typescript@5.2.2) @@ -200,8 +200,8 @@ importers: specifier: workspace:* version: link:../core-utils '@sentry/node': - specifier: ^7.75.0 - version: 7.75.0 + specifier: ^7.77.0 + version: 7.77.0 bcfg: specifier: ^0.2.1 version: 0.2.1 @@ -297,11 +297,11 @@ importers: specifier: ^2.0.0 version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.5)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.17.3) '@typescript-eslint/eslint-plugin': - specifier: ^6.9.0 - version: 6.9.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0)(typescript@5.2.2) + specifier: ^6.9.1 + version: 6.9.1(@typescript-eslint/parser@6.9.1)(eslint@8.52.0)(typescript@5.2.2) '@typescript-eslint/parser': - specifier: ^6.9.0 - version: 6.9.0(eslint@8.52.0)(typescript@5.2.2) + specifier: ^6.9.1 + version: 6.9.1(eslint@8.52.0)(typescript@5.2.2) bip39: specifier: ^3.0.4 version: 3.0.4 @@ -345,11 +345,11 @@ importers: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) viem: - specifier: ^1.18.0 - version: 1.18.0(typescript@5.2.2)(zod@3.22.4) + specifier: ^1.18.4 + version: 1.18.4(typescript@5.2.2)(zod@3.22.4) wagmi: specifier: '>1.0.0' - version: 1.0.1(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2)(viem@1.18.0) + version: 1.0.1(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2)(viem@1.18.4) devDependencies: '@eth-optimism/contracts-bedrock': specifier: workspace:* @@ -371,10 +371,10 @@ importers: version: 1.5.2(@wagmi/core@1.4.5)(typescript@5.2.2)(wagmi@1.0.1) '@wagmi/core': specifier: ^1.4.5 - version: 1.4.5(react@18.2.0)(typescript@5.2.2)(viem@1.18.0) + version: 1.4.5(react@18.2.0)(typescript@5.2.2)(viem@1.18.4) abitype: - specifier: ^0.10.1 - version: 0.10.1(typescript@5.2.2) + specifier: ^0.10.2 + version: 0.10.2(typescript@5.2.2) glob: specifier: ^10.3.10 version: 10.3.10 @@ -467,8 +467,8 @@ importers: specifier: ^0.34.6 version: 0.34.6(vitest@0.34.2) abitype: - specifier: ^0.10.1 - version: 0.10.1(typescript@5.2.2) + specifier: ^0.10.2 + version: 0.10.2(typescript@5.2.2) isomorphic-fetch: specifier: ^3.0.0 version: 3.0.0 @@ -485,8 +485,8 @@ importers: specifier: ^5.2.2 version: 5.2.2 viem: - specifier: ^1.18.0 - version: 1.18.0(typescript@5.2.2)(zod@3.22.4) + specifier: ^1.18.4 + version: 1.18.4(typescript@5.2.2)(zod@3.22.4) vite: specifier: ^4.5.0 version: 4.5.0(@types/node@20.8.9) @@ -509,8 +509,8 @@ importers: specifier: ^4.17.21 version: 4.17.21 merkletreejs: - specifier: ^0.3.10 - version: 0.3.10 + specifier: ^0.3.11 + version: 0.3.11 rlp: specifier: ^2.2.7 version: 2.2.7 @@ -526,10 +526,10 @@ importers: version: 5.7.0 '@nomiclabs/hardhat-ethers': specifier: ^2.2.3 - version: 2.2.3(ethers@5.7.2)(hardhat@2.18.3) + version: 2.2.3(ethers@5.7.2)(hardhat@2.19.0) '@nomiclabs/hardhat-waffle': specifier: ^2.0.1 - version: 2.0.1(@nomiclabs/hardhat-ethers@2.2.3)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.18.3) + version: 2.0.1(@nomiclabs/hardhat-ethers@2.2.3)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.19.0) '@types/chai': specifier: ^4.3.8 version: 4.3.8 @@ -552,8 +552,8 @@ importers: specifier: ^5.7.2 version: 5.7.2 hardhat: - specifier: ^2.18.3 - version: 2.18.3(ts-node@10.9.1)(typescript@5.2.2) + specifier: ^2.19.0 + version: 2.19.0(ts-node@10.9.1)(typescript@5.2.2) hardhat-deploy: specifier: ^0.11.43 version: 0.11.43 @@ -570,14 +570,14 @@ importers: specifier: ^10.9.1 version: 10.9.1(@types/node@20.8.9)(typescript@5.2.2) typedoc: - specifier: ^0.25.2 - version: 0.25.2(typescript@5.2.2) + specifier: ^0.25.3 + version: 0.25.3(typescript@5.2.2) typescript: specifier: ^5.2.2 version: 5.2.2 viem: - specifier: ^1.18.0 - version: 1.18.0(typescript@5.2.2)(zod@3.22.4) + specifier: ^1.18.4 + version: 1.18.4(typescript@5.2.2)(zod@3.22.4) vitest: specifier: ^0.34.2 version: 0.34.2(jsdom@22.1.0) @@ -588,8 +588,8 @@ importers: packages/web3js-plugin: dependencies: '@ethereumjs/rlp': - specifier: ^5.0.0 - version: 5.0.0 + specifier: ^5.0.1 + version: 5.0.1 web3: specifier: '>= 4.0.3 < 5.x' version: 4.0.3 @@ -616,8 +616,8 @@ importers: specifier: ^5.2.2 version: 5.2.2 viem: - specifier: ^1.18.0 - version: 1.18.0(typescript@5.2.2)(zod@3.22.4) + specifier: ^1.18.4 + version: 1.18.4(typescript@5.2.2)(zod@3.22.4) vite: specifier: ^4.5.0 version: 4.5.0(@types/node@20.8.9) @@ -650,20 +650,12 @@ packages: '@jridgewell/trace-mapping': 0.3.19 dev: true - /@babel/code-frame@7.22.10: - resolution: {integrity: sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.22.10 - chalk: 2.4.2 - /@babel/code-frame@7.22.13: resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} engines: {node: '>=6.9.0'} dependencies: '@babel/highlight': 7.22.20 chalk: 2.4.2 - dev: true /@babel/compat-data@7.22.9: resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} @@ -675,7 +667,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.22.10 + '@babel/code-frame': 7.22.13 '@babel/generator': 7.22.10 '@babel/helper-compilation-targets': 7.22.10 '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.10) @@ -789,7 +781,7 @@ packages: '@babel/helper-module-imports': 7.22.5 '@babel/helper-simple-access': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 dev: true /@babel/helper-simple-access@7.22.5: @@ -814,11 +806,6 @@ packages: /@babel/helper-validator-identifier@7.22.20: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.22.5: - resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} - engines: {node: '>=6.9.0'} /@babel/helper-validator-option@7.22.5: resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==} @@ -836,14 +823,6 @@ packages: - supports-color dev: true - /@babel/highlight@7.22.10: - resolution: {integrity: sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.5 - chalk: 2.4.2 - js-tokens: 4.0.0 - /@babel/highlight@7.22.20: resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} engines: {node: '>=6.9.0'} @@ -851,7 +830,6 @@ packages: '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 js-tokens: 4.0.0 - dev: true /@babel/parser@7.22.10: resolution: {integrity: sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==} @@ -895,7 +873,7 @@ packages: resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.22.10 + '@babel/code-frame': 7.22.13 '@babel/parser': 7.22.10 '@babel/types': 7.22.10 dev: true @@ -904,7 +882,7 @@ packages: resolution: {integrity: sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.22.10 + '@babel/code-frame': 7.22.13 '@babel/generator': 7.22.10 '@babel/helper-environment-visitor': 7.22.5 '@babel/helper-function-name': 7.22.5 @@ -941,7 +919,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/helper-string-parser': 7.22.5 - '@babel/helper-validator-identifier': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 dev: true @@ -2161,8 +2139,8 @@ packages: engines: {node: '>=14'} hasBin: true - /@ethereumjs/rlp@5.0.0: - resolution: {integrity: sha512-WuS1l7GJmB0n0HsXLozCoEFc9IwYgf3l0gCkKVYgR67puVF1O4OpEaN0hWmm1c+iHUHFCKt1hJrvy5toLg+6ag==} + /@ethereumjs/rlp@5.0.1: + resolution: {integrity: sha512-Ab/Hfzz+T9Zl+65Nkg+9xAmwKPLicsnQ4NW49pgvJp9ovefuic95cgOS9CbPc9izIEgsqm1UitV0uNveCvud9w==} engines: {node: '>=18'} hasBin: true dev: false @@ -3168,17 +3146,17 @@ packages: hardhat: 2.17.3(typescript@5.2.2) dev: true - /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.18.3): + /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.19.0): resolution: {integrity: sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==} peerDependencies: ethers: ^5.0.0 hardhat: ^2.0.0 dependencies: ethers: 5.7.2 - hardhat: 2.18.3(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.0(ts-node@10.9.1)(typescript@5.2.2) dev: true - /@nomiclabs/hardhat-waffle@2.0.1(@nomiclabs/hardhat-ethers@2.2.3)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.18.3): + /@nomiclabs/hardhat-waffle@2.0.1(@nomiclabs/hardhat-ethers@2.2.3)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.19.0): resolution: {integrity: sha512-2YR2V5zTiztSH9n8BYWgtv3Q+EL0N5Ltm1PAr5z20uAY4SkkfylJ98CIqt18XFvxTD5x4K2wKBzddjV9ViDAZQ==} peerDependencies: '@nomiclabs/hardhat-ethers': ^2.0.0 @@ -3186,12 +3164,12 @@ packages: ethers: ^5.0.0 hardhat: ^2.0.0 dependencies: - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.18.3) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.0) '@types/sinon-chai': 3.2.5 '@types/web3': 1.0.19 ethereum-waffle: 4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.2.2) ethers: 5.7.2 - hardhat: 2.18.3(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.0(ts-node@10.9.1)(typescript@5.2.2) dev: true /@nomiclabs/hardhat-waffle@2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.5)(ethereum-waffle@3.4.4)(ethers@5.7.2)(hardhat@2.17.3): @@ -3210,7 +3188,7 @@ packages: hardhat: 2.17.3(typescript@5.2.2) dev: true - /@nomiclabs/hardhat-waffle@2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.5)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.18.3): + /@nomiclabs/hardhat-waffle@2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.5)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.19.0): resolution: {integrity: sha512-+Wz0hwmJGSI17B+BhU/qFRZ1l6/xMW82QGXE/Gi+WTmwgJrQefuBs1lIf7hzQ1hLk6hpkvb/zwcNkpVKRYTQYg==} peerDependencies: '@nomiclabs/hardhat-ethers': ^2.0.0 @@ -3219,11 +3197,11 @@ packages: ethers: ^5.0.0 hardhat: ^2.0.0 dependencies: - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.18.3) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.0) '@types/sinon-chai': 3.2.5 ethereum-waffle: 4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.2.2) ethers: 5.7.2 - hardhat: 2.18.3(ts-node@10.9.1)(typescript@5.2.2) + hardhat: 2.19.0(ts-node@10.9.1)(typescript@5.2.2) dev: true /@nrwl/nx-cloud@16.5.2: @@ -3434,7 +3412,7 @@ packages: resolution: {integrity: sha512-gYw0ki/EAuV1oSyMxpqandHjnthZjYYy+YWpTAzf8BqfXM3ItcZLpjxfg+3+mXW8HIO+3jw6T9iiqEXsqHaMMw==} dependencies: '@safe-global/safe-gateway-typescript-sdk': 3.7.3 - viem: 1.18.0(typescript@5.2.2)(zod@3.22.4) + viem: 1.18.4(typescript@5.2.2)(zod@3.22.4) transitivePeerDependencies: - bufferutil - encoding @@ -3488,13 +3466,13 @@ packages: '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 - /@sentry-internal/tracing@7.75.0: - resolution: {integrity: sha512-/j4opF/jB9j8qnSiQK75/lFLtkfqXS5/MoOKc2KWK/pOaf15W+6uJzGQ8jRBHLYd9dDg6AyqsF48Wqy561/mNg==} + /@sentry-internal/tracing@7.77.0: + resolution: {integrity: sha512-8HRF1rdqWwtINqGEdx8Iqs9UOP/n8E0vXUu3Nmbqj4p5sQPA7vvCfq+4Y4rTqZFc7sNdFpDsRION5iQEh8zfZw==} engines: {node: '>=8'} dependencies: - '@sentry/core': 7.75.0 - '@sentry/types': 7.75.0 - '@sentry/utils': 7.75.0 + '@sentry/core': 7.77.0 + '@sentry/types': 7.77.0 + '@sentry/utils': 7.77.0 dev: false /@sentry/core@5.30.0: @@ -3508,12 +3486,12 @@ packages: tslib: 1.14.1 dev: true - /@sentry/core@7.75.0: - resolution: {integrity: sha512-vXg3cdJgwzP24oTS9zFCgLW4MgTkMZqXx+ESRq7gTD9qJTpcmAmYT+Ckmvebg8K6DBThV6+0v61r50na2+XdrA==} + /@sentry/core@7.77.0: + resolution: {integrity: sha512-Tj8oTYFZ/ZD+xW8IGIsU6gcFXD/gfE+FUxUaeSosd9KHwBQNOLhZSsYo/tTVf/rnQI/dQnsd4onPZLiL+27aTg==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.75.0 - '@sentry/utils': 7.75.0 + '@sentry/types': 7.77.0 + '@sentry/utils': 7.77.0 dev: false /@sentry/hub@5.30.0: @@ -3551,14 +3529,14 @@ packages: - supports-color dev: true - /@sentry/node@7.75.0: - resolution: {integrity: sha512-z5Xanf9QeTd4YrEuZiJfvtAy2C874Zg4KpurEo3okJ8uYjnbXMsQ3EwVHbKEoYSwE3ExTrqOggPfk2NNSJIECA==} + /@sentry/node@7.77.0: + resolution: {integrity: sha512-Ob5tgaJOj0OYMwnocc6G/CDLWC7hXfVvKX/ofkF98+BbN/tQa5poL+OwgFn9BA8ud8xKzyGPxGU6LdZ8Oh3z/g==} engines: {node: '>=8'} dependencies: - '@sentry-internal/tracing': 7.75.0 - '@sentry/core': 7.75.0 - '@sentry/types': 7.75.0 - '@sentry/utils': 7.75.0 + '@sentry-internal/tracing': 7.77.0 + '@sentry/core': 7.77.0 + '@sentry/types': 7.77.0 + '@sentry/utils': 7.77.0 https-proxy-agent: 5.0.1 transitivePeerDependencies: - supports-color @@ -3580,8 +3558,8 @@ packages: engines: {node: '>=6'} dev: true - /@sentry/types@7.75.0: - resolution: {integrity: sha512-xG8OLADxG7HpGhMxrF4v4tKq/v/gqmLsTZ858R51pz0xCWM8SK6ZSWOKudkAGBIpRjI6RUHMnkBtRAN2aKDOkQ==} + /@sentry/types@7.77.0: + resolution: {integrity: sha512-nfb00XRJVi0QpDHg+JkqrmEBHsqBnxJu191Ded+Cs1OJ5oPXEW6F59LVcBScGvMqe+WEk1a73eH8XezwfgrTsA==} engines: {node: '>=8'} dev: false @@ -3593,11 +3571,11 @@ packages: tslib: 1.14.1 dev: true - /@sentry/utils@7.75.0: - resolution: {integrity: sha512-UHWKeevhUNRp+mAWDbMVFOMgseoq8t/xFgdUywO/2PC14qZKRBH+0k1BKoNkp5sOzDT06ETj2w6wYoYhy6i+dA==} + /@sentry/utils@7.77.0: + resolution: {integrity: sha512-NmM2kDOqVchrey3N5WSzdQoCsyDkQkiRxExPaNI2oKQ/jMWHs9yt0tSy7otPBcXs0AP59ihl75Bvm1tDRcsp5g==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.75.0 + '@sentry/types': 7.77.0 dev: false /@sinclair/typebox@0.27.8: @@ -3947,7 +3925,7 @@ packages: resolution: {integrity: sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==} engines: {node: '>=14'} dependencies: - '@babel/code-frame': 7.22.10 + '@babel/code-frame': 7.22.13 '@babel/runtime': 7.22.6 '@types/aria-query': 5.0.1 aria-query: 5.1.3 @@ -4519,8 +4497,8 @@ packages: '@types/node': 20.8.9 dev: false - /@typescript-eslint/eslint-plugin@6.9.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0)(typescript@5.2.2): - resolution: {integrity: sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==} + /@typescript-eslint/eslint-plugin@6.9.1(@typescript-eslint/parser@6.9.1)(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -4531,11 +4509,11 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.6.2 - '@typescript-eslint/parser': 6.9.0(eslint@8.52.0)(typescript@5.2.2) - '@typescript-eslint/scope-manager': 6.9.0 - '@typescript-eslint/type-utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2) - '@typescript-eslint/utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.9.0 + '@typescript-eslint/parser': 6.9.1(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/scope-manager': 6.9.1 + '@typescript-eslint/type-utils': 6.9.1(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/utils': 6.9.1(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.9.1 debug: 4.3.4(supports-color@8.1.1) eslint: 8.52.0 graphemer: 1.4.0 @@ -4548,8 +4526,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@6.9.0(eslint@8.52.0)(typescript@5.2.2): - resolution: {integrity: sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==} + /@typescript-eslint/parser@6.9.1(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -4558,10 +4536,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.9.0 - '@typescript-eslint/types': 6.9.0 - '@typescript-eslint/typescript-estree': 6.9.0(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.9.0 + '@typescript-eslint/scope-manager': 6.9.1 + '@typescript-eslint/types': 6.9.1 + '@typescript-eslint/typescript-estree': 6.9.1(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.9.1 debug: 4.3.4(supports-color@8.1.1) eslint: 8.52.0 typescript: 5.2.2 @@ -4569,16 +4547,16 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@6.9.0: - resolution: {integrity: sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==} + /@typescript-eslint/scope-manager@6.9.1: + resolution: {integrity: sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.9.0 - '@typescript-eslint/visitor-keys': 6.9.0 + '@typescript-eslint/types': 6.9.1 + '@typescript-eslint/visitor-keys': 6.9.1 dev: true - /@typescript-eslint/type-utils@6.9.0(eslint@8.52.0)(typescript@5.2.2): - resolution: {integrity: sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==} + /@typescript-eslint/type-utils@6.9.1(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -4587,8 +4565,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.9.0(typescript@5.2.2) - '@typescript-eslint/utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 6.9.1(typescript@5.2.2) + '@typescript-eslint/utils': 6.9.1(eslint@8.52.0)(typescript@5.2.2) debug: 4.3.4(supports-color@8.1.1) eslint: 8.52.0 ts-api-utils: 1.0.1(typescript@5.2.2) @@ -4597,13 +4575,13 @@ packages: - supports-color dev: true - /@typescript-eslint/types@6.9.0: - resolution: {integrity: sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==} + /@typescript-eslint/types@6.9.1: + resolution: {integrity: sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.9.0(typescript@5.2.2): - resolution: {integrity: sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==} + /@typescript-eslint/typescript-estree@6.9.1(typescript@5.2.2): + resolution: {integrity: sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -4611,8 +4589,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.9.0 - '@typescript-eslint/visitor-keys': 6.9.0 + '@typescript-eslint/types': 6.9.1 + '@typescript-eslint/visitor-keys': 6.9.1 debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 @@ -4623,8 +4601,8 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@6.9.0(eslint@8.52.0)(typescript@5.2.2): - resolution: {integrity: sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==} + /@typescript-eslint/utils@6.9.1(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -4632,9 +4610,9 @@ packages: '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 6.9.0 - '@typescript-eslint/types': 6.9.0 - '@typescript-eslint/typescript-estree': 6.9.0(typescript@5.2.2) + '@typescript-eslint/scope-manager': 6.9.1 + '@typescript-eslint/types': 6.9.1 + '@typescript-eslint/typescript-estree': 6.9.1(typescript@5.2.2) eslint: 8.52.0 semver: 7.5.4 transitivePeerDependencies: @@ -4642,11 +4620,11 @@ packages: - typescript dev: true - /@typescript-eslint/visitor-keys@6.9.0: - resolution: {integrity: sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==} + /@typescript-eslint/visitor-keys@6.9.1: + resolution: {integrity: sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.9.0 + '@typescript-eslint/types': 6.9.1 eslint-visitor-keys: 3.4.3 dev: true @@ -4880,7 +4858,7 @@ packages: wagmi: optional: true dependencies: - '@wagmi/core': 1.4.5(react@18.2.0)(typescript@5.2.2)(viem@1.18.0) + '@wagmi/core': 1.4.5(react@18.2.0)(typescript@5.2.2)(viem@1.18.4) abitype: 0.8.7(typescript@5.2.2)(zod@3.22.3) abort-controller: 3.0.0 bundle-require: 3.1.2(esbuild@0.16.17) @@ -4902,15 +4880,15 @@ packages: picocolors: 1.0.0 prettier: 2.8.8 typescript: 5.2.2 - viem: 1.18.0(typescript@5.2.2)(zod@3.22.3) - wagmi: 1.0.1(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2)(viem@1.18.0) + viem: 1.18.4(typescript@5.2.2)(zod@3.22.3) + wagmi: 1.0.1(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2)(viem@1.18.4) zod: 3.22.3 transitivePeerDependencies: - bufferutil - utf-8-validate dev: true - /@wagmi/connectors@1.0.1(@wagmi/chains@0.2.22)(react@18.2.0)(typescript@5.2.2)(viem@1.18.0): + /@wagmi/connectors@1.0.1(@wagmi/chains@0.2.22)(react@18.2.0)(typescript@5.2.2)(viem@1.18.4): resolution: {integrity: sha512-fl01vym19DE1uoE+MlASw5zo3Orr/YXlJRjOKLaKYtV+Q7jOLY4TwHgq7sEMs+JYOvFICFBEAlWNNxidr51AqQ==} peerDependencies: '@wagmi/chains': '>=0.2.0' @@ -4933,7 +4911,7 @@ packages: abitype: 0.8.1(typescript@5.2.2) eventemitter3: 4.0.7 typescript: 5.2.2 - viem: 1.18.0(typescript@5.2.2)(zod@3.22.4) + viem: 1.18.4(typescript@5.2.2)(zod@3.22.4) transitivePeerDependencies: - '@react-native-async-storage/async-storage' - bufferutil @@ -4945,7 +4923,7 @@ packages: - utf-8-validate - zod - /@wagmi/connectors@3.1.3(react@18.2.0)(typescript@5.2.2)(viem@1.18.0): + /@wagmi/connectors@3.1.3(react@18.2.0)(typescript@5.2.2)(viem@1.18.4): resolution: {integrity: sha512-UgwsQKQDFObJVJMf9pDfFoXTv710o4zrTHyhIWKBTMMkLpCMsMxN5+ZaDhBYt/BgoRinfRYQo8uwuwLhxE6Log==} peerDependencies: typescript: '>=5.0.4' @@ -4965,7 +4943,7 @@ packages: abitype: 0.8.7(typescript@5.2.2)(zod@3.22.3) eventemitter3: 4.0.7 typescript: 5.2.2 - viem: 1.18.0(typescript@5.2.2)(zod@3.22.4) + viem: 1.18.4(typescript@5.2.2)(zod@3.22.4) transitivePeerDependencies: - '@react-native-async-storage/async-storage' - '@types/react' @@ -4978,7 +4956,7 @@ packages: - zod dev: true - /@wagmi/core@1.0.1(react@18.2.0)(typescript@5.2.2)(viem@1.18.0): + /@wagmi/core@1.0.1(react@18.2.0)(typescript@5.2.2)(viem@1.18.4): resolution: {integrity: sha512-Zzg4Ob92QMF9NsC+z5/8JZjMn3NCCnwVWGJlv79qRX9mp5Ku40OzJNvqDnjcSGjshe6H0L/KtFZAqTlmu8lT7w==} peerDependencies: typescript: '>=4.9.4' @@ -4988,11 +4966,11 @@ packages: optional: true dependencies: '@wagmi/chains': 0.2.22(typescript@5.2.2) - '@wagmi/connectors': 1.0.1(@wagmi/chains@0.2.22)(react@18.2.0)(typescript@5.2.2)(viem@1.18.0) + '@wagmi/connectors': 1.0.1(@wagmi/chains@0.2.22)(react@18.2.0)(typescript@5.2.2)(viem@1.18.4) abitype: 0.8.1(typescript@5.2.2) eventemitter3: 4.0.7 typescript: 5.2.2 - viem: 1.18.0(typescript@5.2.2)(zod@3.22.4) + viem: 1.18.4(typescript@5.2.2)(zod@3.22.4) zustand: 4.3.9(react@18.2.0) transitivePeerDependencies: - '@react-native-async-storage/async-storage' @@ -5006,7 +4984,7 @@ packages: - utf-8-validate - zod - /@wagmi/core@1.4.5(react@18.2.0)(typescript@5.2.2)(viem@1.18.0): + /@wagmi/core@1.4.5(react@18.2.0)(typescript@5.2.2)(viem@1.18.4): resolution: {integrity: sha512-N9luRb1Uk4tBN9kaYcQSWKE9AsRt/rvZaFt5IZech4JPzNN2sQlfhKd9GEjOXYRDqEPHdDvos7qyBKiDNTz4GA==} peerDependencies: typescript: '>=5.0.4' @@ -5015,11 +4993,11 @@ packages: typescript: optional: true dependencies: - '@wagmi/connectors': 3.1.3(react@18.2.0)(typescript@5.2.2)(viem@1.18.0) + '@wagmi/connectors': 3.1.3(react@18.2.0)(typescript@5.2.2)(viem@1.18.4) abitype: 0.8.7(typescript@5.2.2)(zod@3.22.3) eventemitter3: 4.0.7 typescript: 5.2.2 - viem: 1.18.0(typescript@5.2.2)(zod@3.22.4) + viem: 1.18.4(typescript@5.2.2)(zod@3.22.4) zustand: 4.3.9(react@18.2.0) transitivePeerDependencies: - '@react-native-async-storage/async-storage' @@ -5567,8 +5545,8 @@ packages: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} dev: true - /abitype@0.10.1(typescript@5.2.2): - resolution: {integrity: sha512-nFx5F2RniXGXw2Ci1uu6iDGnP/z3hW+H65G7cxrs5JDF3Ot9GuYkBJCRAB9EZ5QIi3dNByZaCrGFUn8LLkLQbw==} + /abitype@0.10.2(typescript@5.2.2): + resolution: {integrity: sha512-1XndI+RKFWK4+TXCNv1683MRyX5NGmlHXCvqzjOqhSS3PQrxT2QYRZq1bMPPRNjn89B3eVaM2w7y3jVj/OIUzA==} peerDependencies: typescript: '>=5.0.4' zod: ^3 >=3.22.0 @@ -7266,7 +7244,7 @@ packages: /call-bind@1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: - function-bind: 1.1.1 + function-bind: 1.1.2 get-intrinsic: 1.2.1 /callsite@1.0.0: @@ -7986,8 +7964,8 @@ packages: dev: true optional: true - /crypto-js@3.3.0: - resolution: {integrity: sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==} + /crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} dev: false /css.escape@1.5.1: @@ -8765,7 +8743,7 @@ packages: define-properties: 1.2.0 es-abstract: 1.22.1 es-set-tostringtag: 2.0.1 - function-bind: 1.1.1 + function-bind: 1.1.2 get-intrinsic: 1.2.1 globalthis: 1.0.3 has-property-descriptors: 1.0.0 @@ -8958,7 +8936,7 @@ packages: eslint-plugin-promise: ^4.2.1 || ^5.0.0 dependencies: eslint: 8.52.0 - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.1)(eslint@8.52.0) eslint-plugin-node: 11.1.0(eslint@8.52.0) eslint-plugin-promise: 5.2.0(eslint@8.52.0) dev: true @@ -8968,12 +8946,12 @@ packages: dependencies: debug: 3.2.7 is-core-module: 2.13.1 - resolve: 1.22.8 + resolve: 1.22.4 transitivePeerDependencies: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-node@0.3.9)(eslint@8.52.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.9.1)(eslint-import-resolver-node@0.3.9)(eslint@8.52.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -8994,7 +8972,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.9.1(eslint@8.52.0)(typescript@5.2.2) debug: 3.2.7 eslint: 8.52.0 eslint-import-resolver-node: 0.3.9 @@ -9013,7 +8991,7 @@ packages: regexpp: 3.2.0 dev: true - /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0): + /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.9.1)(eslint@8.52.0): resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} engines: {node: '>=4'} peerDependencies: @@ -9023,7 +9001,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.9.1(eslint@8.52.0)(typescript@5.2.2) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -9032,7 +9010,7 @@ packages: doctrine: 2.1.0 eslint: 8.52.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-node@0.3.9)(eslint@8.52.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.9.1)(eslint-import-resolver-node@0.3.9)(eslint@8.52.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -9142,13 +9120,13 @@ packages: string.prototype.matchall: 4.0.8 dev: true - /eslint-plugin-unicorn@48.0.1(eslint@8.52.0): - resolution: {integrity: sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==} + /eslint-plugin-unicorn@49.0.0(eslint@8.52.0): + resolution: {integrity: sha512-0fHEa/8Pih5cmzFW5L7xMEfUTvI9WKeQtjmKpTUmY+BiFCDxkxrTdnURJOHKykhtwIeyYsxnecbGvDCml++z4Q==} engines: {node: '>=16'} peerDependencies: - eslint: '>=8.44.0' + eslint: '>=8.52.0' dependencies: - '@babel/helper-validator-identifier': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) ci-info: 3.8.0 clean-regexp: 1.0.0 @@ -9157,7 +9135,6 @@ packages: indent-string: 4.0.0 is-builtin-module: 3.2.1 jsesc: 3.0.2 - lodash: 4.17.21 pluralize: 8.0.0 read-pkg-up: 7.0.1 regexp-tree: 0.1.27 @@ -10490,9 +10467,6 @@ packages: dev: true optional: true - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -10613,7 +10587,7 @@ packages: /get-intrinsic@1.2.1: resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} dependencies: - function-bind: 1.1.1 + function-bind: 1.1.2 has: 1.0.3 has-proto: 1.0.1 has-symbols: 1.0.3 @@ -11007,8 +10981,8 @@ packages: - utf-8-validate dev: true - /hardhat@2.18.3(ts-node@10.9.1)(typescript@5.2.2): - resolution: {integrity: sha512-JuYaTG+4ZHVjEHCW5Hn6jCHH3LpO75dtgznZpM/dLv12RcSlw/xHbeQh3FAsGahQr1epKryZcZEMHvztVZHe0g==} + /hardhat@2.19.0(ts-node@10.9.1)(typescript@5.2.2): + resolution: {integrity: sha512-kMpwovOEfrFRQXEopCP+JTcKVwSYVj8rnXE0LynxDqnh06yvyKCQknmXL6IVYTHQL6Csysc/yNbCHQbjSeJGpA==} hasBin: true peerDependencies: ts-node: '*' @@ -11152,7 +11126,7 @@ packages: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} dependencies: - function-bind: 1.1.1 + function-bind: 1.1.2 /hash-base@3.1.0: resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} @@ -13304,13 +13278,13 @@ packages: semaphore-async-await: 1.5.1 dev: true - /merkletreejs@0.3.10: - resolution: {integrity: sha512-lin42tKfRdkW+6iE5pjtQ9BnH+1Hk3sJ5Fn9hUUSjcXRcJbSISHgPCfYvMNEXiNqZPhz/TyRPEV30qgnujsQ7A==} + /merkletreejs@0.3.11: + resolution: {integrity: sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ==} engines: {node: '>= 7.6.0'} dependencies: bignumber.js: 9.0.1 buffer-reverse: 1.0.1 - crypto-js: 3.3.0 + crypto-js: 4.2.0 treeify: 1.1.0 web3-utils: 1.10.1 dev: false @@ -13946,7 +13920,7 @@ packages: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: hosted-git-info: 2.8.9 - resolve: 1.22.8 + resolve: 1.22.4 semver: 5.7.2 validate-npm-package-license: 3.0.4 @@ -14539,7 +14513,7 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.22.10 + '@babel/code-frame': 7.22.13 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -14631,7 +14605,7 @@ packages: semver: 7.5.4 slash: 2.0.0 tmp: 0.0.33 - yaml: 2.3.3 + yaml: 2.3.1 dev: true /path-browserify@1.0.1: @@ -14799,7 +14773,7 @@ packages: engines: {node: '>=10'} hasBin: true dependencies: - '@sentry/node': 7.75.0 + '@sentry/node': 7.77.0 commander: 2.20.3 pumpify: 2.0.1 split2: 3.2.2 @@ -14898,7 +14872,7 @@ packages: optional: true dependencies: lilconfig: 2.1.0 - yaml: 2.3.3 + yaml: 2.3.2 dev: true /postcss@8.4.27: @@ -15707,7 +15681,7 @@ packages: resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} hasBin: true dependencies: - is-core-module: 2.13.0 + is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 dev: true @@ -15719,7 +15693,6 @@ packages: is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: true /resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} @@ -15728,12 +15701,13 @@ packages: is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + dev: true /resolve@2.0.0-next.4: resolution: {integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==} hasBin: true dependencies: - is-core-module: 2.13.0 + is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 dev: true @@ -17175,7 +17149,7 @@ packages: glob: 7.2.3 mkdirp: 0.5.6 prettier: 2.8.8 - resolve: 1.22.8 + resolve: 1.22.4 ts-essentials: 1.0.4 dev: true @@ -17503,8 +17477,8 @@ packages: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} dev: true - /typedoc@0.25.2(typescript@5.2.2): - resolution: {integrity: sha512-286F7BeATBiWe/qC4PCOCKlSTwfnsLbC/4cZ68oGBbvAqb9vV33quEOXx7q176OXotD+JdEerdQ1OZGJ818lnA==} + /typedoc@0.25.3(typescript@5.2.2): + resolution: {integrity: sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw==} engines: {node: '>= 16'} hasBin: true peerDependencies: @@ -17904,8 +17878,8 @@ packages: vfile-message: 2.0.4 dev: true - /viem@1.18.0(typescript@5.2.2)(zod@3.22.3): - resolution: {integrity: sha512-NeKi5RFj7fHdsnk5pojivHFLkTyBWyehxeSE/gSPTDJKCWnR9i+Ra0W++VwN5ghciEG55O8b4RdpYhzGmhnr7A==} + /viem@1.18.4(typescript@5.2.2)(zod@3.22.3): + resolution: {integrity: sha512-im+y30k+IGT6VtfD/q1V0RX5PaiHPsFTHkKqvTjTqV+ZT8RgJXzOGPXr5E0uPIm2cbJAJp6A9nR9BCHY7BKR2Q==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -17927,8 +17901,8 @@ packages: - zod dev: true - /viem@1.18.0(typescript@5.2.2)(zod@3.22.4): - resolution: {integrity: sha512-NeKi5RFj7fHdsnk5pojivHFLkTyBWyehxeSE/gSPTDJKCWnR9i+Ra0W++VwN5ghciEG55O8b4RdpYhzGmhnr7A==} + /viem@1.18.4(typescript@5.2.2)(zod@3.22.4): + resolution: {integrity: sha512-im+y30k+IGT6VtfD/q1V0RX5PaiHPsFTHkKqvTjTqV+ZT8RgJXzOGPXr5E0uPIm2cbJAJp6A9nR9BCHY7BKR2Q==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -18334,7 +18308,7 @@ packages: xml-name-validator: 4.0.0 dev: true - /wagmi@1.0.1(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2)(viem@1.18.0): + /wagmi@1.0.1(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2)(viem@1.18.4): resolution: {integrity: sha512-+2UkZG9eA3tKqXj1wvlvI8mL0Bcff7Tf5CKfUOyQsdKcY+J5rfwYYya25G+jja57umpHFtfxRaL7xDkNjehrRg==} peerDependencies: react: '>=17.0.0' @@ -18347,12 +18321,12 @@ packages: '@tanstack/query-sync-storage-persister': 4.29.25 '@tanstack/react-query': 4.29.25(react-dom@18.2.0)(react@18.2.0) '@tanstack/react-query-persist-client': 4.29.25(@tanstack/react-query@4.29.25) - '@wagmi/core': 1.0.1(react@18.2.0)(typescript@5.2.2)(viem@1.18.0) + '@wagmi/core': 1.0.1(react@18.2.0)(typescript@5.2.2)(viem@1.18.4) abitype: 0.8.1(typescript@5.2.2) react: 18.2.0 typescript: 5.2.2 use-sync-external-store: 1.2.0(react@18.2.0) - viem: 1.18.0(typescript@5.2.2)(zod@3.22.4) + viem: 1.18.4(typescript@5.2.2)(zod@3.22.4) transitivePeerDependencies: - '@react-native-async-storage/async-storage' - bufferutil @@ -18478,7 +18452,7 @@ packages: web3-providers-http: 4.0.4 web3-providers-ws: 4.0.4 web3-types: 1.1.0 - web3-utils: 4.0.4 + web3-utils: 4.0.5 web3-validator: 2.0.0 optionalDependencies: web3-providers-ipc: 4.0.5 @@ -18502,7 +18476,6 @@ packages: dependencies: web3-types: 1.1.1 dev: false - optional: true /web3-eth-abi@1.2.11: resolution: {integrity: sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg==} @@ -18523,7 +18496,7 @@ packages: '@ethersproject/bignumber': 5.7.0 web3-errors: 1.1.0 web3-types: 1.1.0 - web3-utils: 4.0.4 + web3-utils: 4.0.5 dev: false /web3-eth-accounts@1.2.11: @@ -18569,7 +18542,7 @@ packages: ethereum-cryptography: 2.1.2 web3-errors: 1.1.0 web3-types: 1.1.0 - web3-utils: 4.0.4 + web3-utils: 4.0.5 web3-validator: 2.0.0 dev: false @@ -18601,7 +18574,7 @@ packages: web3-eth: 4.1.0 web3-eth-abi: 4.1.0 web3-types: 1.1.0 - web3-utils: 4.0.4 + web3-utils: 4.0.5 web3-validator: 2.0.0 transitivePeerDependencies: - bufferutil @@ -18639,7 +18612,7 @@ packages: web3-eth-contract: 4.0.4 web3-net: 4.0.4 web3-types: 1.1.0 - web3-utils: 4.0.4 + web3-utils: 4.0.5 web3-validator: 2.0.0 transitivePeerDependencies: - bufferutil @@ -18663,7 +18636,7 @@ packages: dependencies: web3-errors: 1.1.0 web3-types: 1.1.0 - web3-utils: 4.0.4 + web3-utils: 4.0.5 web3-validator: 2.0.0 dev: false @@ -18691,7 +18664,7 @@ packages: web3-eth: 4.1.0 web3-rpc-methods: 1.1.0 web3-types: 1.1.0 - web3-utils: 4.0.4 + web3-utils: 4.0.5 web3-validator: 2.0.0 transitivePeerDependencies: - bufferutil @@ -18756,7 +18729,7 @@ packages: web3-providers-ws: 4.0.4 web3-rpc-methods: 1.1.0 web3-types: 1.1.0 - web3-utils: 4.0.4 + web3-utils: 4.0.5 web3-validator: 2.0.0 transitivePeerDependencies: - bufferutil @@ -18784,7 +18757,7 @@ packages: web3-core: 4.1.0 web3-rpc-methods: 1.1.0 web3-types: 1.1.0 - web3-utils: 4.0.4 + web3-utils: 4.0.5 transitivePeerDependencies: - bufferutil - encoding @@ -18838,7 +18811,7 @@ packages: cross-fetch: 3.1.8 web3-errors: 1.1.0 web3-types: 1.1.0 - web3-utils: 4.0.4 + web3-utils: 4.0.5 transitivePeerDependencies: - encoding dev: false @@ -18887,7 +18860,7 @@ packages: isomorphic-ws: 5.0.0(ws@8.13.0) web3-errors: 1.1.0 web3-types: 1.1.0 - web3-utils: 4.0.4 + web3-utils: 4.0.5 ws: 8.13.0(bufferutil@4.0.7)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil @@ -18931,7 +18904,6 @@ packages: engines: {node: '>=14', npm: '>=6.12.0'} requiresBuild: true dev: false - optional: true /web3-utils@1.10.1: resolution: {integrity: sha512-r6iUUw/uMnNcWXjhRv33Nyrhxq3VGOPBXeSzxhOXIci4SvC/LPTpROY0uTrMX7ztKyODYrHp8WhTkEf+ZnHssw==} @@ -18975,14 +18947,12 @@ packages: /web3-utils@4.0.5: resolution: {integrity: sha512-43xIM7rr3htYNzliVQLpWLQmEf4XX8IXgjvqLcEuC/xje14O5UQM4kamRCtz8v3JZN3X6QTfsV6Zgby67mVmCg==} engines: {node: '>=14', npm: '>=6.12.0'} - requiresBuild: true dependencies: ethereum-cryptography: 2.1.2 web3-errors: 1.1.1 web3-types: 1.1.1 web3-validator: 2.0.1 dev: false - optional: true /web3-validator@1.0.2: resolution: {integrity: sha512-orx1CQAEnwJUnl/8iF2II2zSA4wiooNJvFmVE0Dbmt/kE370SugIDViQP76snhxtouG2AXzz4GyKbPCMlLGh/A==} @@ -19017,7 +18987,6 @@ packages: web3-types: 1.1.1 zod: 3.22.4 dev: false - optional: true /web3@1.2.11: resolution: {integrity: sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ==} @@ -19440,6 +19409,16 @@ packages: engines: {node: '>= 6'} dev: true + /yaml@2.3.1: + resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==} + engines: {node: '>= 14'} + dev: true + + /yaml@2.3.2: + resolution: {integrity: sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==} + engines: {node: '>= 14'} + dev: true + /yaml@2.3.3: resolution: {integrity: sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==} engines: {node: '>= 14'} diff --git a/proxyd/config.go b/proxyd/config.go index fefca9f6e500..63f557c28004 100644 --- a/proxyd/config.go +++ b/proxyd/config.go @@ -22,9 +22,9 @@ type ServerConfig struct { MaxUpstreamBatchSize int `toml:"max_upstream_batch_size"` - EnableRequestLog bool `toml:"enable_request_log"` - MaxRequestBodyLogLen int `toml:"max_request_body_log_len"` - EnablePprof bool `toml:"enable_pprof"` + EnableRequestLog bool `toml:"enable_request_log"` + MaxRequestBodyLogLen int `toml:"max_request_body_log_len"` + EnablePprof bool `toml:"enable_pprof"` EnableXServedByHeader bool `toml:"enable_served_by_header"` } @@ -51,6 +51,7 @@ type RateLimitConfig struct { ExemptUserAgents []string `toml:"exempt_user_agents"` ErrorMessage string `toml:"error_message"` MethodOverrides map[string]*RateLimitMethodOverride `toml:"method_overrides"` + IPHeaderOverride string `toml:"ip_header_override"` } type RateLimitMethodOverride struct { diff --git a/proxyd/go.sum b/proxyd/go.sum index e759ce561aa5..a54ffb592175 100644 --- a/proxyd/go.sum +++ b/proxyd/go.sum @@ -138,7 +138,6 @@ github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= diff --git a/proxyd/rewriter.go b/proxyd/rewriter.go index 98b59ec1d72b..605787eff312 100644 --- a/proxyd/rewriter.go +++ b/proxyd/rewriter.go @@ -66,25 +66,26 @@ func RewriteRequest(rctx RewriteContext, req *RPCReq, res *RPCRes) (RewriteResul "eth_newFilter": return rewriteRange(rctx, req, res, 0) case "debug_getRawReceipts", "consensus_getReceipts": - return rewriteParam(rctx, req, res, 0, true) + return rewriteParam(rctx, req, res, 0, true, false) case "eth_getBalance", "eth_getCode", "eth_getTransactionCount", "eth_call": - return rewriteParam(rctx, req, res, 1, false) - case "eth_getStorageAt": - return rewriteParam(rctx, req, res, 2, false) + return rewriteParam(rctx, req, res, 1, false, true) + case "eth_getStorageAt", + "eth_getProof": + return rewriteParam(rctx, req, res, 2, false, true) case "eth_getBlockTransactionCountByNumber", "eth_getUncleCountByBlockNumber", "eth_getBlockByNumber", "eth_getTransactionByBlockNumberAndIndex", "eth_getUncleByBlockNumberAndIndex": - return rewriteParam(rctx, req, res, 0, false) + return rewriteParam(rctx, req, res, 0, false, false) } return RewriteNone, nil } -func rewriteParam(rctx RewriteContext, req *RPCReq, res *RPCRes, pos int, required bool) (RewriteResult, error) { +func rewriteParam(rctx RewriteContext, req *RPCReq, res *RPCRes, pos int, required bool, blockNrOrHash bool) (RewriteResult, error) { var p []interface{} err := json.Unmarshal(req.Params, &p) if err != nil { @@ -99,13 +100,38 @@ func rewriteParam(rctx RewriteContext, req *RPCReq, res *RPCRes, pos int, requir return RewriteNone, nil } - s, ok := p[pos].(string) - if !ok { - return RewriteOverrideError, errors.New("expected string") - } - val, rw, err := rewriteTag(rctx, s) - if err != nil { - return RewriteOverrideError, err + // support for https://eips.ethereum.org/EIPS/eip-1898 + var val interface{} + var rw bool + if blockNrOrHash { + bnh, err := remarshalBlockNumberOrHash(p[pos]) + if err != nil { + // fallback to string + s, ok := p[pos].(string) + if ok { + val, rw, err = rewriteTag(rctx, s) + if err != nil { + return RewriteOverrideError, err + } + } else { + return RewriteOverrideError, errors.New("expected BlockNumberOrHash or string") + } + } else { + val, rw, err = rewriteTagBlockNumberOrHash(rctx, bnh) + if err != nil { + return RewriteOverrideError, err + } + } + } else { + s, ok := p[pos].(string) + if !ok { + return RewriteOverrideError, errors.New("expected string") + } + + val, rw, err = rewriteTag(rctx, s) + if err != nil { + return RewriteOverrideError, err + } } if rw { @@ -210,14 +236,23 @@ func rewriteTagMap(rctx RewriteContext, m map[string]interface{}, key string) (b return false, nil } -func rewriteTag(rctx RewriteContext, current string) (string, bool, error) { +func remarshalBlockNumberOrHash(current interface{}) (*rpc.BlockNumberOrHash, error) { jv, err := json.Marshal(current) if err != nil { - return "", false, err + return nil, err } var bnh rpc.BlockNumberOrHash err = bnh.UnmarshalJSON(jv) + if err != nil { + return nil, err + } + + return &bnh, nil +} + +func rewriteTag(rctx RewriteContext, current string) (string, bool, error) { + bnh, err := remarshalBlockNumberOrHash(current) if err != nil { return "", false, err } @@ -245,3 +280,31 @@ func rewriteTag(rctx RewriteContext, current string) (string, bool, error) { return current, false, nil } + +func rewriteTagBlockNumberOrHash(rctx RewriteContext, current *rpc.BlockNumberOrHash) (*rpc.BlockNumberOrHash, bool, error) { + // this is a hash, not a block number + if current.BlockNumber == nil { + return current, false, nil + } + + switch *current.BlockNumber { + case rpc.PendingBlockNumber, + rpc.EarliestBlockNumber: + return current, false, nil + case rpc.FinalizedBlockNumber: + bn := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(rctx.finalized)) + return &bn, true, nil + case rpc.SafeBlockNumber: + bn := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(rctx.safe)) + return &bn, true, nil + case rpc.LatestBlockNumber: + bn := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(rctx.latest)) + return &bn, true, nil + default: + if current.BlockNumber.Int64() > int64(rctx.latest) { + return nil, false, ErrRewriteBlockOutOfRange + } + } + + return current, false, nil +} diff --git a/proxyd/rewriter_test.go b/proxyd/rewriter_test.go index 94bc5c962d33..1f0d80ba25c9 100644 --- a/proxyd/rewriter_test.go +++ b/proxyd/rewriter_test.go @@ -5,7 +5,9 @@ import ( "strings" "testing" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/require" ) @@ -282,12 +284,14 @@ func TestRewriteRequest(t *testing.T) { }, expected: RewriteOverrideRequest, check: func(t *testing.T, args args) { - var p []string + var p []interface{} err := json.Unmarshal(args.req.Params, &p) require.Nil(t, err) require.Equal(t, 2, len(p)) require.Equal(t, "0x123", p[0]) - require.Equal(t, hexutil.Uint64(100).String(), p[1]) + bnh, err := remarshalBlockNumberOrHash(p[1]) + require.Nil(t, err) + require.Equal(t, rpc.BlockNumberOrHashWithNumber(100), *bnh) }, }, { @@ -314,12 +318,14 @@ func TestRewriteRequest(t *testing.T) { }, expected: RewriteOverrideRequest, check: func(t *testing.T, args args) { - var p []string + var p []interface{} err := json.Unmarshal(args.req.Params, &p) require.Nil(t, err) require.Equal(t, 2, len(p)) require.Equal(t, "0x123", p[0]) - require.Equal(t, hexutil.Uint64(100).String(), p[1]) + bnh, err := remarshalBlockNumberOrHash(p[1]) + require.Nil(t, err) + require.Equal(t, rpc.BlockNumberOrHashWithNumber(100), *bnh) }, }, { @@ -359,13 +365,15 @@ func TestRewriteRequest(t *testing.T) { }, expected: RewriteOverrideRequest, check: func(t *testing.T, args args) { - var p []string + var p []interface{} err := json.Unmarshal(args.req.Params, &p) require.Nil(t, err) require.Equal(t, 3, len(p)) require.Equal(t, "0x123", p[0]) require.Equal(t, "5", p[1]) - require.Equal(t, hexutil.Uint64(100).String(), p[2]) + bnh, err := remarshalBlockNumberOrHash(p[2]) + require.Nil(t, err) + require.Equal(t, rpc.BlockNumberOrHashWithNumber(100), *bnh) }, }, { @@ -377,13 +385,15 @@ func TestRewriteRequest(t *testing.T) { }, expected: RewriteOverrideRequest, check: func(t *testing.T, args args) { - var p []string + var p []interface{} err := json.Unmarshal(args.req.Params, &p) require.Nil(t, err) require.Equal(t, 3, len(p)) require.Equal(t, "0x123", p[0]) require.Equal(t, "5", p[1]) - require.Equal(t, hexutil.Uint64(100).String(), p[2]) + bnh, err := remarshalBlockNumberOrHash(p[2]) + require.Nil(t, err) + require.Equal(t, rpc.BlockNumberOrHashWithNumber(100), *bnh) }, }, { @@ -517,6 +527,88 @@ func TestRewriteRequest(t *testing.T) { }, expected: RewriteNone, }, + // eip1898 + { + name: "eth_getStorageAt using rpc.BlockNumberOrHash at genesis (blockNumber)", + args: args{ + rctx: RewriteContext{latest: hexutil.Uint64(100)}, + req: &RPCReq{Method: "eth_getStorageAt", Params: mustMarshalJSON([]interface{}{ + "0xae851f927ee40de99aabb7461c00f9622ab91d60", + "10", + map[string]interface{}{ + "blockNumber": "0x0", + }})}, + res: nil, + }, + expected: RewriteNone, + }, + { + name: "eth_getStorageAt using rpc.BlockNumberOrHash at genesis (hash)", + args: args{ + rctx: RewriteContext{latest: hexutil.Uint64(100)}, + req: &RPCReq{Method: "eth_getStorageAt", Params: mustMarshalJSON([]interface{}{ + "0xae851f927ee40de99aabb7461c00f9622ab91d60", + "10", + map[string]interface{}{ + "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", + "requireCanonical": true, + }})}, + res: nil, + }, + expected: RewriteNone, + check: func(t *testing.T, args args) { + var p []interface{} + err := json.Unmarshal(args.req.Params, &p) + require.Nil(t, err) + require.Equal(t, 3, len(p)) + require.Equal(t, "0xae851f927ee40de99aabb7461c00f9622ab91d60", p[0]) + require.Equal(t, "10", p[1]) + bnh, err := remarshalBlockNumberOrHash(p[2]) + require.Nil(t, err) + require.Equal(t, rpc.BlockNumberOrHashWithHash(common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"), true), *bnh) + require.True(t, bnh.RequireCanonical) + }, + }, + { + name: "eth_getStorageAt using rpc.BlockNumberOrHash at latest (blockNumber)", + args: args{ + rctx: RewriteContext{latest: hexutil.Uint64(100)}, + req: &RPCReq{Method: "eth_getStorageAt", Params: mustMarshalJSON([]interface{}{ + "0xae851f927ee40de99aabb7461c00f9622ab91d60", + "10", + map[string]interface{}{ + "blockNumber": "latest", + }})}, + res: nil, + }, + expected: RewriteOverrideRequest, + check: func(t *testing.T, args args) { + var p []interface{} + err := json.Unmarshal(args.req.Params, &p) + require.Nil(t, err) + require.Equal(t, 3, len(p)) + require.Equal(t, "0xae851f927ee40de99aabb7461c00f9622ab91d60", p[0]) + require.Equal(t, "10", p[1]) + bnh, err := remarshalBlockNumberOrHash(p[2]) + require.Nil(t, err) + require.Equal(t, rpc.BlockNumberOrHashWithNumber(100), *bnh) + }, + }, + { + name: "eth_getStorageAt using rpc.BlockNumberOrHash out of range", + args: args{ + rctx: RewriteContext{latest: hexutil.Uint64(100)}, + req: &RPCReq{Method: "eth_getStorageAt", Params: mustMarshalJSON([]interface{}{ + "0xae851f927ee40de99aabb7461c00f9622ab91d60", + "10", + map[string]interface{}{ + "blockNumber": "0x111", + }})}, + res: nil, + }, + expected: RewriteOverrideError, + expectedErr: ErrRewriteBlockOutOfRange, + }, } // generalize tests for other methods with same interface and behavior @@ -528,6 +620,7 @@ func TestRewriteRequest(t *testing.T) { tests = generalize(tests, "eth_getBlockByNumber", "eth_getUncleCountByBlockNumber") tests = generalize(tests, "eth_getBlockByNumber", "eth_getTransactionByBlockNumberAndIndex") tests = generalize(tests, "eth_getBlockByNumber", "eth_getUncleByBlockNumberAndIndex") + tests = generalize(tests, "eth_getStorageSlotAt", "eth_getProof") for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/proxyd/server.go b/proxyd/server.go index 2b7a1bd966f6..5d262da40c89 100644 --- a/proxyd/server.go +++ b/proxyd/server.go @@ -44,6 +44,7 @@ const ( defaultWSWriteTimeout = 10 * time.Second maxRequestBodyLogLen = 2000 defaultMaxUpstreamBatchSize = 10 + defaultRateLimitHeader = "X-Forwarded-For" ) var emptyArrayResponse = json.RawMessage("[]") @@ -73,6 +74,7 @@ type Server struct { wsServer *http.Server cache RPCCache srvMu sync.Mutex + rateLimitHeader string } type limiterFunc func(method string) bool @@ -168,6 +170,11 @@ func NewServer( senderLim = limiterFactory(time.Duration(senderRateLimitConfig.Interval), senderRateLimitConfig.Limit, "senders") } + rateLimitHeader := defaultRateLimitHeader + if rateLimitConfig.IPHeaderOverride != "" { + rateLimitHeader = rateLimitConfig.IPHeaderOverride + } + return &Server{ BackendGroups: backendGroups, wsBackendGroup: wsBackendGroup, @@ -192,6 +199,7 @@ func NewServer( allowedChainIds: senderRateLimitConfig.AllowedChainIds, limExemptOrigins: limExemptOrigins, limExemptUserAgents: limExemptUserAgents, + rateLimitHeader: rateLimitHeader, }, nil } @@ -608,7 +616,7 @@ func (s *Server) HandleWS(w http.ResponseWriter, r *http.Request) { func (s *Server) populateContext(w http.ResponseWriter, r *http.Request) context.Context { vars := mux.Vars(r) authorization := vars["authorization"] - xff := r.Header.Get("X-Forwarded-For") + xff := r.Header.Get(s.rateLimitHeader) if xff == "" { ipPort := strings.Split(r.RemoteAddr, ":") if len(ipPort) == 2 { diff --git a/specs/safe-liveness-checking.md b/specs/safe-liveness-checking.md index 25068268372b..654516bd5201 100644 --- a/specs/safe-liveness-checking.md +++ b/specs/safe-liveness-checking.md @@ -11,7 +11,11 @@ - [Owner removal call flow](#owner-removal-call-flow) - [Shutdown](#shutdown) - [Security Properties](#security-properties) + - [In the guard](#in-the-guard) + - [In the module](#in-the-module) - [Interdependency between the guard and module](#interdependency-between-the-guard-and-module) +- [Operational considerations](#operational-considerations) + - [Manual validation of new owner liveness](#manual-validation-of-new-owner-liveness) - [Deploying the liveness checking system](#deploying-the-liveness-checking-system) - [Modify the liveness checking system](#modify-the-liveness-checking-system) - [Replacing the module](#replacing-the-module) @@ -45,7 +49,18 @@ For implementing liveness checks a `LivenessGuard` is created which receives the each executed transaction, and tracks the latest time at which a transaction was signed by each signer. This time is made publicly available by calling a `lastLive(address)(Timestamp)` method. -Signers may also call the contract's `showLiveness()()` method directly in order to prove liveness. +Owners are recorded in this mapping in one of 4 ways: + +1. Upon deployment, the guard reads the current set of owners from the Safe contract. +1. When a new owner is added to the safe. Similarly, when an owner is removed from the Safe, it's + entry is deleted from the mapping. +1. When a transaction is executed, the signatures on that transaction are passed to the guard and + used to identify the signers. If more than the required number of signatures is provided, they + are ignored. +1. An owner may call the contract's `showLiveness()()` method directly in order to prove liveness. + +Note that the first two methods do not require the owner to actually sign anything. However these mechanisms +are necessary to prevent new owners from being removed before they have had a chance to show liveness. ### The liveness module @@ -85,25 +100,34 @@ sequenceDiagram ### Shutdown -In the unlikely event that the signer set (`N`) is reduced below the allowed threshold, then (and only then) is a - shutdown mechanism activated which removes the existing signers, and hands control of the - multisig over to a predetermined entity. +In the unlikely event that the signer set (`N`) is reduced below the allowed minimum number of + owners, then (and only then) is a shutdown mechanism activated which removes the existing + signers, and hands control of the multisig over to a predetermined entity. ### Security Properties The following security properties must be upheld: +#### In the guard + 1. Signatures are assigned to the correct signer. 1. Non-signers are unable to create a record of having signed. -1. A signer cannot be censored or griefed such that their signing is not recorded. -1. Signers may demonstrate liveness either by signing a transaction or by calling directly to the +1. An owner cannot be censored or griefed such that their signing is not recorded. +1. Owners may demonstrate liveness either by signing a transaction or by calling directly to the guard. -1. The module only removes a signer if they have demonstrated liveness during the interval, or - if necessary to convert the safe to a 1 of 1. -1. The module sets the correct 75% threshold upon removing a signer. +1. It must be impossible for the guard's `checkTransaction` or `checkAfterExecution` method to + permanently revert given any calldata and the current state. +1. The guard correctly handles updates to the owners list, such that new owners are recorded, and + removed owners are deleted. + 1. An `ownersBefore` enumerable set variable is used to accomplish this, it must be emptied at + the end of the `checkAfterExecution` call. + +#### In the module + 1. During a shutdown the module correctly removes all signers, and converts the safe to a 1 of 1. -1. It must be impossible for the guard's checkTransaction or checkAfterExecution to permanently - revert given any calldata and the current state. +1. The module only removes an owner if they have not demonstrated liveness during the interval, or + if enough other owners have been removed to activate the shutdown mechanism. +1. The module correctly sets the Safe's threshold upon removing a signer. Note: neither the module nor guard attempt to prevent a quorum of owners from removing either the liveness module or guard. There are legitimate reasons they might wish to do so. Moreover, if such a quorum @@ -119,6 +143,14 @@ This means that the module can be removed or replaced without any affect on the The module however does have a dependency on the guard; if the guard is removed from the Safe, then the module will no longer be functional and calls to its `removeOwners` function will revert. +## Operational considerations + +### Manual validation of new owner liveness + +As [noted above](#the-liveness-guard) newly added owners are recorded in the guard without +necessarily having signed a transaction. Off-chain validation of the liveness of an address must +therefore be done prior to adding a new owner. + ### Deploying the liveness checking system [deploying]: #deploying-the-liveness-checking-system diff --git a/specs/span-batches.md b/specs/span-batches.md index 3314a19aa457..63c233fc2e2f 100644 --- a/specs/span-batches.md +++ b/specs/span-batches.md @@ -9,6 +9,7 @@ - [Introduction](#introduction) - [Span batch format](#span-batch-format) +- [Span batch Activation Rule](#span-batch-activation-rule) - [Optimization Strategies](#optimization-strategies) - [Truncating information and storing only necessary data](#truncating-information-and-storing-only-necessary-data) - [`tx_data_headers` removal from initial specs](#tx_data_headers-removal-from-initial-specs) @@ -144,6 +145,25 @@ Where: [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 +Total size of encoded span batch is limited to `MAX_SPAN_BATCH_SIZE` (currently 10,000,000 bytes, +equal to `MAX_RLP_BYTES_PER_CHANNEL`). Therefore every field size of span batch will be implicitly limited to +`MAX_SPAN_BATCH_SIZE` . There can be at least single span batch per channel, and channel size is limited +to `MAX_RLP_BYTES_PER_CHANNEL` and you may think that there is already an implicit limit. However, having an explicit +limit for span batch is helpful for several reasons. We may save computation costs by avoiding malicious input while +decoding. For example, lets say bad batcher wrote span batch which `block_count = max.Uint64`. We may early return using +the explicit limit, not trying to consume data until EOF is reached. We can also safely preallocate memory for decoding +because we know the upper limit of memory usage. + +## Span batch Activation Rule + +The span batch upgrade is activated based on timestamp. + +Activation Rule: `upgradeTime != null && span_start.l1_origin.timestamp >= upgradeTime` + +`span_start.l1_origin.timestamp` is the L1 origin block timestamp of the first block in the span batch. +This rule ensures that every chain activity regarding this span batch is done after the hard fork. +i.e. Every block in the span is created, submitted to the L1, and derived from the L1 after the hard fork. + ## Optimization Strategies ### Truncating information and storing only necessary data @@ -252,6 +272,13 @@ Rules are enforced with the [contextual definitions](./derivation.md#batch-queue Span-batch rules, in validation order: +- `batch_origin` is determined like with singular batches: + - `batch.epoch_num == epoch.number+1`: + - If `next_epoch` is not known -> `undecided`: + i.e. a batch that changes the L1 origin cannot be processed until we have the L1 origin data. + - If known, then define `batch_origin` as `next_epoch` +- `batch_origin.timestamp < span_batch_upgrade_timestamp` -> `drop`: + i.e. enforce the [span batch upgrade activation rule](#span-batch-activation-rule). - `batch.start_timestamp > next_timestamp` -> `future`: i.e. the batch must be ready to process. - `batch.start_timestamp < next_timestamp` -> `drop`: i.e. the batch must not be too old. - `batch.parent_check != safe_l2_head.hash[:20]` -> `drop`: i.e. the checked part of the parent hash must be equal diff --git a/specs/superchain-upgrades.md b/specs/superchain-upgrades.md index d606c7eebfdd..19e241ce06dd 100644 --- a/specs/superchain-upgrades.md +++ b/specs/superchain-upgrades.md @@ -199,7 +199,10 @@ and are then retrieved from the superchain target configuration. ### L2 Block-number based activation (deprecated) -Activation rule: `x != null && x >= upgradeNumber` +Activation rule: `upgradeNumber != null && block.number >= upgradeNumber` + +Starting at, and including, the L2 `block` with `block.number >= upgradeNumber`, the upgrade rules apply. +If the upgrade block-number `upgradeNumber` is not specified in the configuration, the upgrade is ignored. This block number based method has commonly been used in L1 up until the Bellatrix/Paris upgrade, a.k.a. The Merge, which was upgraded through special rules. @@ -207,22 +210,19 @@ which was upgraded through special rules. This method is not superchain-compatible, as the activation-parameter is chain-specific (different chains may have different block-heights at the same moment in time). -Starting at, and including, the L2 `block` with `block.number == x`, the upgrade rules apply. -If the upgrade block-number `x` is not specified in the configuration, the upgrade is ignored. - This applies to the L2 block number, not to the L1-origin block number. This means that an L2 upgrade may be inactive, and then active, without changing the L1-origin. ### L2 Block-timestamp based activation -Activation rule: `x != null && x >= upgradeTime` +Activation rule: `upgradeTime != null && block.timestamp >= upgradeTime` + +Starting at, and including, the L2 `block` with `block.timestamp >= upgradeTime`, the upgrade rules apply. +If the upgrade block-timestamp `upgradeTime` is not specified in the configuration, the upgrade is ignored. This is the preferred superchain upgrade activation-parameter type: it is synchronous between all L2 chains and compatible with post-Merge timestamp-based chain upgrades in L1. -Starting at, and including, the L2 `block` with `block.timestamp == x`, the upgrade rules apply. -If the upgrade block-timestamp `x` is not specified in the configuration, the upgrade is ignored. - This applies to the L2 block timestamp, not to the L1-origin block timestamp. This means that an L2 upgrade may be inactive, and then active, without changing the L1-origin. diff --git a/ufm-test-services/metamask/Dockerfile b/ufm-test-services/metamask/Dockerfile index 1e9631470ab0..b09e7bc3912f 100644 --- a/ufm-test-services/metamask/Dockerfile +++ b/ufm-test-services/metamask/Dockerfile @@ -7,6 +7,8 @@ WORKDIR /app # Update PATH ENV PATH /app/node_modules/.bin:$PATH +RUN npm i -g pnpm + RUN if [ "$METAMASK_PLAYWRIGHT_RUN_HEADLESS" != "false" ]; then \ apt-get update && \ apt-get install -y xvfb && \ @@ -14,8 +16,8 @@ RUN if [ "$METAMASK_PLAYWRIGHT_RUN_HEADLESS" != "false" ]; then \ fi # Copy necessary files and directories -COPY package.json /app/ -RUN npm install +COPY package.json pnpm-lock.yaml pnpm-workspace.yaml /app/ +RUN pnpm install --frozen-lockfile COPY tests /app/tests/ COPY playwright.config.ts /app/ COPY start.sh /app/