diff --git a/.changeset/poor-dots-perform.md b/.changeset/poor-dots-perform.md new file mode 100644 index 0000000000000..94c8b3f7d05ea --- /dev/null +++ b/.changeset/poor-dots-perform.md @@ -0,0 +1,8 @@ +--- +'@eth-optimism/indexer': minor +'@eth-optimism/contracts-bedrock': minor +'@eth-optimism/integration-tests-bedrock': minor +'@eth-optimism/sdk': minor +--- + +Adds an implementation of the Two Step Withdrawals V2 proposal diff --git a/indexer/integration_tests/bedrock_test.go b/indexer/integration_tests/bedrock_test.go index 20e26ad6532a8..a638d76fefb0d 100644 --- a/indexer/integration_tests/bedrock_test.go +++ b/indexer/integration_tests/bedrock_test.go @@ -201,11 +201,12 @@ func TestBedrockIndexer(t *testing.T) { require.NoError(t, err) proofCl := gethclient.New(rpcClient) receiptCl := ethclient.NewClient(rpcClient) - wParams, err := withdrawals.FinalizeWithdrawalParameters(context.Background(), proofCl, receiptCl, wdTx.Hash(), finHeader) + wParams, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, wdTx.Hash(), finHeader) require.NoError(t, err) l1Opts.Value = big.NewInt(0) - finTx, err := portal.FinalizeWithdrawalTransaction( + // Prove our withdrawal + proveTx, err := portal.ProveWithdrawalTransaction( l1Opts, bindings.TypesWithdrawalTransaction{ Nonce: wParams.Nonce, @@ -221,6 +222,32 @@ func TestBedrockIndexer(t *testing.T) { ) require.NoError(t, err) + _, err = e2eutils.WaitReceiptOK(e2eutils.TimeoutCtx(t, time.Minute), l1Client, proveTx.Hash()) + require.NoError(t, err) + + // Wait for the finalization period to elapse + _, err = withdrawals.WaitForFinalizationPeriod( + e2eutils.TimeoutCtx(t, time.Minute), + l1Client, + predeploys.DevOptimismPortalAddr, + wParams.BlockNumber, + ) + require.NoError(t, err) + + // Send our finalize withdrawal transaction + finTx, err := portal.FinalizeWithdrawalTransaction( + l1Opts, + bindings.TypesWithdrawalTransaction{ + Nonce: wParams.Nonce, + Sender: wParams.Sender, + Target: wParams.Target, + Value: wParams.Value, + GasLimit: wParams.GasLimit, + Data: wParams.Data, + }, + ) + require.NoError(t, err) + finReceipt, err := e2eutils.WaitReceiptOK(e2eutils.TimeoutCtx(t, time.Minute), l1Client, finTx.Hash()) require.NoError(t, err) diff --git a/op-bindings/bindings/optimismportal.go b/op-bindings/bindings/optimismportal.go index 703db62b3dee0..c960a6c69cc6d 100644 --- a/op-bindings/bindings/optimismportal.go +++ b/op-bindings/bindings/optimismportal.go @@ -48,8 +48,8 @@ type TypesWithdrawalTransaction struct { // OptimismPortalMetaData contains all meta data concerning the OptimismPortal contract. var OptimismPortalMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"opaqueData\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASE_FEE_MAX_CHANGE_DENOMINATOR\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ELASTICITY_MULTIPLIER\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INITIAL_BASE_FEE\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINIMUM_BASE_FEE\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TARGET_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"donateETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structTypes.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structTypes.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"_withdrawalProof\",\"type\":\"bytes[]\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"isBlockFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x6101206040523480156200001257600080fd5b506040516200484038038062004840833981016040819052620000359162000261565b6000608081905260a052600160c0526001600160a01b0382166101005260e08190526200006162000069565b50506200029d565b600054610100900460ff16158080156200008a5750600054600160ff909116105b80620000ba5750620000a730620001af60201b620012761760201c565b158015620000ba575060005460ff166001145b620001235760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000147576000805461ff0019166101001790555b603280546001600160a01b03191661dead17905562000165620001be565b8015620001ac576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054610100900460ff166200022b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200011a565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b600080604083850312156200027557600080fd5b82516001600160a01b03811681146200028d57600080fd5b6020939093015192949293505050565b60805160a05160c05160e05161010051614549620002f76000396000818161014f01528181610b2401526111e90152600081816103f8015261146c0152600061094001526000610917015260006108ee01526145496000f3fe6080604052600436106101115760003560e01c80638b4c40b0116100a5578063ca3e99ba11610074578063cff0ab9611610059578063cff0ab9614610332578063e9e05c42146103d3578063f4daa291146103e657600080fd5b8063ca3e99ba14610308578063cd7c97891461031d57600080fd5b80638b4c40b0146101365780639bf62d821461027b578063a14238e7146102a8578063c4fc4798146102e857600080fd5b8063683d95c8116100e1578063683d95c81461021b5780636bb0291e1461023b5780638129fc1c14610250578063867ead131461026557600080fd5b80621c2ff61461013d57806313620abd1461019b57806354fd4d50146101d457806364b79208146101f657600080fd5b36610138576101363334620186a060006040518060200160405280600081525061041a565b005b600080fd5b34801561014957600080fd5b506101717f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101a757600080fd5b506101b3633b9aca0081565b6040516fffffffffffffffffffffffffffffffff9091168152602001610192565b3480156101e057600080fd5b506101e96108e7565b6040516101929190613b25565b34801561020257600080fd5b5061020d627a120081565b604051908152602001610192565b34801561022757600080fd5b50610136610236366004613cfa565b61098a565b34801561024757600080fd5b5061020d600481565b34801561025c57600080fd5b50610136610fe2565b34801561027157600080fd5b5061020d61271081565b34801561028757600080fd5b506032546101719073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b457600080fd5b506102d86102c3366004613dee565b60336020526000908152604090205460ff1681565b6040519015158152602001610192565b3480156102f457600080fd5b506102d8610303366004613dee565b6111a0565b34801561031457600080fd5b5061020d611265565b34801561032957600080fd5b5061020d600881565b34801561033e57600080fd5b5060015461039a906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff9283166020850152911690820152606001610192565b6101366103e1366004613e07565b61041a565b3480156103f257600080fd5b5061020d7f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156104d15773ffffffffffffffffffffffffffffffffffffffff8716156104d157604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b333281146104f2575033731111000000000000000000000000000000001111015b6000348888888860405160200161050d959493929190613e94565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161057d9190613b25565b60405180910390a450506001546000906105bd907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643613f28565b905080156107465760006105d56004627a1200613f6e565b6001546106009190700100000000000000000000000000000000900467ffffffffffffffff16613fd6565b9050600060086106146004627a1200613f6e565b6001546106349085906fffffffffffffffffffffffffffffffff1661404a565b61063e9190613f6e565b6106489190613f6e565b6001549091506000906106949061067e906106769085906fffffffffffffffffffffffffffffffff16614106565b612710611292565b6fffffffffffffffffffffffffffffffff6112ad565b905060018411156107075761070461067e670de0b6b3a76400006106f06106bc600883613f6e565b6106ce90670de0b6b3a7640000613fd6565b6106d960018a613f28565b6106eb90670de0b6b3a764000061417a565b6112bc565b6106fa908561404a565b6106769190613f6e565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054849190601090610779908490700100000000000000000000000000000000900467ffffffffffffffff166141b7565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315610855576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d6974000060648201526084016104c8565b600154600090610881906fffffffffffffffffffffffffffffffff1667ffffffffffffffff86166141e3565b6fffffffffffffffffffffffffffffffff16905060006108a548633b9aca006112ed565b6108af908361421b565b905060005a6108be9086613f28565b9050808211156108da576108da6108d58284613f28565b6112fd565b5050505050505050505050565b60606109127f000000000000000000000000000000000000000000000000000000000000000061132b565b61093b7f000000000000000000000000000000000000000000000000000000000000000061132b565b6109647f000000000000000000000000000000000000000000000000000000000000000061132b565b6040516020016109769392919061422f565b604051602081830303815290604052905090565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610a33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e0060648201526084016104c8565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610af2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e74726163740060648201526084016104c8565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610b7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba391906142a5565b9050610bae81611468565b610c3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4f7074696d69736d506f7274616c3a2070726f706f73616c206973206e6f742060448201527f7965742066696e616c697a65640000000000000000000000000000000000000060648201526084016104c8565b610c51610c4c368690038601866142f4565b6114a2565b815114610ce0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084016104c8565b6000610ceb876114fe565b9050610d05816040870135610d00868861435a565b61152e565b610d91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f66000000000000000000000000000060648201526084016104c8565b60008181526033602052604090205460ff1615610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a6564000000000000000000000060648201526084016104c8565b600081815260336020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556080870151610e7990614e20906143de565b5a1015610f08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c00000000000000000060648201526084016104c8565b8660200151603260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000610f6b886040015189608001518a606001518b60a001516115f5565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610fd090841515815260200190565b60405180910390a25050505050505050565b600054610100900460ff16158080156110025750600054600160ff909116105b8061101c5750303b15801561101c575060005460ff166001145b6110a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104c8565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561110657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905561113a61160f565b801561119d57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa15801561122f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125391906142a5565b905061125e81611468565b9392505050565b6112736004627a1200613f6e565b81565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000818312156112a257816112a4565b825b90505b92915050565b60008183126112a257816112a4565b60006112a4670de0b6b3a7640000836112d4866116f2565b6112de919061404a565b6112e89190613f6e565b611936565b6000818310156112a257816112a4565b6000805a90505b825a6113109083613f28565b10156113265761131f826143f6565b9150611304565b505050565b60608160000361136e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156113985780611382816143f6565b91506113919050600a8361421b565b9150611372565b60008167ffffffffffffffff8111156113b3576113b3613b38565b6040519080825280601f01601f1916602001820160405280156113dd576020820181803683370190505b5090505b8415611460576113f2600183613f28565b91506113ff600a8661442e565b61140a9060306143de565b60f81b81838151811061141f5761141f614442565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611459600a8661421b565b94506113e1565b949350505050565b60007f0000000000000000000000000000000000000000000000000000000000000000826020015161149a91906143de565b421192915050565b600081600001518260200151836040015184606001516040516020016114e1949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a088015193516000976114e1979096959101614471565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506115ec9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152908587611b75565b95945050505050565b600080600080845160208601878a8af19695505050505050565b600054610100900460ff166116a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104c8565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b600080821361175d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104c8565b6000606061176a84611b99565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361196757506000919050565b680755bf798b4a1bf1e582126119d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f57000000000000000000000000000000000000000060448201526064016104c8565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080611b8186611c6f565b9050611b8f81868686611ca1565b9695505050505050565b6000808211611c04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104c8565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60608180519060200120604051602001611c8b91815260200190565b6040516020818303038152906040529050919050565b6000806000611cb1878686611cde565b91509150818015611cd357508051602080830191909120875191880191909120145b979650505050505050565b600060606000611ced85611dfc565b90506000806000611cff848a89611eeb565b81519295509093509150158080611d135750815b611d9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2070726f76696465642070726f6f6620697320696e60448201527f76616c696400000000000000000000000000000000000000000000000000000060648201526084016104c8565b600081611dbb5760405180602001604052806000815250611de7565b611de786611dca600188613f28565b81518110611dda57611dda614442565b60200260200101516125ef565b805115159c909b509950505050505050505050565b805160609060008167ffffffffffffffff811115611e1c57611e1c613b38565b604051908082528060200260200182016040528015611e6157816020015b6040805180820190915260608082526020820152815260200190600190039081611e3a5790505b50905060005b82811015611ee3576040518060400160405280868381518110611e8c57611e8c614442565b60200260200101518152602001611ebb878481518110611eae57611eae614442565b6020026020010151612626565b815250828281518110611ed057611ed0614442565b6020908102919091010152600101611e67565b509392505050565b60006060818080611efb87612639565b9050600086604051602001611f1291815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152606080835260208301529150600090819060005b8c51811015612571578c8181518110611f7257611f72614442565b602002602001015191508284611f8891906143de565b9350611f956001886143de565b9650836000036120505781518051602091820120604051611fe592611fbf92910190815260200190565b604051602081830303815290604052868051602091820120825192909101919091201490565b61204b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016104c8565b6121a7565b815151602011612106578151805160209182012060405161207a92611fbf92910190815260200190565b61204b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c20686173680000000000000000000000000000000000000000000000000060648201526084016104c8565b8151855160208088019190912082519190920120146121a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f652068617368000000000000000000000000000000000000000000000000000060648201526084016104c8565b6121b3601060016143de565b8260200151510361222557855184146125715760008685815181106121da576121da614442565b602001015160f81c60f81b60f81c9050600083602001518260ff168151811061220557612205614442565b60200260200101519050612218816127d4565b965060019450505061255f565b6002826020015151036124d757600061223d836127f9565b905060008160008151811061225457612254614442565b016020015160f81c9050600061226b6002836144c8565b6122769060026144ea565b90506000612287848360ff1661281d565b905060006122958b8a61281d565b905060006122a38383612853565b9050825182511015612337576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a20696e76616c6964206b6579206c656e677468206660448201527f6f72206c656166206f7220657874656e73696f6e206e6f64650000000000000060648201526084016104c8565b60ff85166002148061234c575060ff85166003145b156123b6578083511480156123615750808251145b1561237357612370818b6143de565b99505b6040518060400160405280600181526020017f80000000000000000000000000000000000000000000000000000000000000008152509a50505050505050612571565b60ff851615806123c9575060ff85166001145b1561244f5782518114612419576040518060400160405280600181526020017f80000000000000000000000000000000000000000000000000000000000000008152509a50505050505050612571565b612440886020015160018151811061243357612433614442565b60200260200101516127d4565b9a50975061255f945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e20707265666978000000000000000000000000000060648201526084016104c8565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f646500000000000000000000000000000000000000000000000060648201526084016104c8565b80612569816143f6565b915050611f57565b508561257d868561281d565b60408051808201909152600181527f80000000000000000000000000000000000000000000000000000000000000006020918201528651908701207f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4211498509850985050505050505093509350939050565b602081015180516060916112a79161260990600190613f28565b8151811061261957612619614442565b6020026020010151612902565b60606112a761263483612a62565b612b4b565b8051606090600061264b82600261417a565b67ffffffffffffffff81111561266357612663613b38565b6040519080825280601f01601f19166020018201604052801561268d576020820181803683370190505b5090506000805b838110156127ca578581815181106126ae576126ae614442565b6020910101517fff000000000000000000000000000000000000000000000000000000000000008116925060041c7f0ff0000000000000000000000000000000000000000000000000000000000000168361270a83600261417a565b8151811061271a5761271a614442565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f0f0000000000000000000000000000000000000000000000000000000000000082168361277883600261417a565b6127839060016143de565b8151811061279357612793614442565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101612694565b5090949350505050565b606060208260000151106127f0576127eb82612902565b6112a7565b6112a782612daf565b60606112a7612818836020015160008151811061261957612619614442565b612639565b60608251821061283c57506040805160208101909152600081526112a7565b6112a4838384865161284e9190613f28565b612dc5565b6000806000835185511061286857835161286b565b84515b90505b80821080156128f2575083828151811061288a5761288a614442565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168583815181106128c9576128c9614442565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15611ee35781600101915061286e565b6060600080600061291285612f9d565b91945092509050600081600181111561292d5761292d61450d565b146129ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d0000000000000060648201526084016104c8565b6129c482846143de565b855114612a53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e64657200000000000000000000000060648201526084016104c8565b6115ec85602001518484613a0a565b60408051808201909152600080825260208201526000825111612b2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016104c8565b50604080518082019091528151815260209182019181019190915290565b60606000806000612b5b85612f9d565b919450925090506001816001811115612b7657612b7661450d565b14612c03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d000000000000000060648201526084016104c8565b8451612c0f83856143de565b14612c9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e646572000000000000000000000000000060648201526084016104c8565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081612cb55790505090506000845b8751811015612da357600080612d286040518060400160405280858d60000151612d0c9190613f28565b8152602001858d60200151612d2191906143de565b9052612f9d565b509150915060405180604001604052808383612d4491906143de565b8152602001848c60200151612d5991906143de565b815250858581518110612d6e57612d6e614442565b6020908102919091010152612d846001856143de565b9350612d9081836143de565b612d9a90846143de565b92505050612ce2565b50815295945050505050565b60606112a7826020015160008460000151613a0a565b60608182601f011015612e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104c8565b828284011015612ea0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104c8565b81830184511015612f0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016104c8565b606082158015612f2c5760405191506000825260208201604052612f94565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612f65578051835260209283019201612f4d565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60008060008084600001511161305b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016104c8565b6020840151805160001a607f8111613080576000600160009450945094505050613a03565b60b7811161328e576000613095608083613f28565b905080876000015111613150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a4016104c8565b6001838101517fff000000000000000000000000000000000000000000000000000000000000001690821415806131c957507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b61327b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a4016104c8565b5060019550935060009250613a03915050565b60bf81116135dc5760006132a360b783613f28565b90508087600001511161335e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a4016104c8565b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361343c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a4016104c8565b600184015160088302610100031c60378111613500576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a4016104c8565b61350a81846143de565b8951116135bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a4016104c8565b6135ca8360016143de565b9750955060009450613a039350505050565b60f781116136bd5760006135f160c083613f28565b9050808760000151116136ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a4016104c8565b600195509350849250613a03915050565b60006136ca60f783613f28565b905080876000015111613785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a4016104c8565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a4016104c8565b600184015160088302610100031c60378111613927576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a4016104c8565b61393181846143de565b8951116139e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a4016104c8565b6139f18360016143de565b9750955060019450613a039350505050565b9193909250565b606060008267ffffffffffffffff811115613a2757613a27613b38565b6040519080825280601f01601f191660200182016040528015613a51576020820181803683370190505b50905082600003613a6357905061125e565b6000613a6f85876143de565b90506020820160005b85811015613a90578281015182820152602001613a78565b85811115613a9f576000868301525b50919695505050505050565b60005b83811015613ac6578181015183820152602001613aae565b83811115613ad5576000848401525b50505050565b60008151808452613af3816020860160208601613aab565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006112a46020830184613adb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715613b8a57613b8a613b38565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613bd757613bd7613b38565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114613c0357600080fd5b919050565b600082601f830112613c1957600080fd5b813567ffffffffffffffff811115613c3357613c33613b38565b613c6460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613b90565b818152846020838601011115613c7957600080fd5b816020850160208301376000918101602001919091529392505050565b600060808284031215613ca857600080fd5b50919050565b60008083601f840112613cc057600080fd5b50813567ffffffffffffffff811115613cd857600080fd5b6020830191508360208260051b8501011115613cf357600080fd5b9250929050565b600080600080600060e08688031215613d1257600080fd5b853567ffffffffffffffff80821115613d2a57600080fd5b9087019060c0828a031215613d3e57600080fd5b613d46613b67565b82358152613d5660208401613bdf565b6020820152613d6760408401613bdf565b6040820152606083013560608201526080830135608082015260a083013582811115613d9257600080fd5b613d9e8b828601613c08565b60a083015250965060208801359550613dba8960408a01613c96565b945060c0880135915080821115613dd057600080fd5b50613ddd88828901613cae565b969995985093965092949392505050565b600060208284031215613e0057600080fd5b5035919050565b600080600080600060a08688031215613e1f57600080fd5b613e2886613bdf565b945060208601359350604086013567ffffffffffffffff8082168214613e4d57600080fd5b9093506060870135908115158214613e6457600080fd5b90925060808701359080821115613e7a57600080fd5b50613e8788828901613c08565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251613ee8816049850160208701613aab565b919091016049019695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613f3a57613f3a613ef9565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613f7d57613f7d613f3f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615613fd157613fd1613ef9565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561401057614010613ef9565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561404457614044613ef9565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561408b5761408b613ef9565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156140c6576140c6613ef9565b600087129250878205871284841616156140e2576140e2613ef9565b878505871281841616156140f8576140f8613ef9565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561414057614140613ef9565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561417457614174613ef9565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156141b2576141b2613ef9565b500290565b600067ffffffffffffffff8083168185168083038211156141da576141da613ef9565b01949350505050565b60006fffffffffffffffffffffffffffffffff8083168185168183048111821515161561421257614212613ef9565b02949350505050565b60008261422a5761422a613f3f565b500490565b60008451614241818460208901613aab565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161427d816001850160208a01613aab565b60019201918201528351614298816002840160208801613aab565b0160020195945050505050565b6000604082840312156142b757600080fd5b6040516040810181811067ffffffffffffffff821117156142da576142da613b38565b604052825181526020928301519281019290925250919050565b60006080828403121561430657600080fd5b6040516080810181811067ffffffffffffffff8211171561432957614329613b38565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff8084111561437557614375613b38565b8360051b6020614386818301613b90565b86815291850191818101903684111561439e57600080fd5b865b848110156143d2578035868111156143b85760008081fd5b6143c436828b01613c08565b8452509183019183016143a0565b50979650505050505050565b600082198211156143f1576143f1613ef9565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361442757614427613ef9565b5060010190565b60008261443d5761443d613f3f565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526144bc60c0830184613adb565b98975050505050505050565b600060ff8316806144db576144db613f3f565b8060ff84160691505092915050565b600060ff821660ff84168082101561450457614504613ef9565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"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\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"opaqueData\",\"type\":\"bytes\"}],\"name\":\"TransactionDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"WithdrawalFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"WithdrawalProven\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASE_FEE_MAX_CHANGE_DENOMINATOR\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ELASTICITY_MULTIPLIER\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INITIAL_BASE_FEE\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINIMUM_BASE_FEE\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TARGET_RESOURCE_LIMIT\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"depositTransaction\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"donateETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structTypes.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\"}],\"name\":\"finalizeWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"name\":\"isBlockFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structTypes.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}],\"internalType\":\"structTypes.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"_withdrawalProof\",\"type\":\"bytes[]\"}],\"name\":\"proveWithdrawalTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"provenWithdrawals\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162004eff38038062004eff833981016040819052620000359162000261565b6000608081905260a052600160c0526001600160a01b0382166101005260e08190526200006162000069565b50506200029d565b600054610100900460ff16158080156200008a5750600054600160ff909116105b80620000ba5750620000a730620001af60201b620018e11760201c565b158015620000ba575060005460ff166001145b620001235760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000147576000805461ff0019166101001790555b603280546001600160a01b03191661dead17905562000165620001be565b8015620001ac576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054610100900460ff166200022b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200011a565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b600080604083850312156200027557600080fd5b82516001600160a01b03811681146200028d57600080fd5b6020939093015192949293505050565b60805160a05160c05160e05161010051614bfa620003056000396000818161018501528181610aba01528181611154015281816113c601526118570152600081816104da0152611d0e01526000610dab01526000610d8201526000610d590152614bfa6000f3fe6080604052600436106101475760003560e01c80638c3152e9116100c0578063cd7c978911610074578063e965084c11610059578063e965084c14610429578063e9e05c42146104b5578063f4daa291146104c857600080fd5b8063cd7c978914610373578063cff0ab961461038857600080fd5b8063a14238e7116100a5578063a14238e7146102fe578063c4fc47981461033e578063ca3e99ba1461035e57600080fd5b80638c3152e9146102b15780639bf62d82146102d157600080fd5b806364b79208116101175780638129fc1c116100fc5780638129fc1c14610286578063867ead131461029b5780638b4c40b01461016c57600080fd5b806364b792081461024c5780636bb0291e1461027157600080fd5b80621c2ff61461017357806313620abd146101d15780634870496f1461020a57806354fd4d501461022a57600080fd5b3661016e5761016c3334620186a06000604051806020016040528060008152506104fc565b005b600080fd5b34801561017f57600080fd5b506101a77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101dd57600080fd5b506101e9633b9aca0081565b6040516fffffffffffffffffffffffffffffffff90911681526020016101c8565b34801561021657600080fd5b5061016c6102253660046142e8565b6109c9565b34801561023657600080fd5b5061023f610d52565b6040516101c8919061443e565b34801561025857600080fd5b50610263627a120081565b6040519081526020016101c8565b34801561027d57600080fd5b50610263600481565b34801561029257600080fd5b5061016c610df5565b3480156102a757600080fd5b5061026361271081565b3480156102bd57600080fd5b5061016c6102cc366004614451565b610fb3565b3480156102dd57600080fd5b506032546101a79073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030a57600080fd5b5061032e610319366004614486565b60336020526000908152604090205460ff1681565b60405190151581526020016101c8565b34801561034a57600080fd5b5061032e610359366004614486565b61180c565b34801561036a57600080fd5b506102636118d0565b34801561037f57600080fd5b50610263600881565b34801561039457600080fd5b506001546103f0906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101c8565b34801561043557600080fd5b50610487610444366004614486565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101c8565b61016c6104c336600461449f565b6104fc565b3480156104d457600080fd5b506102637f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156105b35773ffffffffffffffffffffffffffffffffffffffff8716156105b357604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b333281146105d4575033731111000000000000000000000000000000001111015b600034888888886040516020016105ef95949392919061452c565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161065f919061443e565b60405180910390a4505060015460009061069f907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436145c0565b905080156108285760006106b76004627a1200614606565b6001546106e29190700100000000000000000000000000000000900467ffffffffffffffff1661466e565b9050600060086106f66004627a1200614606565b6001546107169085906fffffffffffffffffffffffffffffffff166146e2565b6107209190614606565b61072a9190614606565b60015490915060009061077690610760906107589085906fffffffffffffffffffffffffffffffff1661479e565b6127106118fd565b6fffffffffffffffffffffffffffffffff611916565b905060018411156107e9576107e6610760670de0b6b3a76400006107d261079e600883614606565b6107b090670de0b6b3a764000061466e565b6107bb60018a6145c0565b6107cd90670de0b6b3a7640000614812565b611925565b6107dc90856146e2565b6107589190614606565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805484919060109061085b908490700100000000000000000000000000000000900467ffffffffffffffff1661484f565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315610937576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d6974000060648201526084016105aa565b600154600090610963906fffffffffffffffffffffffffffffffff1667ffffffffffffffff861661487b565b6fffffffffffffffffffffffffffffffff169050600061098748633b9aca00611956565b61099190836148b3565b905060005a6109a090866145c0565b9050808211156109bc576109bc6109b782846145c0565b611966565b5050505050505050505050565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e74726163740060648201526084016105aa565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610b15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3991906148c7565b519050610b53610b4e36869003860186614916565b611994565b8114610be1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084016105aa565b6000610bec876119f0565b9050610c06816040870135610c01868861497c565b611a20565b610c92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f66000000000000000000000000000060648201526084016105aa565b604080516060810182528381526fffffffffffffffffffffffffffffffff42811660208084019182528a8316848601908152600087815260348352868120955186559251905184167001000000000000000000000000000000000293169290921760019093019290925589830151908a0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169184917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a450505050505050565b6060610d7d7f0000000000000000000000000000000000000000000000000000000000000000611ae7565b610da67f0000000000000000000000000000000000000000000000000000000000000000611ae7565b610dcf7f0000000000000000000000000000000000000000000000000000000000000000611ae7565b604051602001610de193929190614a00565b604051602081830303815290604052905090565b600054610100900460ff1615808015610e155750600054600160ff909116105b80610e2f5750303b158015610e2f575060005460ff166001145b610ebb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105aa565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f1957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055610f4d611c24565b8015610fb057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461105c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e0060648201526084016105aa565b6000611067826119f0565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e00000000000000000000000000000000000060648201526084016105aa565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166320e9fcd46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e19190614a76565b81602001516fffffffffffffffffffffffffffffffff1610156112ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a4016105aa565b6112cb81602001516fffffffffffffffffffffffffffffffff16611d07565b61137d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a4016105aa565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015611421573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144591906148c7565b82518151919250146114ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a4016105aa565b61150c8160200151611d07565b6115be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a4016105aa565b60008381526033602052604090205460ff161561165d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a6564000000000000000000000060648201526084016105aa565b600083815260336020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560808401516116a690614e2090614a8f565b5a1015611735576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c00000000000000000060648201526084016105aa565b8360200151603260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060006117988560400151866080015187606001518860a00151611d3b565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906117fd90841515815260200190565b60405180910390a25050505050565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906118ca9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa15801561189d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c191906148c7565b60200151611d07565b92915050565b6118de6004627a1200614606565b81565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60008183121561190d578161190f565b825b9392505050565b600081831261190d578161190f565b600061190f670de0b6b3a76400008361193d86611d55565b61194791906146e2565b6119519190614606565b611f99565b60008183101561190d578161190f565b6000805a90505b825a61197990836145c0565b101561198f5761198882614aa7565b915061196d565b505050565b600081600001518260200151836040015184606001516040516020016119d3949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a088015193516000976119d3979096959101614adf565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250611ade9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529085876121d8565b95945050505050565b606081600003611b2a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611b545780611b3e81614aa7565b9150611b4d9050600a836148b3565b9150611b2e565b60008167ffffffffffffffff811115611b6f57611b6f61410e565b6040519080825280601f01601f191660200182016040528015611b99576020820181803683370190505b5090505b8415611c1c57611bae6001836145c0565b9150611bbb600a86614b36565b611bc6906030614a8f565b60f81b818381518110611bdb57611bdb614b4a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611c15600a866148b3565b9450611b9d565b949350505050565b600054610100900460ff16611cbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105aa565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6000611d337f000000000000000000000000000000000000000000000000000000000000000083614a8f565b421192915050565b600080600080845160208601878a8af19695505050505050565b6000808213611dc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016105aa565b60006060611dcd846121fc565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213611fca57506000919050565b680755bf798b4a1bf1e5821261203c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f57000000000000000000000000000000000000000060448201526064016105aa565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000806121e4866122d2565b90506121f281868686612304565b9695505050505050565b6000808211612267576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016105aa565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606081805190602001206040516020016122ee91815260200190565b6040516020818303038152906040529050919050565b6000806000612314878686612341565b9150915081801561233657508051602080830191909120875191880191909120145b979650505050505050565b6000606060006123508561245f565b90506000806000612362848a8961254e565b815192955090935091501580806123765750815b612402576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2070726f76696465642070726f6f6620697320696e60448201527f76616c696400000000000000000000000000000000000000000000000000000060648201526084016105aa565b60008161241e576040518060200160405280600081525061244a565b61244a8661242d6001886145c0565b8151811061243d5761243d614b4a565b6020026020010151612c52565b805115159c909b509950505050505050505050565b805160609060008167ffffffffffffffff81111561247f5761247f61410e565b6040519080825280602002602001820160405280156124c457816020015b604080518082019091526060808252602082015281526020019060019003908161249d5790505b50905060005b828110156125465760405180604001604052808683815181106124ef576124ef614b4a565b6020026020010151815260200161251e87848151811061251157612511614b4a565b6020026020010151612c89565b81525082828151811061253357612533614b4a565b60209081029190910101526001016124ca565b509392505050565b6000606081808061255e87612c9c565b905060008660405160200161257591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152606080835260208301529150600090819060005b8c51811015612bd4578c81815181106125d5576125d5614b4a565b6020026020010151915082846125eb9190614a8f565b93506125f8600188614a8f565b9650836000036126b357815180516020918201206040516126489261262292910190815260200190565b604051602081830303815290604052868051602091820120825192909101919091201490565b6126ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016105aa565b61280a565b81515160201161276957815180516020918201206040516126dd9261262292910190815260200190565b6126ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c20686173680000000000000000000000000000000000000000000000000060648201526084016105aa565b81518551602080880191909120825191909201201461280a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f652068617368000000000000000000000000000000000000000000000000000060648201526084016105aa565b61281660106001614a8f565b826020015151036128885785518414612bd457600086858151811061283d5761283d614b4a565b602001015160f81c60f81b60f81c9050600083602001518260ff168151811061286857612868614b4a565b6020026020010151905061287b81612e37565b9650600194505050612bc2565b600282602001515103612b3a5760006128a083612e5c565b90506000816000815181106128b7576128b7614b4a565b016020015160f81c905060006128ce600283614b79565b6128d9906002614b9b565b905060006128ea848360ff16612e80565b905060006128f88b8a612e80565b905060006129068383612eb6565b905082518251101561299a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a20696e76616c6964206b6579206c656e677468206660448201527f6f72206c656166206f7220657874656e73696f6e206e6f64650000000000000060648201526084016105aa565b60ff8516600214806129af575060ff85166003145b15612a19578083511480156129c45750808251145b156129d6576129d3818b614a8f565b99505b6040518060400160405280600181526020017f80000000000000000000000000000000000000000000000000000000000000008152509a50505050505050612bd4565b60ff85161580612a2c575060ff85166001145b15612ab25782518114612a7c576040518060400160405280600181526020017f80000000000000000000000000000000000000000000000000000000000000008152509a50505050505050612bd4565b612aa38860200151600181518110612a9657612a96614b4a565b6020026020010151612e37565b9a509750612bc2945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e20707265666978000000000000000000000000000060648201526084016105aa565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f646500000000000000000000000000000000000000000000000060648201526084016105aa565b80612bcc81614aa7565b9150506125ba565b5085612be08685612e80565b60408051808201909152600181527f80000000000000000000000000000000000000000000000000000000000000006020918201528651908701207f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4211498509850985050505050505093509350939050565b602081015180516060916118ca91612c6c906001906145c0565b81518110612c7c57612c7c614b4a565b6020026020010151612f65565b60606118ca612c97836130c5565b6131ae565b80516060906000612cae826002614812565b67ffffffffffffffff811115612cc657612cc661410e565b6040519080825280601f01601f191660200182016040528015612cf0576020820181803683370190505b5090506000805b83811015612e2d57858181518110612d1157612d11614b4a565b6020910101517fff000000000000000000000000000000000000000000000000000000000000008116925060041c7f0ff00000000000000000000000000000000000000000000000000000000000001683612d6d836002614812565b81518110612d7d57612d7d614b4a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f0f00000000000000000000000000000000000000000000000000000000000000821683612ddb836002614812565b612de6906001614a8f565b81518110612df657612df6614b4a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101612cf7565b5090949350505050565b60606020826000015110612e5357612e4e82612f65565b6118ca565b6118ca82613412565b60606118ca612e7b8360200151600081518110612c7c57612c7c614b4a565b612c9c565b606082518210612e9f57506040805160208101909152600081526118ca565b61190f8383848651612eb191906145c0565b613428565b60008060008351855110612ecb578351612ece565b84515b90505b8082108015612f555750838281518110612eed57612eed614b4a565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916858381518110612f2c57612f2c614b4a565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561254657816001019150612ed1565b60606000806000612f7585613600565b919450925090506000816001811115612f9057612f90614bbe565b1461301d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d0000000000000060648201526084016105aa565b6130278284614a8f565b8551146130b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e64657200000000000000000000000060648201526084016105aa565b611ade8560200151848461406d565b60408051808201909152600080825260208201526000825111613190576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016105aa565b50604080518082019091528151815260209182019181019190915290565b606060008060006131be85613600565b9194509250905060018160018111156131d9576131d9614bbe565b14613266576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d000000000000000060648201526084016105aa565b84516132728385614a8f565b146132ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e646572000000000000000000000000000060648201526084016105aa565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816133185790505090506000845b87518110156134065760008061338b6040518060400160405280858d6000015161336f91906145c0565b8152602001858d602001516133849190614a8f565b9052613600565b5091509150604051806040016040528083836133a79190614a8f565b8152602001848c602001516133bc9190614a8f565b8152508585815181106133d1576133d1614b4a565b60209081029190910101526133e7600185614a8f565b93506133f38183614a8f565b6133fd9084614a8f565b92505050613345565b50815295945050505050565b60606118ca82602001516000846000015161406d565b60608182601f011015613497576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016105aa565b828284011015613503576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016105aa565b81830184511015613570576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016105aa565b60608215801561358f57604051915060008252602082016040526135f7565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156135c85780518352602092830192016135b0565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6000806000808460000151116136be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016105aa565b6020840151805160001a607f81116136e3576000600160009450945094505050614066565b60b781116138f15760006136f86080836145c0565b9050808760000151116137b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a4016105aa565b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214158061382c57507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b6138de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a4016105aa565b5060019550935060009250614066915050565b60bf8111613c3f57600061390660b7836145c0565b9050808760000151116139c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a4016105aa565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613a9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a4016105aa565b600184015160088302610100031c60378111613b63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a4016105aa565b613b6d8184614a8f565b895111613c22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a4016105aa565b613c2d836001614a8f565b97509550600094506140669350505050565b60f78111613d20576000613c5460c0836145c0565b905080876000015111613d0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a4016105aa565b600195509350849250614066915050565b6000613d2d60f7836145c0565b905080876000015111613de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a4016105aa565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613ec6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a4016105aa565b600184015160088302610100031c60378111613f8a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a4016105aa565b613f948184614a8f565b895111614049576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a4016105aa565b614054836001614a8f565b97509550600194506140669350505050565b9193909250565b606060008267ffffffffffffffff81111561408a5761408a61410e565b6040519080825280601f01601f1916602001820160405280156140b4576020820181803683370190505b509050826000036140c657905061190f565b60006140d28587614a8f565b90506020820160005b858110156140f35782810151828201526020016140db565b85811115614102576000868301525b50919695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156141845761418461410e565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146141b057600080fd5b919050565b600082601f8301126141c657600080fd5b813567ffffffffffffffff8111156141e0576141e061410e565b61421160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161413d565b81815284602083860101111561422657600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561425557600080fd5b60405160c0810167ffffffffffffffff82821081831117156142795761427961410e565b81604052829350843583526142906020860161418c565b60208401526142a16040860161418c565b6040840152606085013560608401526080850135608084015260a08501359150808211156142ce57600080fd5b506142db858286016141b5565b60a0830152505092915050565b600080600080600085870360e081121561430157600080fd5b863567ffffffffffffffff8082111561431957600080fd5b6143258a838b01614243565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561435e57600080fd5b60408901955060c089013592508083111561437857600080fd5b828901925089601f84011261438c57600080fd5b823591508082111561439d57600080fd5b508860208260051b84010111156143b357600080fd5b959894975092955050506020019190565b60005b838110156143df5781810151838201526020016143c7565b838111156143ee576000848401525b50505050565b6000815180845261440c8160208601602086016143c4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061190f60208301846143f4565b60006020828403121561446357600080fd5b813567ffffffffffffffff81111561447a57600080fd5b611c1c84828501614243565b60006020828403121561449857600080fd5b5035919050565b600080600080600060a086880312156144b757600080fd5b6144c08661418c565b945060208601359350604086013567ffffffffffffffff80821682146144e557600080fd5b90935060608701359081151582146144fc57600080fd5b9092506080870135908082111561451257600080fd5b5061451f888289016141b5565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516145808160498501602087016143c4565b919091016049019695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156145d2576145d2614591565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614615576146156145d7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561466957614669614591565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156146a8576146a8614591565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156146dc576146dc614591565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561472357614723614591565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561475e5761475e614591565b6000871292508782058712848416161561477a5761477a614591565b8785058712818416161561479057614790614591565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156147d8576147d8614591565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561480c5761480c614591565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561484a5761484a614591565b500290565b600067ffffffffffffffff80831681851680830382111561487257614872614591565b01949350505050565b60006fffffffffffffffffffffffffffffffff808316818516818304811182151516156148aa576148aa614591565b02949350505050565b6000826148c2576148c26145d7565b500490565b6000604082840312156148d957600080fd5b6040516040810181811067ffffffffffffffff821117156148fc576148fc61410e565b604052825181526020928301519281019290925250919050565b60006080828403121561492857600080fd5b6040516080810181811067ffffffffffffffff8211171561494b5761494b61410e565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff808411156149975761499761410e565b8360051b60206149a881830161413d565b8681529185019181810190368411156149c057600080fd5b865b848110156149f4578035868111156149da5760008081fd5b6149e636828b016141b5565b8452509183019183016149c2565b50979650505050505050565b60008451614a128184602089016143c4565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551614a4e816001850160208a016143c4565b60019201918201528351614a698160028401602088016143c4565b0160020195945050505050565b600060208284031215614a8857600080fd5b5051919050565b60008219821115614aa257614aa2614591565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614ad857614ad8614591565b5060010190565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152614b2a60c08301846143f4565b98975050505050505050565b600082614b4557614b456145d7565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680614b8c57614b8c6145d7565b8060ff84160691505092915050565b600060ff821660ff841680821015614bb557614bb5614591565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", } // OptimismPortalABI is the input ABI used to generate the binding from. @@ -610,6 +610,56 @@ func (_OptimismPortal *OptimismPortalCallerSession) Params() (struct { return _OptimismPortal.Contract.Params(&_OptimismPortal.CallOpts) } +// ProvenWithdrawals is a free data retrieval call binding the contract method 0xe965084c. +// +// Solidity: function provenWithdrawals(bytes32 ) view returns(bytes32 outputRoot, uint128 timestamp, uint128 l2BlockNumber) +func (_OptimismPortal *OptimismPortalCaller) ProvenWithdrawals(opts *bind.CallOpts, arg0 [32]byte) (struct { + OutputRoot [32]byte + Timestamp *big.Int + L2BlockNumber *big.Int +}, error) { + var out []interface{} + err := _OptimismPortal.contract.Call(opts, &out, "provenWithdrawals", arg0) + + outstruct := new(struct { + OutputRoot [32]byte + Timestamp *big.Int + L2BlockNumber *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.OutputRoot = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + outstruct.Timestamp = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.L2BlockNumber = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// ProvenWithdrawals is a free data retrieval call binding the contract method 0xe965084c. +// +// Solidity: function provenWithdrawals(bytes32 ) view returns(bytes32 outputRoot, uint128 timestamp, uint128 l2BlockNumber) +func (_OptimismPortal *OptimismPortalSession) ProvenWithdrawals(arg0 [32]byte) (struct { + OutputRoot [32]byte + Timestamp *big.Int + L2BlockNumber *big.Int +}, error) { + return _OptimismPortal.Contract.ProvenWithdrawals(&_OptimismPortal.CallOpts, arg0) +} + +// ProvenWithdrawals is a free data retrieval call binding the contract method 0xe965084c. +// +// Solidity: function provenWithdrawals(bytes32 ) view returns(bytes32 outputRoot, uint128 timestamp, uint128 l2BlockNumber) +func (_OptimismPortal *OptimismPortalCallerSession) ProvenWithdrawals(arg0 [32]byte) (struct { + OutputRoot [32]byte + Timestamp *big.Int + L2BlockNumber *big.Int +}, error) { + return _OptimismPortal.Contract.ProvenWithdrawals(&_OptimismPortal.CallOpts, arg0) +} + // Version is a free data retrieval call binding the contract method 0x54fd4d50. // // Solidity: function version() view returns(string) @@ -683,25 +733,25 @@ func (_OptimismPortal *OptimismPortalTransactorSession) DonateETH() (*types.Tran return _OptimismPortal.Contract.DonateETH(&_OptimismPortal.TransactOpts) } -// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0x683d95c8. +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0x8c3152e9. // -// Solidity: function finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx, uint256 _l2BlockNumber, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes[] _withdrawalProof) returns() -func (_OptimismPortal *OptimismPortalTransactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _tx TypesWithdrawalTransaction, _l2BlockNumber *big.Int, _outputRootProof TypesOutputRootProof, _withdrawalProof [][]byte) (*types.Transaction, error) { - return _OptimismPortal.contract.Transact(opts, "finalizeWithdrawalTransaction", _tx, _l2BlockNumber, _outputRootProof, _withdrawalProof) +// Solidity: function finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx) returns() +func (_OptimismPortal *OptimismPortalTransactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _tx TypesWithdrawalTransaction) (*types.Transaction, error) { + return _OptimismPortal.contract.Transact(opts, "finalizeWithdrawalTransaction", _tx) } -// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0x683d95c8. +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0x8c3152e9. // -// Solidity: function finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx, uint256 _l2BlockNumber, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes[] _withdrawalProof) returns() -func (_OptimismPortal *OptimismPortalSession) FinalizeWithdrawalTransaction(_tx TypesWithdrawalTransaction, _l2BlockNumber *big.Int, _outputRootProof TypesOutputRootProof, _withdrawalProof [][]byte) (*types.Transaction, error) { - return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _tx, _l2BlockNumber, _outputRootProof, _withdrawalProof) +// Solidity: function finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx) returns() +func (_OptimismPortal *OptimismPortalSession) FinalizeWithdrawalTransaction(_tx TypesWithdrawalTransaction) (*types.Transaction, error) { + return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _tx) } -// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0x683d95c8. +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0x8c3152e9. // -// Solidity: function finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx, uint256 _l2BlockNumber, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes[] _withdrawalProof) returns() -func (_OptimismPortal *OptimismPortalTransactorSession) FinalizeWithdrawalTransaction(_tx TypesWithdrawalTransaction, _l2BlockNumber *big.Int, _outputRootProof TypesOutputRootProof, _withdrawalProof [][]byte) (*types.Transaction, error) { - return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _tx, _l2BlockNumber, _outputRootProof, _withdrawalProof) +// Solidity: function finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx) returns() +func (_OptimismPortal *OptimismPortalTransactorSession) FinalizeWithdrawalTransaction(_tx TypesWithdrawalTransaction) (*types.Transaction, error) { + return _OptimismPortal.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal.TransactOpts, _tx) } // Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. @@ -725,6 +775,27 @@ func (_OptimismPortal *OptimismPortalTransactorSession) Initialize() (*types.Tra return _OptimismPortal.Contract.Initialize(&_OptimismPortal.TransactOpts) } +// ProveWithdrawalTransaction is a paid mutator transaction binding the contract method 0x4870496f. +// +// Solidity: function proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx, uint256 _l2BlockNumber, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes[] _withdrawalProof) returns() +func (_OptimismPortal *OptimismPortalTransactor) ProveWithdrawalTransaction(opts *bind.TransactOpts, _tx TypesWithdrawalTransaction, _l2BlockNumber *big.Int, _outputRootProof TypesOutputRootProof, _withdrawalProof [][]byte) (*types.Transaction, error) { + return _OptimismPortal.contract.Transact(opts, "proveWithdrawalTransaction", _tx, _l2BlockNumber, _outputRootProof, _withdrawalProof) +} + +// ProveWithdrawalTransaction is a paid mutator transaction binding the contract method 0x4870496f. +// +// Solidity: function proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx, uint256 _l2BlockNumber, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes[] _withdrawalProof) returns() +func (_OptimismPortal *OptimismPortalSession) ProveWithdrawalTransaction(_tx TypesWithdrawalTransaction, _l2BlockNumber *big.Int, _outputRootProof TypesOutputRootProof, _withdrawalProof [][]byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.ProveWithdrawalTransaction(&_OptimismPortal.TransactOpts, _tx, _l2BlockNumber, _outputRootProof, _withdrawalProof) +} + +// ProveWithdrawalTransaction is a paid mutator transaction binding the contract method 0x4870496f. +// +// Solidity: function proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx, uint256 _l2BlockNumber, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes[] _withdrawalProof) returns() +func (_OptimismPortal *OptimismPortalTransactorSession) ProveWithdrawalTransaction(_tx TypesWithdrawalTransaction, _l2BlockNumber *big.Int, _outputRootProof TypesOutputRootProof, _withdrawalProof [][]byte) (*types.Transaction, error) { + return _OptimismPortal.Contract.ProveWithdrawalTransaction(&_OptimismPortal.TransactOpts, _tx, _l2BlockNumber, _outputRootProof, _withdrawalProof) +} + // Receive is a paid mutator transaction binding the contract receive function. // // Solidity: receive() payable returns() @@ -1187,3 +1258,165 @@ func (_OptimismPortal *OptimismPortalFilterer) ParseWithdrawalFinalized(log type event.Raw = log return event, nil } + +// OptimismPortalWithdrawalProvenIterator is returned from FilterWithdrawalProven and is used to iterate over the raw logs and unpacked data for WithdrawalProven events raised by the OptimismPortal contract. +type OptimismPortalWithdrawalProvenIterator struct { + Event *OptimismPortalWithdrawalProven // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *OptimismPortalWithdrawalProvenIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(OptimismPortalWithdrawalProven) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(OptimismPortalWithdrawalProven) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *OptimismPortalWithdrawalProvenIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OptimismPortalWithdrawalProvenIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OptimismPortalWithdrawalProven represents a WithdrawalProven event raised by the OptimismPortal contract. +type OptimismPortalWithdrawalProven struct { + WithdrawalHash [32]byte + From common.Address + To common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWithdrawalProven is a free log retrieval operation binding the contract event 0x67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f62. +// +// Solidity: event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to) +func (_OptimismPortal *OptimismPortalFilterer) FilterWithdrawalProven(opts *bind.FilterOpts, withdrawalHash [][32]byte, from []common.Address, to []common.Address) (*OptimismPortalWithdrawalProvenIterator, error) { + + var withdrawalHashRule []interface{} + for _, withdrawalHashItem := range withdrawalHash { + withdrawalHashRule = append(withdrawalHashRule, withdrawalHashItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _OptimismPortal.contract.FilterLogs(opts, "WithdrawalProven", withdrawalHashRule, fromRule, toRule) + if err != nil { + return nil, err + } + return &OptimismPortalWithdrawalProvenIterator{contract: _OptimismPortal.contract, event: "WithdrawalProven", logs: logs, sub: sub}, nil +} + +// WatchWithdrawalProven is a free log subscription operation binding the contract event 0x67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f62. +// +// Solidity: event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to) +func (_OptimismPortal *OptimismPortalFilterer) WatchWithdrawalProven(opts *bind.WatchOpts, sink chan<- *OptimismPortalWithdrawalProven, withdrawalHash [][32]byte, from []common.Address, to []common.Address) (event.Subscription, error) { + + var withdrawalHashRule []interface{} + for _, withdrawalHashItem := range withdrawalHash { + withdrawalHashRule = append(withdrawalHashRule, withdrawalHashItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _OptimismPortal.contract.WatchLogs(opts, "WithdrawalProven", withdrawalHashRule, fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(OptimismPortalWithdrawalProven) + if err := _OptimismPortal.contract.UnpackLog(event, "WithdrawalProven", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseWithdrawalProven is a log parse operation binding the contract event 0x67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f62. +// +// Solidity: event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to) +func (_OptimismPortal *OptimismPortalFilterer) ParseWithdrawalProven(log types.Log) (*OptimismPortalWithdrawalProven, error) { + event := new(OptimismPortalWithdrawalProven) + if err := _OptimismPortal.contract.UnpackLog(event, "WithdrawalProven", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/op-bindings/bindings/optimismportal_more.go b/op-bindings/bindings/optimismportal_more.go index 12a16acf6f544..829d08722b256 100644 --- a/op-bindings/bindings/optimismportal_more.go +++ b/op-bindings/bindings/optimismportal_more.go @@ -9,11 +9,11 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const OptimismPortalStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"params\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_struct(ResourceParams)1007_storage\"},{\"astId\":1003,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_uint256)1006_storage\"},{\"astId\":1004,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"l2Sender\",\"offset\":0,\"slot\":\"50\",\"type\":\"t_address\"},{\"astId\":1005,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"finalizedWithdrawals\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_mapping(t_bytes32,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)1006_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[48]\",\"numberOfBytes\":\"1536\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_struct(ResourceParams)1007_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ResourceMetering.ResourceParams\",\"numberOfBytes\":\"32\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}" +const OptimismPortalStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"params\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_struct(ResourceParams)1009_storage\"},{\"astId\":1003,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_uint256)1007_storage\"},{\"astId\":1004,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"l2Sender\",\"offset\":0,\"slot\":\"50\",\"type\":\"t_address\"},{\"astId\":1005,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"finalizedWithdrawals\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":1006,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"provenWithdrawals\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_mapping(t_bytes32,t_struct(ProvenWithdrawal)1008_storage)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)1007_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[48]\",\"numberOfBytes\":\"1536\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_mapping(t_bytes32,t_struct(ProvenWithdrawal)1008_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e struct OptimismPortal.ProvenWithdrawal)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_struct(ProvenWithdrawal)1008_storage\"},\"t_struct(ProvenWithdrawal)1008_storage\":{\"encoding\":\"inplace\",\"label\":\"struct OptimismPortal.ProvenWithdrawal\",\"numberOfBytes\":\"64\"},\"t_struct(ResourceParams)1009_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ResourceMetering.ResourceParams\",\"numberOfBytes\":\"32\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}" var OptimismPortalStorageLayout = new(solc.StorageLayout) -var OptimismPortalDeployedBin = "0x6080604052600436106101115760003560e01c80638b4c40b0116100a5578063ca3e99ba11610074578063cff0ab9611610059578063cff0ab9614610332578063e9e05c42146103d3578063f4daa291146103e657600080fd5b8063ca3e99ba14610308578063cd7c97891461031d57600080fd5b80638b4c40b0146101365780639bf62d821461027b578063a14238e7146102a8578063c4fc4798146102e857600080fd5b8063683d95c8116100e1578063683d95c81461021b5780636bb0291e1461023b5780638129fc1c14610250578063867ead131461026557600080fd5b80621c2ff61461013d57806313620abd1461019b57806354fd4d50146101d457806364b79208146101f657600080fd5b36610138576101363334620186a060006040518060200160405280600081525061041a565b005b600080fd5b34801561014957600080fd5b506101717f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101a757600080fd5b506101b3633b9aca0081565b6040516fffffffffffffffffffffffffffffffff9091168152602001610192565b3480156101e057600080fd5b506101e96108e7565b6040516101929190613b25565b34801561020257600080fd5b5061020d627a120081565b604051908152602001610192565b34801561022757600080fd5b50610136610236366004613cfa565b61098a565b34801561024757600080fd5b5061020d600481565b34801561025c57600080fd5b50610136610fe2565b34801561027157600080fd5b5061020d61271081565b34801561028757600080fd5b506032546101719073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b457600080fd5b506102d86102c3366004613dee565b60336020526000908152604090205460ff1681565b6040519015158152602001610192565b3480156102f457600080fd5b506102d8610303366004613dee565b6111a0565b34801561031457600080fd5b5061020d611265565b34801561032957600080fd5b5061020d600881565b34801561033e57600080fd5b5060015461039a906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff9283166020850152911690820152606001610192565b6101366103e1366004613e07565b61041a565b3480156103f257600080fd5b5061020d7f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156104d15773ffffffffffffffffffffffffffffffffffffffff8716156104d157604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b333281146104f2575033731111000000000000000000000000000000001111015b6000348888888860405160200161050d959493929190613e94565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161057d9190613b25565b60405180910390a450506001546000906105bd907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643613f28565b905080156107465760006105d56004627a1200613f6e565b6001546106009190700100000000000000000000000000000000900467ffffffffffffffff16613fd6565b9050600060086106146004627a1200613f6e565b6001546106349085906fffffffffffffffffffffffffffffffff1661404a565b61063e9190613f6e565b6106489190613f6e565b6001549091506000906106949061067e906106769085906fffffffffffffffffffffffffffffffff16614106565b612710611292565b6fffffffffffffffffffffffffffffffff6112ad565b905060018411156107075761070461067e670de0b6b3a76400006106f06106bc600883613f6e565b6106ce90670de0b6b3a7640000613fd6565b6106d960018a613f28565b6106eb90670de0b6b3a764000061417a565b6112bc565b6106fa908561404a565b6106769190613f6e565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054849190601090610779908490700100000000000000000000000000000000900467ffffffffffffffff166141b7565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315610855576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d6974000060648201526084016104c8565b600154600090610881906fffffffffffffffffffffffffffffffff1667ffffffffffffffff86166141e3565b6fffffffffffffffffffffffffffffffff16905060006108a548633b9aca006112ed565b6108af908361421b565b905060005a6108be9086613f28565b9050808211156108da576108da6108d58284613f28565b6112fd565b5050505050505050505050565b60606109127f000000000000000000000000000000000000000000000000000000000000000061132b565b61093b7f000000000000000000000000000000000000000000000000000000000000000061132b565b6109647f000000000000000000000000000000000000000000000000000000000000000061132b565b6040516020016109769392919061422f565b604051602081830303815290604052905090565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610a33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e0060648201526084016104c8565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610af2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e74726163740060648201526084016104c8565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610b7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba391906142a5565b9050610bae81611468565b610c3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4f7074696d69736d506f7274616c3a2070726f706f73616c206973206e6f742060448201527f7965742066696e616c697a65640000000000000000000000000000000000000060648201526084016104c8565b610c51610c4c368690038601866142f4565b6114a2565b815114610ce0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084016104c8565b6000610ceb876114fe565b9050610d05816040870135610d00868861435a565b61152e565b610d91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f66000000000000000000000000000060648201526084016104c8565b60008181526033602052604090205460ff1615610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a6564000000000000000000000060648201526084016104c8565b600081815260336020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556080870151610e7990614e20906143de565b5a1015610f08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c00000000000000000060648201526084016104c8565b8660200151603260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000610f6b886040015189608001518a606001518b60a001516115f5565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610fd090841515815260200190565b60405180910390a25050505050505050565b600054610100900460ff16158080156110025750600054600160ff909116105b8061101c5750303b15801561101c575060005460ff166001145b6110a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104c8565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561110657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905561113a61160f565b801561119d57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101829052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa15801561122f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125391906142a5565b905061125e81611468565b9392505050565b6112736004627a1200613f6e565b81565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000818312156112a257816112a4565b825b90505b92915050565b60008183126112a257816112a4565b60006112a4670de0b6b3a7640000836112d4866116f2565b6112de919061404a565b6112e89190613f6e565b611936565b6000818310156112a257816112a4565b6000805a90505b825a6113109083613f28565b10156113265761131f826143f6565b9150611304565b505050565b60608160000361136e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156113985780611382816143f6565b91506113919050600a8361421b565b9150611372565b60008167ffffffffffffffff8111156113b3576113b3613b38565b6040519080825280601f01601f1916602001820160405280156113dd576020820181803683370190505b5090505b8415611460576113f2600183613f28565b91506113ff600a8661442e565b61140a9060306143de565b60f81b81838151811061141f5761141f614442565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611459600a8661421b565b94506113e1565b949350505050565b60007f0000000000000000000000000000000000000000000000000000000000000000826020015161149a91906143de565b421192915050565b600081600001518260200151836040015184606001516040516020016114e1949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a088015193516000976114e1979096959101614471565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506115ec9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152908587611b75565b95945050505050565b600080600080845160208601878a8af19695505050505050565b600054610100900460ff166116a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016104c8565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b600080821361175d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104c8565b6000606061176a84611b99565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361196757506000919050565b680755bf798b4a1bf1e582126119d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f57000000000000000000000000000000000000000060448201526064016104c8565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b600080611b8186611c6f565b9050611b8f81868686611ca1565b9695505050505050565b6000808211611c04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016104c8565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60608180519060200120604051602001611c8b91815260200190565b6040516020818303038152906040529050919050565b6000806000611cb1878686611cde565b91509150818015611cd357508051602080830191909120875191880191909120145b979650505050505050565b600060606000611ced85611dfc565b90506000806000611cff848a89611eeb565b81519295509093509150158080611d135750815b611d9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2070726f76696465642070726f6f6620697320696e60448201527f76616c696400000000000000000000000000000000000000000000000000000060648201526084016104c8565b600081611dbb5760405180602001604052806000815250611de7565b611de786611dca600188613f28565b81518110611dda57611dda614442565b60200260200101516125ef565b805115159c909b509950505050505050505050565b805160609060008167ffffffffffffffff811115611e1c57611e1c613b38565b604051908082528060200260200182016040528015611e6157816020015b6040805180820190915260608082526020820152815260200190600190039081611e3a5790505b50905060005b82811015611ee3576040518060400160405280868381518110611e8c57611e8c614442565b60200260200101518152602001611ebb878481518110611eae57611eae614442565b6020026020010151612626565b815250828281518110611ed057611ed0614442565b6020908102919091010152600101611e67565b509392505050565b60006060818080611efb87612639565b9050600086604051602001611f1291815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152606080835260208301529150600090819060005b8c51811015612571578c8181518110611f7257611f72614442565b602002602001015191508284611f8891906143de565b9350611f956001886143de565b9650836000036120505781518051602091820120604051611fe592611fbf92910190815260200190565b604051602081830303815290604052868051602091820120825192909101919091201490565b61204b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016104c8565b6121a7565b815151602011612106578151805160209182012060405161207a92611fbf92910190815260200190565b61204b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c20686173680000000000000000000000000000000000000000000000000060648201526084016104c8565b8151855160208088019190912082519190920120146121a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f652068617368000000000000000000000000000000000000000000000000000060648201526084016104c8565b6121b3601060016143de565b8260200151510361222557855184146125715760008685815181106121da576121da614442565b602001015160f81c60f81b60f81c9050600083602001518260ff168151811061220557612205614442565b60200260200101519050612218816127d4565b965060019450505061255f565b6002826020015151036124d757600061223d836127f9565b905060008160008151811061225457612254614442565b016020015160f81c9050600061226b6002836144c8565b6122769060026144ea565b90506000612287848360ff1661281d565b905060006122958b8a61281d565b905060006122a38383612853565b9050825182511015612337576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a20696e76616c6964206b6579206c656e677468206660448201527f6f72206c656166206f7220657874656e73696f6e206e6f64650000000000000060648201526084016104c8565b60ff85166002148061234c575060ff85166003145b156123b6578083511480156123615750808251145b1561237357612370818b6143de565b99505b6040518060400160405280600181526020017f80000000000000000000000000000000000000000000000000000000000000008152509a50505050505050612571565b60ff851615806123c9575060ff85166001145b1561244f5782518114612419576040518060400160405280600181526020017f80000000000000000000000000000000000000000000000000000000000000008152509a50505050505050612571565b612440886020015160018151811061243357612433614442565b60200260200101516127d4565b9a50975061255f945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e20707265666978000000000000000000000000000060648201526084016104c8565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f646500000000000000000000000000000000000000000000000060648201526084016104c8565b80612569816143f6565b915050611f57565b508561257d868561281d565b60408051808201909152600181527f80000000000000000000000000000000000000000000000000000000000000006020918201528651908701207f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4211498509850985050505050505093509350939050565b602081015180516060916112a79161260990600190613f28565b8151811061261957612619614442565b6020026020010151612902565b60606112a761263483612a62565b612b4b565b8051606090600061264b82600261417a565b67ffffffffffffffff81111561266357612663613b38565b6040519080825280601f01601f19166020018201604052801561268d576020820181803683370190505b5090506000805b838110156127ca578581815181106126ae576126ae614442565b6020910101517fff000000000000000000000000000000000000000000000000000000000000008116925060041c7f0ff0000000000000000000000000000000000000000000000000000000000000168361270a83600261417a565b8151811061271a5761271a614442565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f0f0000000000000000000000000000000000000000000000000000000000000082168361277883600261417a565b6127839060016143de565b8151811061279357612793614442565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101612694565b5090949350505050565b606060208260000151106127f0576127eb82612902565b6112a7565b6112a782612daf565b60606112a7612818836020015160008151811061261957612619614442565b612639565b60608251821061283c57506040805160208101909152600081526112a7565b6112a4838384865161284e9190613f28565b612dc5565b6000806000835185511061286857835161286b565b84515b90505b80821080156128f2575083828151811061288a5761288a614442565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168583815181106128c9576128c9614442565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15611ee35781600101915061286e565b6060600080600061291285612f9d565b91945092509050600081600181111561292d5761292d61450d565b146129ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d0000000000000060648201526084016104c8565b6129c482846143de565b855114612a53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e64657200000000000000000000000060648201526084016104c8565b6115ec85602001518484613a0a565b60408051808201909152600080825260208201526000825111612b2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016104c8565b50604080518082019091528151815260209182019181019190915290565b60606000806000612b5b85612f9d565b919450925090506001816001811115612b7657612b7661450d565b14612c03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d000000000000000060648201526084016104c8565b8451612c0f83856143de565b14612c9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e646572000000000000000000000000000060648201526084016104c8565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081612cb55790505090506000845b8751811015612da357600080612d286040518060400160405280858d60000151612d0c9190613f28565b8152602001858d60200151612d2191906143de565b9052612f9d565b509150915060405180604001604052808383612d4491906143de565b8152602001848c60200151612d5991906143de565b815250858581518110612d6e57612d6e614442565b6020908102919091010152612d846001856143de565b9350612d9081836143de565b612d9a90846143de565b92505050612ce2565b50815295945050505050565b60606112a7826020015160008460000151613a0a565b60608182601f011015612e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104c8565b828284011015612ea0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016104c8565b81830184511015612f0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016104c8565b606082158015612f2c5760405191506000825260208201604052612f94565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612f65578051835260209283019201612f4d565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60008060008084600001511161305b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016104c8565b6020840151805160001a607f8111613080576000600160009450945094505050613a03565b60b7811161328e576000613095608083613f28565b905080876000015111613150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a4016104c8565b6001838101517fff000000000000000000000000000000000000000000000000000000000000001690821415806131c957507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b61327b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a4016104c8565b5060019550935060009250613a03915050565b60bf81116135dc5760006132a360b783613f28565b90508087600001511161335e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a4016104c8565b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361343c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a4016104c8565b600184015160088302610100031c60378111613500576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a4016104c8565b61350a81846143de565b8951116135bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a4016104c8565b6135ca8360016143de565b9750955060009450613a039350505050565b60f781116136bd5760006135f160c083613f28565b9050808760000151116136ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a4016104c8565b600195509350849250613a03915050565b60006136ca60f783613f28565b905080876000015111613785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a4016104c8565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a4016104c8565b600184015160088302610100031c60378111613927576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a4016104c8565b61393181846143de565b8951116139e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a4016104c8565b6139f18360016143de565b9750955060019450613a039350505050565b9193909250565b606060008267ffffffffffffffff811115613a2757613a27613b38565b6040519080825280601f01601f191660200182016040528015613a51576020820181803683370190505b50905082600003613a6357905061125e565b6000613a6f85876143de565b90506020820160005b85811015613a90578281015182820152602001613a78565b85811115613a9f576000868301525b50919695505050505050565b60005b83811015613ac6578181015183820152602001613aae565b83811115613ad5576000848401525b50505050565b60008151808452613af3816020860160208601613aab565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006112a46020830184613adb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715613b8a57613b8a613b38565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613bd757613bd7613b38565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114613c0357600080fd5b919050565b600082601f830112613c1957600080fd5b813567ffffffffffffffff811115613c3357613c33613b38565b613c6460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613b90565b818152846020838601011115613c7957600080fd5b816020850160208301376000918101602001919091529392505050565b600060808284031215613ca857600080fd5b50919050565b60008083601f840112613cc057600080fd5b50813567ffffffffffffffff811115613cd857600080fd5b6020830191508360208260051b8501011115613cf357600080fd5b9250929050565b600080600080600060e08688031215613d1257600080fd5b853567ffffffffffffffff80821115613d2a57600080fd5b9087019060c0828a031215613d3e57600080fd5b613d46613b67565b82358152613d5660208401613bdf565b6020820152613d6760408401613bdf565b6040820152606083013560608201526080830135608082015260a083013582811115613d9257600080fd5b613d9e8b828601613c08565b60a083015250965060208801359550613dba8960408a01613c96565b945060c0880135915080821115613dd057600080fd5b50613ddd88828901613cae565b969995985093965092949392505050565b600060208284031215613e0057600080fd5b5035919050565b600080600080600060a08688031215613e1f57600080fd5b613e2886613bdf565b945060208601359350604086013567ffffffffffffffff8082168214613e4d57600080fd5b9093506060870135908115158214613e6457600080fd5b90925060808701359080821115613e7a57600080fd5b50613e8788828901613c08565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251613ee8816049850160208701613aab565b919091016049019695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613f3a57613f3a613ef9565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613f7d57613f7d613f3f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615613fd157613fd1613ef9565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561401057614010613ef9565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561404457614044613ef9565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561408b5761408b613ef9565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156140c6576140c6613ef9565b600087129250878205871284841616156140e2576140e2613ef9565b878505871281841616156140f8576140f8613ef9565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561414057614140613ef9565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561417457614174613ef9565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156141b2576141b2613ef9565b500290565b600067ffffffffffffffff8083168185168083038211156141da576141da613ef9565b01949350505050565b60006fffffffffffffffffffffffffffffffff8083168185168183048111821515161561421257614212613ef9565b02949350505050565b60008261422a5761422a613f3f565b500490565b60008451614241818460208901613aab565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161427d816001850160208a01613aab565b60019201918201528351614298816002840160208801613aab565b0160020195945050505050565b6000604082840312156142b757600080fd5b6040516040810181811067ffffffffffffffff821117156142da576142da613b38565b604052825181526020928301519281019290925250919050565b60006080828403121561430657600080fd5b6040516080810181811067ffffffffffffffff8211171561432957614329613b38565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff8084111561437557614375613b38565b8360051b6020614386818301613b90565b86815291850191818101903684111561439e57600080fd5b865b848110156143d2578035868111156143b85760008081fd5b6143c436828b01613c08565b8452509183019183016143a0565b50979650505050505050565b600082198211156143f1576143f1613ef9565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361442757614427613ef9565b5060010190565b60008261443d5761443d613f3f565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526144bc60c0830184613adb565b98975050505050505050565b600060ff8316806144db576144db613f3f565b8060ff84160691505092915050565b600060ff821660ff84168082101561450457614504613ef9565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a" +var OptimismPortalDeployedBin = "0x6080604052600436106101475760003560e01c80638c3152e9116100c0578063cd7c978911610074578063e965084c11610059578063e965084c14610429578063e9e05c42146104b5578063f4daa291146104c857600080fd5b8063cd7c978914610373578063cff0ab961461038857600080fd5b8063a14238e7116100a5578063a14238e7146102fe578063c4fc47981461033e578063ca3e99ba1461035e57600080fd5b80638c3152e9146102b15780639bf62d82146102d157600080fd5b806364b79208116101175780638129fc1c116100fc5780638129fc1c14610286578063867ead131461029b5780638b4c40b01461016c57600080fd5b806364b792081461024c5780636bb0291e1461027157600080fd5b80621c2ff61461017357806313620abd146101d15780634870496f1461020a57806354fd4d501461022a57600080fd5b3661016e5761016c3334620186a06000604051806020016040528060008152506104fc565b005b600080fd5b34801561017f57600080fd5b506101a77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101dd57600080fd5b506101e9633b9aca0081565b6040516fffffffffffffffffffffffffffffffff90911681526020016101c8565b34801561021657600080fd5b5061016c6102253660046142e8565b6109c9565b34801561023657600080fd5b5061023f610d52565b6040516101c8919061443e565b34801561025857600080fd5b50610263627a120081565b6040519081526020016101c8565b34801561027d57600080fd5b50610263600481565b34801561029257600080fd5b5061016c610df5565b3480156102a757600080fd5b5061026361271081565b3480156102bd57600080fd5b5061016c6102cc366004614451565b610fb3565b3480156102dd57600080fd5b506032546101a79073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030a57600080fd5b5061032e610319366004614486565b60336020526000908152604090205460ff1681565b60405190151581526020016101c8565b34801561034a57600080fd5b5061032e610359366004614486565b61180c565b34801561036a57600080fd5b506102636118d0565b34801561037f57600080fd5b50610263600881565b34801561039457600080fd5b506001546103f0906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101c8565b34801561043557600080fd5b50610487610444366004614486565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101c8565b61016c6104c336600461449f565b6104fc565b3480156104d457600080fd5b506102637f000000000000000000000000000000000000000000000000000000000000000081565b8260005a905083156105b35773ffffffffffffffffffffffffffffffffffffffff8716156105b357604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b333281146105d4575033731111000000000000000000000000000000001111015b600034888888886040516020016105ef95949392919061452c565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161065f919061443e565b60405180910390a4505060015460009061069f907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436145c0565b905080156108285760006106b76004627a1200614606565b6001546106e29190700100000000000000000000000000000000900467ffffffffffffffff1661466e565b9050600060086106f66004627a1200614606565b6001546107169085906fffffffffffffffffffffffffffffffff166146e2565b6107209190614606565b61072a9190614606565b60015490915060009061077690610760906107589085906fffffffffffffffffffffffffffffffff1661479e565b6127106118fd565b6fffffffffffffffffffffffffffffffff611916565b905060018411156107e9576107e6610760670de0b6b3a76400006107d261079e600883614606565b6107b090670de0b6b3a764000061466e565b6107bb60018a6145c0565b6107cd90670de0b6b3a7640000614812565b611925565b6107dc90856146e2565b6107589190614606565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805484919060109061085b908490700100000000000000000000000000000000900467ffffffffffffffff1661484f565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550627a1200600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315610937576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d6974000060648201526084016105aa565b600154600090610963906fffffffffffffffffffffffffffffffff1667ffffffffffffffff861661487b565b6fffffffffffffffffffffffffffffffff169050600061098748633b9aca00611956565b61099190836148b3565b905060005a6109a090866145c0565b9050808211156109bc576109bc6109b782846145c0565b611966565b5050505050505050505050565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e74726163740060648201526084016105aa565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015610b15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3991906148c7565b519050610b53610b4e36869003860186614916565b611994565b8114610be1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084016105aa565b6000610bec876119f0565b9050610c06816040870135610c01868861497c565b611a20565b610c92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f66000000000000000000000000000060648201526084016105aa565b604080516060810182528381526fffffffffffffffffffffffffffffffff42811660208084019182528a8316848601908152600087815260348352868120955186559251905184167001000000000000000000000000000000000293169290921760019093019290925589830151908a0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169184917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a450505050505050565b6060610d7d7f0000000000000000000000000000000000000000000000000000000000000000611ae7565b610da67f0000000000000000000000000000000000000000000000000000000000000000611ae7565b610dcf7f0000000000000000000000000000000000000000000000000000000000000000611ae7565b604051602001610de193929190614a00565b604051602081830303815290604052905090565b600054610100900460ff1615808015610e155750600054600160ff909116105b80610e2f5750303b158015610e2f575060005460ff166001145b610ebb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105aa565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f1957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055610f4d611c24565b8015610fb057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461105c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e0060648201526084016105aa565b6000611067826119f0565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e00000000000000000000000000000000000060648201526084016105aa565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166320e9fcd46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e19190614a76565b81602001516fffffffffffffffffffffffffffffffff1610156112ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a4016105aa565b6112cb81602001516fffffffffffffffffffffffffffffffff16611d07565b61137d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a4016105aa565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae557906024016040805180830381865afa158015611421573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144591906148c7565b82518151919250146114ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a4016105aa565b61150c8160200151611d07565b6115be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a4016105aa565b60008381526033602052604090205460ff161561165d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a6564000000000000000000000060648201526084016105aa565b600083815260336020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560808401516116a690614e2090614a8f565b5a1015611735576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a20696e73756666696369656e742067617360448201527f20746f2066696e616c697a65207769746864726177616c00000000000000000060648201526084016105aa565b8360200151603260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060006117988560400151866080015187606001518860a00151611d3b565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906117fd90841515815260200190565b60405180910390a25050505050565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906118ca9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae557906024016040805180830381865afa15801561189d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c191906148c7565b60200151611d07565b92915050565b6118de6004627a1200614606565b81565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60008183121561190d578161190f565b825b9392505050565b600081831261190d578161190f565b600061190f670de0b6b3a76400008361193d86611d55565b61194791906146e2565b6119519190614606565b611f99565b60008183101561190d578161190f565b6000805a90505b825a61197990836145c0565b101561198f5761198882614aa7565b915061196d565b505050565b600081600001518260200151836040015184606001516040516020016119d3949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a088015193516000976119d3979096959101614adf565b604080516020810185905260009181018290528190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250611ade9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529085876121d8565b95945050505050565b606081600003611b2a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611b545780611b3e81614aa7565b9150611b4d9050600a836148b3565b9150611b2e565b60008167ffffffffffffffff811115611b6f57611b6f61410e565b6040519080825280601f01601f191660200182016040528015611b99576020820181803683370190505b5090505b8415611c1c57611bae6001836145c0565b9150611bbb600a86614b36565b611bc6906030614a8f565b60f81b818381518110611bdb57611bdb614b4a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611c15600a866148b3565b9450611b9d565b949350505050565b600054610100900460ff16611cbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105aa565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6000611d337f000000000000000000000000000000000000000000000000000000000000000083614a8f565b421192915050565b600080600080845160208601878a8af19695505050505050565b6000808213611dc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016105aa565b60006060611dcd846121fc565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213611fca57506000919050565b680755bf798b4a1bf1e5821261203c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f57000000000000000000000000000000000000000060448201526064016105aa565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000806121e4866122d2565b90506121f281868686612304565b9695505050505050565b6000808211612267576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016105aa565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606081805190602001206040516020016122ee91815260200190565b6040516020818303038152906040529050919050565b6000806000612314878686612341565b9150915081801561233657508051602080830191909120875191880191909120145b979650505050505050565b6000606060006123508561245f565b90506000806000612362848a8961254e565b815192955090935091501580806123765750815b612402576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2070726f76696465642070726f6f6620697320696e60448201527f76616c696400000000000000000000000000000000000000000000000000000060648201526084016105aa565b60008161241e576040518060200160405280600081525061244a565b61244a8661242d6001886145c0565b8151811061243d5761243d614b4a565b6020026020010151612c52565b805115159c909b509950505050505050505050565b805160609060008167ffffffffffffffff81111561247f5761247f61410e565b6040519080825280602002602001820160405280156124c457816020015b604080518082019091526060808252602082015281526020019060019003908161249d5790505b50905060005b828110156125465760405180604001604052808683815181106124ef576124ef614b4a565b6020026020010151815260200161251e87848151811061251157612511614b4a565b6020026020010151612c89565b81525082828151811061253357612533614b4a565b60209081029190910101526001016124ca565b509392505050565b6000606081808061255e87612c9c565b905060008660405160200161257591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152606080835260208301529150600090819060005b8c51811015612bd4578c81815181106125d5576125d5614b4a565b6020026020010151915082846125eb9190614a8f565b93506125f8600188614a8f565b9650836000036126b357815180516020918201206040516126489261262292910190815260200190565b604051602081830303815290604052868051602091820120825192909101919091201490565b6126ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016105aa565b61280a565b81515160201161276957815180516020918201206040516126dd9261262292910190815260200190565b6126ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c20686173680000000000000000000000000000000000000000000000000060648201526084016105aa565b81518551602080880191909120825191909201201461280a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f652068617368000000000000000000000000000000000000000000000000000060648201526084016105aa565b61281660106001614a8f565b826020015151036128885785518414612bd457600086858151811061283d5761283d614b4a565b602001015160f81c60f81b60f81c9050600083602001518260ff168151811061286857612868614b4a565b6020026020010151905061287b81612e37565b9650600194505050612bc2565b600282602001515103612b3a5760006128a083612e5c565b90506000816000815181106128b7576128b7614b4a565b016020015160f81c905060006128ce600283614b79565b6128d9906002614b9b565b905060006128ea848360ff16612e80565b905060006128f88b8a612e80565b905060006129068383612eb6565b905082518251101561299a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a20696e76616c6964206b6579206c656e677468206660448201527f6f72206c656166206f7220657874656e73696f6e206e6f64650000000000000060648201526084016105aa565b60ff8516600214806129af575060ff85166003145b15612a19578083511480156129c45750808251145b156129d6576129d3818b614a8f565b99505b6040518060400160405280600181526020017f80000000000000000000000000000000000000000000000000000000000000008152509a50505050505050612bd4565b60ff85161580612a2c575060ff85166001145b15612ab25782518114612a7c576040518060400160405280600181526020017f80000000000000000000000000000000000000000000000000000000000000008152509a50505050505050612bd4565b612aa38860200151600181518110612a9657612a96614b4a565b6020026020010151612e37565b9a509750612bc2945050505050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e20707265666978000000000000000000000000000060648201526084016105aa565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f646500000000000000000000000000000000000000000000000060648201526084016105aa565b80612bcc81614aa7565b9150506125ba565b5085612be08685612e80565b60408051808201909152600181527f80000000000000000000000000000000000000000000000000000000000000006020918201528651908701207f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4211498509850985050505050505093509350939050565b602081015180516060916118ca91612c6c906001906145c0565b81518110612c7c57612c7c614b4a565b6020026020010151612f65565b60606118ca612c97836130c5565b6131ae565b80516060906000612cae826002614812565b67ffffffffffffffff811115612cc657612cc661410e565b6040519080825280601f01601f191660200182016040528015612cf0576020820181803683370190505b5090506000805b83811015612e2d57858181518110612d1157612d11614b4a565b6020910101517fff000000000000000000000000000000000000000000000000000000000000008116925060041c7f0ff00000000000000000000000000000000000000000000000000000000000001683612d6d836002614812565b81518110612d7d57612d7d614b4a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f0f00000000000000000000000000000000000000000000000000000000000000821683612ddb836002614812565b612de6906001614a8f565b81518110612df657612df6614b4a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101612cf7565b5090949350505050565b60606020826000015110612e5357612e4e82612f65565b6118ca565b6118ca82613412565b60606118ca612e7b8360200151600081518110612c7c57612c7c614b4a565b612c9c565b606082518210612e9f57506040805160208101909152600081526118ca565b61190f8383848651612eb191906145c0565b613428565b60008060008351855110612ecb578351612ece565b84515b90505b8082108015612f555750838281518110612eed57612eed614b4a565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916858381518110612f2c57612f2c614b4a565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561254657816001019150612ed1565b60606000806000612f7585613600565b919450925090506000816001811115612f9057612f90614bbe565b1461301d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d0000000000000060648201526084016105aa565b6130278284614a8f565b8551146130b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e64657200000000000000000000000060648201526084016105aa565b611ade8560200151848461406d565b60408051808201909152600080825260208201526000825111613190576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016105aa565b50604080518082019091528151815260209182019181019190915290565b606060008060006131be85613600565b9194509250905060018160018111156131d9576131d9614bbe565b14613266576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d000000000000000060648201526084016105aa565b84516132728385614a8f565b146132ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e646572000000000000000000000000000060648201526084016105aa565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816133185790505090506000845b87518110156134065760008061338b6040518060400160405280858d6000015161336f91906145c0565b8152602001858d602001516133849190614a8f565b9052613600565b5091509150604051806040016040528083836133a79190614a8f565b8152602001848c602001516133bc9190614a8f565b8152508585815181106133d1576133d1614b4a565b60209081029190910101526133e7600185614a8f565b93506133f38183614a8f565b6133fd9084614a8f565b92505050613345565b50815295945050505050565b60606118ca82602001516000846000015161406d565b60608182601f011015613497576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016105aa565b828284011015613503576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016105aa565b81830184511015613570576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016105aa565b60608215801561358f57604051915060008252602082016040526135f7565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156135c85780518352602092830192016135b0565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6000806000808460000151116136be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016105aa565b6020840151805160001a607f81116136e3576000600160009450945094505050614066565b60b781116138f15760006136f86080836145c0565b9050808760000151116137b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a4016105aa565b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214158061382c57507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b6138de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a4016105aa565b5060019550935060009250614066915050565b60bf8111613c3f57600061390660b7836145c0565b9050808760000151116139c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a4016105aa565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613a9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a4016105aa565b600184015160088302610100031c60378111613b63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a4016105aa565b613b6d8184614a8f565b895111613c22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a4016105aa565b613c2d836001614a8f565b97509550600094506140669350505050565b60f78111613d20576000613c5460c0836145c0565b905080876000015111613d0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a4016105aa565b600195509350849250614066915050565b6000613d2d60f7836145c0565b905080876000015111613de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a4016105aa565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613ec6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a4016105aa565b600184015160088302610100031c60378111613f8a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a4016105aa565b613f948184614a8f565b895111614049576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a4016105aa565b614054836001614a8f565b97509550600194506140669350505050565b9193909250565b606060008267ffffffffffffffff81111561408a5761408a61410e565b6040519080825280601f01601f1916602001820160405280156140b4576020820181803683370190505b509050826000036140c657905061190f565b60006140d28587614a8f565b90506020820160005b858110156140f35782810151828201526020016140db565b85811115614102576000868301525b50919695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156141845761418461410e565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146141b057600080fd5b919050565b600082601f8301126141c657600080fd5b813567ffffffffffffffff8111156141e0576141e061410e565b61421160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161413d565b81815284602083860101111561422657600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561425557600080fd5b60405160c0810167ffffffffffffffff82821081831117156142795761427961410e565b81604052829350843583526142906020860161418c565b60208401526142a16040860161418c565b6040840152606085013560608401526080850135608084015260a08501359150808211156142ce57600080fd5b506142db858286016141b5565b60a0830152505092915050565b600080600080600085870360e081121561430157600080fd5b863567ffffffffffffffff8082111561431957600080fd5b6143258a838b01614243565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561435e57600080fd5b60408901955060c089013592508083111561437857600080fd5b828901925089601f84011261438c57600080fd5b823591508082111561439d57600080fd5b508860208260051b84010111156143b357600080fd5b959894975092955050506020019190565b60005b838110156143df5781810151838201526020016143c7565b838111156143ee576000848401525b50505050565b6000815180845261440c8160208601602086016143c4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061190f60208301846143f4565b60006020828403121561446357600080fd5b813567ffffffffffffffff81111561447a57600080fd5b611c1c84828501614243565b60006020828403121561449857600080fd5b5035919050565b600080600080600060a086880312156144b757600080fd5b6144c08661418c565b945060208601359350604086013567ffffffffffffffff80821682146144e557600080fd5b90935060608701359081151582146144fc57600080fd5b9092506080870135908082111561451257600080fd5b5061451f888289016141b5565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516145808160498501602087016143c4565b919091016049019695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156145d2576145d2614591565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614615576146156145d7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561466957614669614591565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156146a8576146a8614591565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156146dc576146dc614591565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561472357614723614591565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561475e5761475e614591565b6000871292508782058712848416161561477a5761477a614591565b8785058712818416161561479057614790614591565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156147d8576147d8614591565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561480c5761480c614591565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561484a5761484a614591565b500290565b600067ffffffffffffffff80831681851680830382111561487257614872614591565b01949350505050565b60006fffffffffffffffffffffffffffffffff808316818516818304811182151516156148aa576148aa614591565b02949350505050565b6000826148c2576148c26145d7565b500490565b6000604082840312156148d957600080fd5b6040516040810181811067ffffffffffffffff821117156148fc576148fc61410e565b604052825181526020928301519281019290925250919050565b60006080828403121561492857600080fd5b6040516080810181811067ffffffffffffffff8211171561494b5761494b61410e565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff808411156149975761499761410e565b8360051b60206149a881830161413d565b8681529185019181810190368411156149c057600080fd5b865b848110156149f4578035868111156149da5760008081fd5b6149e636828b016141b5565b8452509183019183016149c2565b50979650505050505050565b60008451614a128184602089016143c4565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551614a4e816001850160208a016143c4565b60019201918201528351614a698160028401602088016143c4565b0160020195945050505050565b600060208284031215614a8857600080fd5b5051919050565b60008219821115614aa257614aa2614591565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614ad857614ad8614591565b5060010190565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152614b2a60c08301846143f4565b98975050505050505050565b600082614b4557614b456145d7565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680614b8c57614b8c6145d7565b8060ff84160691505092915050565b600060ff821660ff841680821015614bb557614bb5614591565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a" func init() { if err := json.Unmarshal([]byte(OptimismPortalStorageLayoutJSON), OptimismPortalStorageLayout); err != nil { diff --git a/op-e2e/actions/user.go b/op-e2e/actions/user.go index fa46ae17a0066..88533e25c53eb 100644 --- a/op-e2e/actions/user.go +++ b/op-e2e/actions/user.go @@ -379,14 +379,68 @@ func (s *CrossLayerUser) Address() common.Address { return s.L1.address } -// ActCompleteWithdrawal creates a L1 withdrawal completion tx for latest withdrawal. +// ActCompleteWithdrawal creates a L1 proveWithdrawal tx for latest withdrawal. +// The tx hash is remembered as the last L1 tx, to check as L1 actor. +func (s *CrossLayerUser) ActProveWithdrawal(t Testing) { + s.L1.lastTxHash = s.ProveWithdrawal(t, s.lastL2WithdrawalTxHash) +} + +// ProveWithdrawal creates a L1 proveWithdrawal tx for the given L2 withdrawal tx, returning the tx hash. +func (s *CrossLayerUser) ProveWithdrawal(t Testing, l2TxHash common.Hash) common.Hash { + // Figure out when our withdrawal was included + receipt := s.L2.CheckReceipt(t, true, l2TxHash) + l2WithdrawalBlock, err := s.L2.env.EthCl.BlockByNumber(t.Ctx(), receipt.BlockNumber) + require.NoError(t, err) + + // Figure out what the Output oracle on L1 has seen so far + l2OutputBlockNr, err := s.L1.env.Bindings.L2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) + require.NoError(t, err) + l2OutputBlock, err := s.L2.env.EthCl.BlockByNumber(t.Ctx(), l2OutputBlockNr) + require.NoError(t, err) + + // Check if the L2 output is even old enough to include the withdrawal + if l2OutputBlock.NumberU64() < l2WithdrawalBlock.NumberU64() { + t.InvalidAction("the latest L2 output is %d and is not past L2 block %d that includes the withdrawal yet, no withdrawal can be proved yet", l2OutputBlock.NumberU64(), l2WithdrawalBlock.NumberU64()) + return common.Hash{} + } + + // We generate a proof for the latest L2 output, which shouldn't require archive-node data if it's recent enough. + header, err := s.L2.env.EthCl.HeaderByNumber(t.Ctx(), l2OutputBlockNr) + require.NoError(t, err) + params, err := withdrawals.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header) + require.NoError(t, err) + + // Create the prove tx + tx, err := s.L1.env.Bindings.OptimismPortal.ProveWithdrawalTransaction( + &s.L1.txOpts, + bindings.TypesWithdrawalTransaction{ + Nonce: params.Nonce, + Sender: params.Sender, + Target: params.Target, + Value: params.Value, + GasLimit: params.GasLimit, + Data: params.Data, + }, + params.BlockNumber, + params.OutputRootProof, + params.WithdrawalProof, + ) + require.NoError(t, err) + + // Send the actual tx (since tx opts don't send by default) + err = s.L1.env.EthCl.SendTransaction(t.Ctx(), tx) + require.NoError(t, err, "must send prove tx") + return tx.Hash() +} + +// ActCompleteWithdrawal creates a L1 withdrawal finalization tx for latest withdrawal. // The tx hash is remembered as the last L1 tx, to check as L1 actor. // The withdrawal functions like CompleteWithdrawal func (s *CrossLayerUser) ActCompleteWithdrawal(t Testing) { s.L1.lastTxHash = s.CompleteWithdrawal(t, s.lastL2WithdrawalTxHash) } -// CompleteWithdrawal creates a L1 withdrawal completion tx for the given L2 withdrawal tx, returning the tx hash. +// CompleteWithdrawal creates a L1 withdrawal finalization tx for the given L2 withdrawal tx, returning the tx hash. // It's an invalid action to attempt to complete a withdrawal that has not passed the L1 finalization period yet func (s *CrossLayerUser) CompleteWithdrawal(t Testing, l2TxHash common.Hash) common.Hash { finalizationPeriod, err := s.L1.env.Bindings.OptimismPortal.FINALIZATIONPERIODSECONDS(&bind.CallOpts{}) @@ -420,9 +474,11 @@ func (s *CrossLayerUser) CompleteWithdrawal(t Testing, l2TxHash common.Hash) com } // We generate a proof for the latest L2 output, which shouldn't require archive-node data if it's recent enough. + // Note that for the `FinalizeWithdrawalTransaction` function, this proof isn't needed. We simply use some of the + // params for the `WithdrawalTransaction` type generated in the bindings. header, err := s.L2.env.EthCl.HeaderByNumber(t.Ctx(), l2OutputBlockNr) require.NoError(t, err) - params, err := withdrawals.FinalizeWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header) + params, err := withdrawals.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header) require.NoError(t, err) // Create the withdrawal tx @@ -436,14 +492,11 @@ func (s *CrossLayerUser) CompleteWithdrawal(t Testing, l2TxHash common.Hash) com GasLimit: params.GasLimit, Data: params.Data, }, - params.BlockNumber, - params.OutputRootProof, - params.WithdrawalProof, ) require.NoError(t, err) // Send the actual tx (since tx opts don't send by default) err = s.L1.env.EthCl.SendTransaction(t.Ctx(), tx) - require.NoError(t, err, "must send tx") + require.NoError(t, err, "must send finalize tx") return tx.Hash() } diff --git a/op-e2e/actions/user_test.go b/op-e2e/actions/user_test.go index 8b3dcd06a7963..31085ba51dc4d 100644 --- a/op-e2e/actions/user_test.go +++ b/op-e2e/actions/user_test.go @@ -17,6 +17,8 @@ import ( // - transact on L2 // - deposit on L1 // - withdraw from L2 +// - prove tx on L1 +// - wait 1 week + 1 second // - finalize withdrawal on L1 func TestCrossLayerUser(gt *testing.T) { t := NewDefaultTesting(gt) @@ -133,7 +135,22 @@ func TestCrossLayerUser(gt *testing.T) { require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "proposal failed") } - // make the L1 side of the withdrawal tx + // prove our withdrawal on L1 + alice.ActProveWithdrawal(t) + // include proved withdrawal in new L1 block + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(alice.Address())(t) + miner.ActL1EndBlock(t) + // check withdrawal succeeded + alice.L1.ActCheckReceiptStatusOfLastTx(true)(t) + + // A bit hacky- Mines an empty block with the time delta + // of the finalization period (12s) + 1 in order for the + // withdrawal to be finalized successfully. + miner.ActL1StartBlock(13)(t) + miner.ActL1EndBlock(t) + + // make the L1 finalize withdrawal tx alice.ActCompleteWithdrawal(t) // include completed withdrawal in new L1 block miner.ActL1StartBlock(12)(t) diff --git a/op-e2e/e2eutils/setup.go b/op-e2e/e2eutils/setup.go index 77362ec48c2fa..8253552a16fd3 100644 --- a/op-e2e/e2eutils/setup.go +++ b/op-e2e/e2eutils/setup.go @@ -85,6 +85,7 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams { L1GenesisBlockGasUsed: 0, L1GenesisBlockParentHash: common.Hash{}, L1GenesisBlockBaseFeePerGas: uint64ToBig(1000_000_000), // 1 gwei + FinalizationPeriodSeconds: 12, L2GenesisBlockNonce: 0, L2GenesisBlockExtraData: []byte{}, diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go index e12c2d1b4e5cd..abe559b80d106 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -817,7 +817,7 @@ func TestWithdrawals(t *testing.T) { startBalance, err = l1Client.BalanceAt(ctx, fromAddr, nil) require.Nil(t, err) - // Wait for finalization and then create the Finalized Withdrawal Transaction + // Get l2BlockNumber for proof generation ctx, cancel = context.WithTimeout(context.Background(), 20*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) defer cancel() blockNumber, err := withdrawals.WaitForFinalizationPeriod(ctx, l1Client, predeploys.DevOptimismPortalAddr, receipt.BlockNumber) @@ -834,14 +834,16 @@ func TestWithdrawals(t *testing.T) { receiptCl := ethclient.NewClient(rpcClient) // Now create withdrawal - params, err := withdrawals.FinalizeWithdrawalParameters(context.Background(), proofCl, receiptCl, tx.Hash(), header) + params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, tx.Hash(), header) require.Nil(t, err) portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client) require.Nil(t, err) opts.Value = nil - tx, err = portal.FinalizeWithdrawalTransaction( + + // Prove withdrawal + tx, err = portal.ProveWithdrawalTransaction( opts, bindings.TypesWithdrawalTransaction{ Nonce: params.Nonce, @@ -855,17 +857,42 @@ func TestWithdrawals(t *testing.T) { params.OutputRootProof, params.WithdrawalProof, ) + require.Nil(t, err) + + // Ensure that our withdrawal was proved successfully + proveReceipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + require.Nil(t, err, "prove withdrawal") + require.Equal(t, types.ReceiptStatusSuccessful, proveReceipt.Status) + // Wait for finalization and then create the Finalized Withdrawal Transaction + ctx, cancel = context.WithTimeout(context.Background(), 20*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + defer cancel() + _, err = withdrawals.WaitForFinalizationPeriod(ctx, l1Client, predeploys.DevOptimismPortalAddr, params.BlockNumber) + require.Nil(t, err) + + // Finalize withdrawal + tx, err = portal.FinalizeWithdrawalTransaction( + opts, + bindings.TypesWithdrawalTransaction{ + Nonce: params.Nonce, + Sender: params.Sender, + Target: params.Target, + Value: params.Value, + GasLimit: params.GasLimit, + Data: params.Data, + }, + ) require.Nil(t, err) - receipt, err = waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + // Ensure that our withdrawal was finalized successfully + finalizeReceipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "finalize withdrawal") - require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) + require.Equal(t, types.ReceiptStatusSuccessful, finalizeReceipt.Status) // Verify balance after withdrawal ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) defer cancel() - header, err = l1Client.HeaderByNumber(ctx, receipt.BlockNumber) + header, err = l1Client.HeaderByNumber(ctx, finalizeReceipt.BlockNumber) require.Nil(t, err) ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) @@ -875,8 +902,9 @@ func TestWithdrawals(t *testing.T) { // Ensure that withdrawal - gas fees are added to the L1 balance // Fun fact, the fee is greater than the withdrawal amount + // NOTE: The gas fees include *both* the ProveWithdrawalTransaction and FinalizeWithdrawalTransaction transactions. diff = new(big.Int).Sub(endBalance, startBalance) - fees = calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) + fees = calcGasFees(proveReceipt.GasUsed+finalizeReceipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) withdrawAmount = withdrawAmount.Sub(withdrawAmount, fees) require.Equal(t, withdrawAmount, diff) } diff --git a/op-node/withdrawals/utils.go b/op-node/withdrawals/utils.go index 07895c4f29040..6766767a96d1b 100644 --- a/op-node/withdrawals/utils.go +++ b/op-node/withdrawals/utils.go @@ -129,8 +129,9 @@ type ReceiptClient interface { TransactionReceipt(context.Context, common.Hash) (*types.Receipt, error) } -// FinalizedWithdrawalParameters is the set of parameters to pass to the FinalizedWithdrawal function -type FinalizedWithdrawalParameters struct { +// ProvenWithdrawalParameters is the set of parameters to pass to the ProveWithdrawalTransaction +// and FinalizeWithdrawalTransaction functions +type ProvenWithdrawalParameters struct { Nonce *big.Int Sender common.Address Target common.Address @@ -142,40 +143,40 @@ type FinalizedWithdrawalParameters struct { WithdrawalProof [][]byte // List of trie nodes to prove L2 storage } -// FinalizeWithdrawalParameters queries L2 to generate all withdrawal parameters and proof necessary to finalize an withdrawal on L1. +// ProveWithdrawalParameters queries L2 to generate all withdrawal parameters and proof necessary to prove a withdrawal on L1. // The header provided is very important. It should be a block (timestamp) for which there is a submitted output in the L2 Output Oracle // contract. If not, the withdrawal will fail as it the storage proof cannot be verified if there is no submitted state root. -func FinalizeWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, txHash common.Hash, header *types.Header) (FinalizedWithdrawalParameters, error) { +func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, txHash common.Hash, header *types.Header) (ProvenWithdrawalParameters, error) { // Transaction receipt receipt, err := l2ReceiptCl.TransactionReceipt(ctx, txHash) if err != nil { - return FinalizedWithdrawalParameters{}, err + return ProvenWithdrawalParameters{}, err } // Parse the receipt ev, err := ParseMessagePassed(receipt) if err != nil { - return FinalizedWithdrawalParameters{}, err + return ProvenWithdrawalParameters{}, err } // Generate then verify the withdrawal proof withdrawalHash, err := WithdrawalHash(ev) if !bytes.Equal(withdrawalHash[:], ev.WithdrawalHash[:]) { - return FinalizedWithdrawalParameters{}, errors.New("Computed withdrawal hash incorrectly") + return ProvenWithdrawalParameters{}, errors.New("Computed withdrawal hash incorrectly") } if err != nil { - return FinalizedWithdrawalParameters{}, err + return ProvenWithdrawalParameters{}, err } slot := StorageSlotOfWithdrawalHash(withdrawalHash) p, err := proofCl.GetProof(ctx, predeploys.L2ToL1MessagePasserAddr, []string{slot.String()}, header.Number) if err != nil { - return FinalizedWithdrawalParameters{}, err + return ProvenWithdrawalParameters{}, err } // TODO: Could skip this step, but it's nice to double check it err = VerifyProof(header.Root, p) if err != nil { - return FinalizedWithdrawalParameters{}, err + return ProvenWithdrawalParameters{}, err } if len(p.StorageProof) != 1 { - return FinalizedWithdrawalParameters{}, errors.New("invalid amount of storage proofs") + return ProvenWithdrawalParameters{}, errors.New("invalid amount of storage proofs") } // Encode it as expected by the contract @@ -184,7 +185,7 @@ func FinalizeWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Re trieNodes[i] = common.FromHex(s) } - return FinalizedWithdrawalParameters{ + return ProvenWithdrawalParameters{ Nonce: ev.Nonce, Sender: ev.Sender, Target: ev.Target, diff --git a/packages/contracts-bedrock/.gas-snapshot b/packages/contracts-bedrock/.gas-snapshot index 0b6818e6a1ac9..a3ae37379c3ae 100644 --- a/packages/contracts-bedrock/.gas-snapshot +++ b/packages/contracts-bedrock/.gas-snapshot @@ -1,17 +1,17 @@ AddressAliasHelper_Test:test_fuzz_roundtrip(address) (runs: 256, μ: 466, ~: 466) -GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_0() (gas: 261401) -GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_1() (gas: 75561) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 348162) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 112340) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 348184) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 112315) +GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_0() (gas: 261393) +GasBenchMark_L1CrossDomainMessenger:test_L1MessengerSendMessage_benchmark_1() (gas: 75533) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 348154) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 112312) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 348176) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 112287) GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 40569) GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 68693) -GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 75010) -GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 35823) +GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 75002) +GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 35795) CrossDomainMessenger_Test:testFuzz_baseGas(uint32) (runs: 256, μ: 20263, ~: 20263) CrossDomainMessenger_Test:test_baseGas() (gas: 20100) -CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner() (gas: 61896) +CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner() (gas: 61888) CrossDomainOwnable_Test:test_onlyOwner() (gas: 34945) CrossDomainOwnable_Test:test_revertOnlyOwner() (gas: 10619) CrossDomainOwnable2_Test:test_onlyOwner() (gas: 77878) @@ -20,9 +20,9 @@ CrossDomainOwnable2_Test:test_revertNotSetOnlyOwner2() (gas: 14598) CrossDomainOwnable2_Test:test_revertOnlyOwner() (gas: 61800) DeployerWhitelist_Test:test_owner() (gas: 7591) DeployerWhitelist_Test:test_storageSlots() (gas: 33427) -Encoding_Test:test_decodeVersionedNonce_differential(uint240,uint16) (runs: 256, μ: 13329, ~: 13345) -Encoding_Test:test_encodeCrossDomainMessage_differential(uint240,uint8,address,address,uint256,uint256,bytes) (runs: 256, μ: 87650, ~: 91649) -Encoding_Test:test_encodeDepositTransaction_differential(address,address,uint256,uint256,uint64,bool,bytes,uint256) (runs: 256, μ: 106526, ~: 101730) +Encoding_Test:test_decodeVersionedNonce_differential(uint240,uint16) (runs: 256, μ: 13351, ~: 13367) +Encoding_Test:test_encodeCrossDomainMessage_differential(uint240,uint8,address,address,uint256,uint256,bytes) (runs: 256, μ: 87476, ~: 91604) +Encoding_Test:test_encodeDepositTransaction_differential(address,address,uint256,uint256,uint64,bool,bytes,uint256) (runs: 256, μ: 106528, ~: 101730) Encoding_Test:test_nonceVersioning(uint240,uint16) (runs: 256, μ: 652, ~: 652) FeeVault_Test:test_constructor() (gas: 10748) FeeVault_Test:test_minWithdrawalAmount() (gas: 10711) @@ -35,9 +35,9 @@ GasPriceOracle_Test:test_setGasPriceReverts() (gas: 5911) GasPriceOracle_Test:test_setL1BaseFeeReverts() (gas: 5954) Hashing_Test:test_hashCrossDomainMessage_differential(uint256,address,address,uint256,uint256,bytes) (runs: 256, μ: 23905, ~: 23788) Hashing_Test:test_hashDepositSource() (gas: 628) -Hashing_Test:test_hashDepositTransaction_differential(address,address,uint256,uint256,uint64,bytes,uint256) (runs: 256, μ: 66710, ~: 66432) -Hashing_Test:test_hashOutputRootProof_differential(bytes32,bytes32,bytes32,bytes32) (runs: 256, μ: 72062, ~: 93483) -Hashing_Test:test_hashWithdrawal_differential(uint256,address,address,uint256,uint256,bytes) (runs: 256, μ: 23654, ~: 23478) +Hashing_Test:test_hashDepositTransaction_differential(address,address,uint256,uint256,uint64,bytes,uint256) (runs: 256, μ: 66644, ~: 66366) +Hashing_Test:test_hashOutputRootProof_differential(bytes32,bytes32,bytes32,bytes32) (runs: 256, μ: 72084, ~: 93505) +Hashing_Test:test_hashWithdrawal_differential(uint256,address,address,uint256,uint256,bytes) (runs: 256, μ: 23676, ~: 23500) L1BlockTest:test_basefee() (gas: 7553) L1BlockTest:test_hash() (gas: 7597) L1BlockTest:test_number() (gas: 7630) @@ -52,23 +52,23 @@ L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 24560) L1CrossDomainMessenger_Test:testCannot_L1MessengerUnpause() (gas: 24518) L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 24738) L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 52972) -L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageFirstStuckSecondSucceeds() (gas: 197363) -L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 190971) -L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 73729) -L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 65858) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageFirstStuckSecondSucceeds() (gas: 197386) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 190994) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 73752) +L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 65881) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageV0Fails() (gas: 33280) L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 60549) L1CrossDomainMessenger_Test:test_L1MessengerReplayMessageWithValue() (gas: 38215) -L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 299555) -L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1490502) +L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 299547) +L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1490486) L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 45233) L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24283) -L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 84115) -L1StandardBridge_DepositERC20To_Test:test_depositERC20To_success() (gas: 575637) -L1StandardBridge_DepositERC20_Test:test_depositERC20_succeeds() (gas: 573505) +L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 84138) +L1StandardBridge_DepositERC20To_Test:test_depositERC20To_success() (gas: 575801) +L1StandardBridge_DepositERC20_Test:test_depositERC20_succeeds() (gas: 573669) L1StandardBridge_DepositERC20_TestFail:test_depositERC20_revert_notEoa() (gas: 22321) -L1StandardBridge_DepositETHTo_Test:test_depositETHTo() (gas: 324769) -L1StandardBridge_DepositETH_Test:test_depositETH_success() (gas: 367616) +L1StandardBridge_DepositETHTo_Test:test_depositETHTo() (gas: 324761) +L1StandardBridge_DepositETH_Test:test_depositETH_success() (gas: 367608) L1StandardBridge_DepositETH_TestFail:test_DepositETH_revert_notEoa() (gas: 40781) L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_revert_incorrectValue() (gas: 34229) L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_revert_sendToMessenger() (gas: 34312) @@ -79,7 +79,7 @@ L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_r L1StandardBridge_FinalizeETHWithdrawal_Test:test_finalizeETHWithdrawal() (gas: 58708) L1StandardBridge_Getter_Test:test_getters_success() (gas: 31568) L1StandardBridge_Initialize_Test:test_initialize_success() (gas: 22072) -L1StandardBridge_Receive_Test:test_receive_success() (gas: 514315) +L1StandardBridge_Receive_Test:test_receive_success() (gas: 514479) L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10860) L2CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 167833) L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8411) @@ -154,33 +154,39 @@ OptimismMintableTokenFactory_Test:test_bridge() (gas: 7672) OptimismMintableTokenFactory_Test:test_createStandardL2Token() (gas: 1109858) OptimismMintableTokenFactory_Test:test_createStandardL2TokenSameTwice() (gas: 2205813) OptimismMintableTokenFactory_Test:test_createStandardL2TokenShouldRevertIfRemoteIsZero() (gas: 9443) -OptimismPortalUpgradeable_Test:test_cannotInitImpl() (gas: 10835) -OptimismPortalUpgradeable_Test:test_cannotInitProxy() (gas: 15811) -OptimismPortalUpgradeable_Test:test_initValuesOnProxy() (gas: 15989) -OptimismPortalUpgradeable_Test:test_upgrading() (gas: 180632) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_differential(address,address,uint256,uint256,bytes) (runs: 256, μ: 234653, ~: 235021) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnInsufficientGas() (gas: 135146) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnInvalidOutputRootProof() (gas: 83661) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnRecentWithdrawal() (gas: 52898) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnReentrancy() (gas: 180409) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnReplay() (gas: 232157) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOnSelfCall() (gas: 52937) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_revertsOninvalidWithdrawalProof() (gas: 132466) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_succeeds() (gas: 164519) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails() (gas: 267168) -OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 17319) -OptimismPortal_Test:test_OptimismPortalContractCreationReverts() (gas: 14245) -OptimismPortal_Test:test_OptimismPortalReceiveEth() (gas: 127534) -OptimismPortal_Test:test_depositTransaction_NoValueContract() (gas: 76714) -OptimismPortal_Test:test_depositTransaction_NoValueEOA() (gas: 77015) -OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract() (gas: 76696) -OptimismPortal_Test:test_depositTransaction_createWithZeroValueForEOA() (gas: 77040) -OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation() (gas: 83740) -OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation() (gas: 75927) -OptimismPortal_Test:test_depositTransaction_withEthValueFromContract() (gas: 83379) -OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA() (gas: 84039) -OptimismPortal_Test:test_isBlockFinalized() (gas: 114183) -OptimismPortal_Test:test_simple_isBlockFinalized() (gas: 24262) +OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 10791) +OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 15834) +OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_success() (gas: 16010) +OptimismPortalUpgradeable_Test:test_upgradeToAndCall_upgrading_success() (gas: 180630) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_differential_success(address,address,uint256,uint256,bytes) (runs: 256, μ: 220459, ~: 220292) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 192857) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 195122) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() (gas: 39628) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 190555) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 193103) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 173032) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 233436) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 232836) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_success() (gas: 224781) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails_fails() (gas: 327453) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 191332) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 81377) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 50821) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_oninvalidWithdrawalProof_reverts() (gas: 130170) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_success() (gas: 176914) +OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 17342) +OptimismPortal_Test:test_OptimismPortalReceiveEth_success() (gas: 127528) +OptimismPortal_Test:test_depositTransaction_NoValueContract_success() (gas: 76728) +OptimismPortal_Test:test_depositTransaction_NoValueEOA_success() (gas: 77006) +OptimismPortal_Test:test_depositTransaction_contractCreation_reverts() (gas: 14224) +OptimismPortal_Test:test_depositTransaction_createWithZeroValueForContract_success() (gas: 76688) +OptimismPortal_Test:test_depositTransaction_createWithZeroValueForEOA_success() (gas: 77076) +OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreation_success() (gas: 83690) +OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation_success() (gas: 75897) +OptimismPortal_Test:test_depositTransaction_withEthValueFromContract_success() (gas: 83414) +OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA_success() (gas: 84009) +OptimismPortal_Test:test_isBlockFinalized_success() (gas: 113932) +OptimismPortal_Test:test_simple_isBlockFinalized_success() (gas: 24222) Proxy_Test:test_clashingFunctionSignatures() (gas: 101427) Proxy_Test:test_implementationKey() (gas: 20942) Proxy_Test:test_implementationProxyCallIfNotAdmin() (gas: 30021) diff --git a/packages/contracts-bedrock/.storage-layout b/packages/contracts-bedrock/.storage-layout index 8d7618f3a04be..3d4c990923ce1 100644 --- a/packages/contracts-bedrock/.storage-layout +++ b/packages/contracts-bedrock/.storage-layout @@ -88,21 +88,23 @@ ➡ contracts/L1/OptimismPortal.sol:OptimismPortal ======================= -+----------------------+----------------------------------------+------+--------+-------+------------------------------------------------+ -| Name | Type | Slot | Offset | Bytes | Contract | -+========================================================================================================================================+ -| _initialized | uint8 | 0 | 0 | 1 | contracts/L1/OptimismPortal.sol:OptimismPortal | -|----------------------+----------------------------------------+------+--------+-------+------------------------------------------------| -| _initializing | bool | 0 | 1 | 1 | contracts/L1/OptimismPortal.sol:OptimismPortal | -|----------------------+----------------------------------------+------+--------+-------+------------------------------------------------| -| params | struct ResourceMetering.ResourceParams | 1 | 0 | 32 | contracts/L1/OptimismPortal.sol:OptimismPortal | -|----------------------+----------------------------------------+------+--------+-------+------------------------------------------------| -| __gap | uint256[48] | 2 | 0 | 1536 | contracts/L1/OptimismPortal.sol:OptimismPortal | -|----------------------+----------------------------------------+------+--------+-------+------------------------------------------------| -| l2Sender | address | 50 | 0 | 20 | contracts/L1/OptimismPortal.sol:OptimismPortal | -|----------------------+----------------------------------------+------+--------+-------+------------------------------------------------| -| finalizedWithdrawals | mapping(bytes32 => bool) | 51 | 0 | 32 | contracts/L1/OptimismPortal.sol:OptimismPortal | -+----------------------+----------------------------------------+------+--------+-------+------------------------------------------------+ ++----------------------+------------------------------------------------------------+------+--------+-------+------------------------------------------------+ +| Name | Type | Slot | Offset | Bytes | Contract | ++============================================================================================================================================================+ +| _initialized | uint8 | 0 | 0 | 1 | contracts/L1/OptimismPortal.sol:OptimismPortal | +|----------------------+------------------------------------------------------------+------+--------+-------+------------------------------------------------| +| _initializing | bool | 0 | 1 | 1 | contracts/L1/OptimismPortal.sol:OptimismPortal | +|----------------------+------------------------------------------------------------+------+--------+-------+------------------------------------------------| +| params | struct ResourceMetering.ResourceParams | 1 | 0 | 32 | contracts/L1/OptimismPortal.sol:OptimismPortal | +|----------------------+------------------------------------------------------------+------+--------+-------+------------------------------------------------| +| __gap | uint256[48] | 2 | 0 | 1536 | contracts/L1/OptimismPortal.sol:OptimismPortal | +|----------------------+------------------------------------------------------------+------+--------+-------+------------------------------------------------| +| l2Sender | address | 50 | 0 | 20 | contracts/L1/OptimismPortal.sol:OptimismPortal | +|----------------------+------------------------------------------------------------+------+--------+-------+------------------------------------------------| +| finalizedWithdrawals | mapping(bytes32 => bool) | 51 | 0 | 32 | contracts/L1/OptimismPortal.sol:OptimismPortal | +|----------------------+------------------------------------------------------------+------+--------+-------+------------------------------------------------| +| provenWithdrawals | mapping(bytes32 => struct OptimismPortal.ProvenWithdrawal) | 52 | 0 | 32 | contracts/L1/OptimismPortal.sol:OptimismPortal | ++----------------------+------------------------------------------------------------+------+--------+-------+------------------------------------------------+ ======================= ➡ contracts/L1/SystemConfig.sol:SystemConfig diff --git a/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol b/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol index 5386307e2e697..ea36944a7370f 100644 --- a/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol +++ b/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol @@ -19,6 +19,15 @@ import { Semver } from "../universal/Semver.sol"; * Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface. */ contract OptimismPortal is Initializable, ResourceMetering, Semver { + /** + * @notice Represents a proven withdrawal + */ + struct ProvenWithdrawal { + bytes32 outputRoot; + uint128 timestamp; + uint128 l2BlockNumber; + } + /** * @notice Version of the deposit event. */ @@ -61,6 +70,11 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { */ mapping(bytes32 => bool) public finalizedWithdrawals; + /** + * @notice A mapping of withdrawal hashes to `ProvenWithdrawal` data. + */ + mapping(bytes32 => ProvenWithdrawal) public provenWithdrawals; + /** * @notice Emitted when a transaction is deposited from L1 to L2. The parameters of this event * are read by the rollup node and used to derive deposit transactions on L2. @@ -77,6 +91,17 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { bytes opaqueData ); + /** + * @notice Emitted when a withdrawal transaction is proven. + * + * @param withdrawalHash Hash of the withdrawal transaction. + */ + event WithdrawalProven( + bytes32 indexed withdrawalHash, + address indexed from, + address indexed to + ); + /** * @notice Emitted when a withdrawal transaction is finalized. * @@ -125,47 +150,38 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { } /** - * @notice Finalizes a withdrawal transaction. + * @notice Proves a withdrawal transaction. * * @param _tx Withdrawal transaction to finalize. * @param _l2BlockNumber L2 block number of the outputRoot. * @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root. * @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract. */ - function finalizeWithdrawalTransaction( + function proveWithdrawalTransaction( Types.WithdrawalTransaction memory _tx, uint256 _l2BlockNumber, Types.OutputRootProof calldata _outputRootProof, bytes[] calldata _withdrawalProof ) external { - // Prevent nested withdrawals within withdrawals. - require( - l2Sender == DEFAULT_L2_SENDER, - "OptimismPortal: can only trigger one withdrawal per transaction" - ); - // Prevent users from creating a deposit transaction where this address is the message // sender on L2. // In the context of the proxy delegate calling to this implementation, // address(this) will return the address of the proxy. + // + // Because this is checked here, we do not need to check again in + // `finalizeWithdrawalTransaction` require( _tx.target != address(this), "OptimismPortal: you cannot send messages to the portal contract" ); - // Get the output root. This will fail if there is no - // output root for the given block number. - Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber); - - // Ensure that enough time has passed since the proposal was submitted before allowing a - // withdrawal. Under the assumption that the fault proof mechanism is operating correctly, - // we can infer that any withdrawal that has passed the finalization period must be valid - // and can therefore be operated on. - require(_isOutputFinalized(proposal), "OptimismPortal: proposal is not yet finalized"); + // Get the output root and load onto the stack to prevent multiple mloads. This will + // fail if there is no output root for the given block number. + bytes32 outputRoot = L2_ORACLE.getL2Output(_l2BlockNumber).outputRoot; // Verify that the output root can be generated with the elements in the proof. require( - proposal.outputRoot == Hashing.hashOutputRootProof(_outputRootProof), + outputRoot == Hashing.hashOutputRootProof(_outputRootProof), "OptimismPortal: invalid output root proof" ); @@ -185,6 +201,73 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { "OptimismPortal: invalid withdrawal inclusion proof" ); + // Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`, + // and `l2BlockNumber` in the `provenWithdrawals` mapping. A certain withdrawal + // can be proved multiple times and thus overwrite a previously stored `ProvenWithdrawal`, + // but this is safe due to the replay check in `finalizeWithdrawalTransaction`. + provenWithdrawals[withdrawalHash] = ProvenWithdrawal({ + outputRoot: outputRoot, + timestamp: uint128(block.timestamp), + l2BlockNumber: uint128(_l2BlockNumber) + }); + + // Emit a `WithdrawalProven` event. + emit WithdrawalProven(withdrawalHash, _tx.sender, _tx.target); + } + + /** + * @notice Finalizes a withdrawal transaction. + * + * @param _tx Withdrawal transaction to finalize. + */ + function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external { + // Prevent nested withdrawals within withdrawals. + require( + l2Sender == DEFAULT_L2_SENDER, + "OptimismPortal: can only trigger one withdrawal per transaction" + ); + + // All withdrawals have a unique hash, we'll use this as the identifier for the withdrawal + // and to prevent replay attacks. + bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx); + + // Grab the proven withdrawal from the `provenWithdrawals` map. + ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash]; + + // Ensure that the withdrawal has been proven + require(provenWithdrawal.timestamp != 0, "OptimismPortal: withdrawal has not been proven"); + + // Ensure that the proven withdrawal's timestamp is greater than the + // L2 Oracle's starting timestamp. + require( + provenWithdrawal.timestamp >= L2_ORACLE.STARTING_TIMESTAMP(), + "OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp" + ); + + // Ensure that the withdrawal's finalization period has elapsed. + require( + _isFinalizationPeriodElapsed(provenWithdrawal.timestamp), + "OptimismPortal: proven withdrawal finalization period has not elapsed" + ); + + // Grab the OutputProposal from the L2 Oracle + Types.OutputProposal memory proposal = L2_ORACLE.getL2Output( + provenWithdrawal.l2BlockNumber + ); + + // Check that the output proposal hasn't been updated. + require( + proposal.outputRoot == provenWithdrawal.outputRoot, + "OptimismPortal: output root proven is not the same as current output root" + ); + + // Perform second checks on the withdrawal's finalization period, this time with + // the `OutputProposal`'s timestamp fetched from the L2 Oracle. + require( + _isFinalizationPeriodElapsed(proposal.timestamp), + "OptimismPortal: output proposal finalization period has not elapsed" + ); + // Check that this withdrawal has not already been finalized, this is replay protection. require( finalizedWithdrawals[withdrawalHash] == false, @@ -225,8 +308,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { * @param _l2BlockNumber The number of the L2 block. */ function isBlockFinalized(uint256 _l2BlockNumber) external view returns (bool) { - Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(_l2BlockNumber); - return _isOutputFinalized(proposal); + return _isFinalizationPeriodElapsed(L2_ORACLE.getL2Output(_l2BlockNumber).timestamp); } /** @@ -277,16 +359,13 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { } /** - * @notice Determine if an L2 Output is finalized. + * @notice Determine if the finalization period has elapsed with respect to the + * passed timestamp. * - * @param _proposal The output proposal to check. + * @param _timestamp The timestamp to check. */ - function _isOutputFinalized(Types.OutputProposal memory _proposal) - internal - view - returns (bool) - { - return block.timestamp > _proposal.timestamp + FINALIZATION_PERIOD_SECONDS; + function _isFinalizationPeriodElapsed(uint256 _timestamp) internal view returns (bool) { + return block.timestamp > _timestamp + FINALIZATION_PERIOD_SECONDS; } /** diff --git a/packages/contracts-bedrock/contracts/test/CommonTest.t.sol b/packages/contracts-bedrock/contracts/test/CommonTest.t.sol index 3fbeb0e270caa..a7e74c1109335 100644 --- a/packages/contracts-bedrock/contracts/test/CommonTest.t.sol +++ b/packages/contracts-bedrock/contracts/test/CommonTest.t.sol @@ -453,7 +453,7 @@ contract ERC721Bridge_Initializer is Messenger_Initializer { } contract FFIInterface is Test { - function getFinalizeWithdrawalTransactionInputs(Types.WithdrawalTransaction memory _tx) + function getProveWithdrawalTransactionInputs(Types.WithdrawalTransaction memory _tx) external returns ( bytes32, @@ -466,7 +466,7 @@ contract FFIInterface is Test { string[] memory cmds = new string[](9); cmds[0] = "node"; cmds[1] = "dist/scripts/differential-testing.js"; - cmds[2] = "getFinalizeWithdrawalTransactionInputs"; + cmds[2] = "getProveWithdrawalTransactionInputs"; cmds[3] = vm.toString(_tx.nonce); cmds[4] = vm.toString(_tx.sender); cmds[5] = vm.toString(_tx.target); diff --git a/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol b/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol index 311f273ee3c8c..7e66216bd2f0b 100644 --- a/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol +++ b/packages/contracts-bedrock/contracts/test/OptimismPortal.t.sol @@ -16,7 +16,7 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD); } - function test_OptimismPortalReceiveEth() external { + function test_OptimismPortalReceiveEth_success() external { vm.expectEmit(true, true, false, true); emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex""); @@ -30,14 +30,14 @@ contract OptimismPortal_Test is Portal_Initializer { } // Test: depositTransaction fails when contract creation has a non-zero destination address - function test_OptimismPortalContractCreationReverts() external { + 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""); } // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value - function test_depositTransaction_NoValueEOA() external { + function test_depositTransaction_NoValueEOA_success() external { // EOA emulation vm.prank(address(this), address(this)); vm.expectEmit(true, true, false, true); @@ -61,7 +61,7 @@ contract OptimismPortal_Test is Portal_Initializer { } // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value - function test_depositTransaction_NoValueContract() external { + function test_depositTransaction_NoValueContract_success() external { vm.expectEmit(true, true, false, true); emitTransactionDeposited( AddressAliasHelper.applyL1ToL2Alias(address(this)), @@ -83,7 +83,7 @@ contract OptimismPortal_Test is Portal_Initializer { } // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value - function test_depositTransaction_createWithZeroValueForEOA() external { + function test_depositTransaction_createWithZeroValueForEOA_success() external { // EOA emulation vm.prank(address(this), address(this)); @@ -102,7 +102,7 @@ contract OptimismPortal_Test is Portal_Initializer { } // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value - function test_depositTransaction_createWithZeroValueForContract() external { + function test_depositTransaction_createWithZeroValueForContract_success() external { vm.expectEmit(true, true, false, true); emitTransactionDeposited( AddressAliasHelper.applyL1ToL2Alias(address(this)), @@ -118,7 +118,7 @@ contract OptimismPortal_Test is Portal_Initializer { } // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH - function test_depositTransaction_withEthValueFromEOA() external { + function test_depositTransaction_withEthValueFromEOA_success() external { // EOA emulation vm.prank(address(this), address(this)); @@ -144,7 +144,7 @@ contract OptimismPortal_Test is Portal_Initializer { } // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH - function test_depositTransaction_withEthValueFromContract() external { + function test_depositTransaction_withEthValueFromContract_success() external { vm.expectEmit(true, true, false, true); emitTransactionDeposited( AddressAliasHelper.applyL1ToL2Alias(address(this)), @@ -166,7 +166,7 @@ contract OptimismPortal_Test is Portal_Initializer { } // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH - function test_depositTransaction_withEthValueAndEOAContractCreation() external { + function test_depositTransaction_withEthValueAndEOAContractCreation_success() external { // EOA emulation vm.prank(address(this), address(this)); @@ -192,7 +192,7 @@ contract OptimismPortal_Test is Portal_Initializer { } // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH - function test_depositTransaction_withEthValueAndContractContractCreation() external { + function test_depositTransaction_withEthValueAndContractContractCreation_success() external { vm.expectEmit(true, true, false, true); emitTransactionDeposited( AddressAliasHelper.applyL1ToL2Alias(address(this)), @@ -214,7 +214,7 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(address(op).balance, NON_ZERO_VALUE); } - function test_simple_isBlockFinalized() external { + function test_simple_isBlockFinalized_success() external { vm.mockCall( address(op.L2_ORACLE()), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), @@ -229,7 +229,7 @@ contract OptimismPortal_Test is Portal_Initializer { assertEq(op.isBlockFinalized(startingBlockNumber), true); } - function test_isBlockFinalized() external { + function test_isBlockFinalized_success() external { uint256 checkpoint = oracle.nextBlockNumber(); vm.roll(checkpoint); vm.warp(oracle.computeL2Timestamp(checkpoint) + 1); @@ -272,7 +272,12 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { bytes[] _withdrawalProof; Types.OutputRootProof internal _outputRootProof; - event WithdrawalFinalized(bytes32 indexed, bool success); + event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); + event WithdrawalProven( + bytes32 indexed withdrawalHash, + address indexed from, + address indexed to + ); // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls. constructor() { @@ -287,7 +292,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { }); // Get withdrawal proof data we can use for testing. (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi - .getFinalizeWithdrawalTransactionInputs(_defaultTx); + .getProveWithdrawalTransactionInputs(_defaultTx); // Setup a dummy output root proof for reuse. _outputRootProof = Types.OutputRootProof({ @@ -316,102 +321,297 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { vm.deal(address(op), 0xFFFFFFFF); } + // Utility function used in the subsequent test. This is necessary to assert that the + // reentrant call will revert. + function callPortalAndExpectRevert() external payable { + 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); + // Assert that the withdrawal was not finalized. + assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx))); + } + + // Test: proveWithdrawalTransaction cannot prove a withdrawal with itself (the OptimismPortal) as the target. + function test_proveWithdrawalTransaction_onSelfCall_reverts() external { + _defaultTx.target = address(op); + vm.expectRevert("OptimismPortal: you cannot send messages to the portal contract"); + op.proveWithdrawalTransaction( + _defaultTx, + _proposedBlockNumber, + _outputRootProof, + _withdrawalProof + ); + } + + // Test: proveWithdrawalTransaction reverts if the outputRootProof does not match the output root + function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external { + // Modify the version to invalidate the withdrawal proof. + _outputRootProof.version = bytes32(uint256(1)); + vm.expectRevert("OptimismPortal: invalid output root proof"); + op.proveWithdrawalTransaction( + _defaultTx, + _proposedBlockNumber, + _outputRootProof, + _withdrawalProof + ); + } + + // Test: proveWithdrawalTransaction reverts if the proof is invalid due to non-existence of + // the withdrawal. + function test_proveWithdrawalTransaction_oninvalidWithdrawalProof_reverts() external { + // modify the default test values to invalidate the proof. + _defaultTx.data = hex"abcd"; + vm.expectRevert("OptimismPortal: invalid withdrawal inclusion proof"); + op.proveWithdrawalTransaction( + _defaultTx, + _proposedBlockNumber, + _outputRootProof, + _withdrawalProof + ); + } + + // Test: proveWithdrawalTransaction succeeds and emits the WithdrawalProven event. + function test_proveWithdrawalTransaction_validWithdrawalProof_success() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + op.proveWithdrawalTransaction( + _defaultTx, + _proposedBlockNumber, + _outputRootProof, + _withdrawalProof + ); + } + // Test: finalizeWithdrawalTransaction succeeds and emits the WithdrawalFinalized event. - function test_finalizeWithdrawalTransaction_succeeds() external { + function test_finalizeWithdrawalTransaction_provenWithdrawalHash_success() external { uint256 bobBalanceBefore = address(bob).balance; + vm.expectEmit(true, true, true, true); - emit WithdrawalFinalized(_withdrawalHash, true); - op.finalizeWithdrawalTransaction( + emit WithdrawalProven(_withdrawalHash, alice, bob); + op.proveWithdrawalTransaction( _defaultTx, _proposedBlockNumber, _outputRootProof, _withdrawalProof ); + + vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1); + vm.expectEmit(true, true, false, true); + emit WithdrawalFinalized(_withdrawalHash, true); + op.finalizeWithdrawalTransaction(_defaultTx); + assert(address(bob).balance == bobBalanceBefore + 100); } - // Test: finalizeWithdrawalTransaction fails because the target reverts, - // and emits the WithdrawalFinalized event with success=false. - function test_finalizeWithdrawalTransaction_targetFails() external { + // Test: finalizeWithdrawalTransaction reverts if the withdrawal has not been proven. + function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external { + uint256 bobBalanceBefore = address(bob).balance; + + vm.expectRevert("OptimismPortal: withdrawal has not been proven"); + op.finalizeWithdrawalTransaction(_defaultTx); + + assert(address(bob).balance == bobBalanceBefore); + } + + // Test: finalizeWithdrawalTransaction reverts if withdrawal not proven long enough ago. + function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external { uint256 bobBalanceBefore = address(bob).balance; - vm.etch(bob, hex"fe"); // Contract with just the invalid opcode. vm.expectEmit(true, true, true, true); - emit WithdrawalFinalized(_withdrawalHash, false); - op.finalizeWithdrawalTransaction( + emit WithdrawalProven(_withdrawalHash, alice, bob); + op.proveWithdrawalTransaction( _defaultTx, _proposedBlockNumber, _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()), + abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), + abi.encode(bytes32(uint256(1)), _proposedBlockNumber) + ); + + vm.expectRevert("OptimismPortal: proven withdrawal finalization period has not elapsed"); + op.finalizeWithdrawalTransaction(_defaultTx); + assert(address(bob).balance == bobBalanceBefore); } - // Test: finalizeWithdrawalTransaction cannot finalize a withdrawal with itself (the OptimismPortal) as the target. - function test_finalizeWithdrawalTransaction_revertsOnSelfCall() external { - _defaultTx.target = address(op); - vm.expectRevert("OptimismPortal: you cannot send messages to the portal contract"); - op.finalizeWithdrawalTransaction( + // Test: finalizeWithdrawalTransaction reverts if the provenWithdrawal's timestamp is less + // than the L2 output oracle's starting timestamp + function test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() external { + uint256 bobBalanceBefore = address(bob).balance; + + // Prove our withdrawal + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + op.proveWithdrawalTransaction( _defaultTx, _proposedBlockNumber, _outputRootProof, _withdrawalProof ); + + // Warp to after the finalization period + vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1); + + // Mock a STARTING_TIMESTAMP change on the L2 Oracle + vm.mockCall( + address(op.L2_ORACLE()), + abi.encodeWithSignature("STARTING_TIMESTAMP()"), + abi.encode(block.timestamp + 1) + ); + + // Attempt to finalize the withdrawal + vm.expectRevert( + "OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp" + ); + op.finalizeWithdrawalTransaction(_defaultTx); + + // Ensure that bob's balance has remained the same + assertEq(bobBalanceBefore, address(bob).balance); } - // Test: finalizeWithdrawalTransaction reverts if the outputRootProof does not match the output root - function test_finalizeWithdrawalTransaction_revertsOnInvalidOutputRootProof() external { - // Modify the version to invalidate the withdrawal proof. - _outputRootProof.version = bytes32(uint256(1)); - vm.expectRevert("OptimismPortal: invalid output root proof"); - op.finalizeWithdrawalTransaction( + // Test: finalizeWithdrawalTransaction reverts if the output root proven is not the same as the + // output root at the time of finalization. + function test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() external { + uint256 bobBalanceBefore = address(bob).balance; + + // Prove our withdrawal + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + op.proveWithdrawalTransaction( _defaultTx, _proposedBlockNumber, _outputRootProof, _withdrawalProof ); + + // Warp to after the finalization period + vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1); + + // Mock an outputRoot change on the output proposal before attempting + // to finalize the withdrawal. + vm.mockCall( + address(op.L2_ORACLE()), + abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), + abi.encode(Types.OutputProposal(bytes32(uint256(0)), _proposedBlockNumber)) + ); + + // Attempt to finalize the withdrawal + vm.expectRevert( + "OptimismPortal: output root proven is not the same as current output root" + ); + op.finalizeWithdrawalTransaction(_defaultTx); + + // Ensure that bob's balance has remained the same + assertEq(bobBalanceBefore, address(bob).balance); + } + + // Test: finalizeWithdrawalTransaction reverts if the output proposal's timestamp has + // not passed the finalization period. + function test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() external { + uint256 bobBalanceBefore = address(bob).balance; + + // Prove our withdrawal + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + op.proveWithdrawalTransaction( + _defaultTx, + _proposedBlockNumber, + _outputRootProof, + _withdrawalProof + ); + + // Warp to after the finalization period + vm.warp(block.timestamp + op.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()), + abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), + abi.encode(Types.OutputProposal(_outputRoot, block.timestamp + 1)) + ); + + // Attempt to finalize the withdrawal + vm.expectRevert("OptimismPortal: output proposal finalization period has not elapsed"); + op.finalizeWithdrawalTransaction(_defaultTx); + + // Ensure that bob's balance has remained the same + assertEq(bobBalanceBefore, address(bob).balance); + } + + // Test: finalizeWithdrawalTransaction fails because the target reverts, + // and emits the WithdrawalFinalized event with success=false. + function test_finalizeWithdrawalTransaction_targetFails_fails() external { + uint256 bobBalanceBefore = address(bob).balance; + vm.etch(bob, hex"fe"); // Contract with just the invalid opcode. + + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + op.proveWithdrawalTransaction( + _defaultTx, + _proposedBlockNumber, + _outputRootProof, + _withdrawalProof + ); + + vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1); + vm.expectEmit(true, true, true, true); + emit WithdrawalFinalized(_withdrawalHash, false); + op.finalizeWithdrawalTransaction(_defaultTx); + + assert(address(bob).balance == bobBalanceBefore); } // Test: finalizeWithdrawalTransaction reverts if the finalization period has not yet passed. - function test_finalizeWithdrawalTransaction_revertsOnRecentWithdrawal() external { + function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external { // Setup the Oracle to return an output with a recent timestamp uint256 recentTimestamp = block.timestamp - 1000; vm.mockCall( address(op.L2_ORACLE()), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), - abi.encode(bytes32(uint256(1)), recentTimestamp) + abi.encode(_outputRoot, recentTimestamp) ); - vm.expectRevert("OptimismPortal: proposal is not yet finalized"); - op.finalizeWithdrawalTransaction( + op.proveWithdrawalTransaction( _defaultTx, _proposedBlockNumber, _outputRootProof, _withdrawalProof ); + + vm.expectRevert("OptimismPortal: proven withdrawal finalization period has not elapsed"); + op.finalizeWithdrawalTransaction(_defaultTx); } // Test: finalizeWithdrawalTransaction reverts if the withdrawal has already been finalized. - function test_finalizeWithdrawalTransaction_revertsOnReplay() external { + function test_finalizeWithdrawalTransaction_onReplay_reverts() external { vm.expectEmit(true, true, true, true); - emit WithdrawalFinalized(_withdrawalHash, true); - op.finalizeWithdrawalTransaction( + emit WithdrawalProven(_withdrawalHash, alice, bob); + op.proveWithdrawalTransaction( _defaultTx, _proposedBlockNumber, _outputRootProof, _withdrawalProof ); + + vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1); + vm.expectEmit(true, true, true, true); + emit WithdrawalFinalized(_withdrawalHash, true); + op.finalizeWithdrawalTransaction(_defaultTx); + vm.expectRevert("OptimismPortal: withdrawal has already been finalized"); - op.finalizeWithdrawalTransaction( - _defaultTx, - _proposedBlockNumber, - _outputRootProof, - _withdrawalProof - ); + op.finalizeWithdrawalTransaction(_defaultTx); } // Test: finalizeWithdrawalTransaction reverts if insufficient gas is supplied. - function test_finalizeWithdrawalTransaction_revertsOnInsufficientGas() external { + function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external { // This number was identified through trial and error. uint256 gasLimit = 150_000; Types.WithdrawalTransaction memory insufficientGasTx = Types.WithdrawalTransaction({ @@ -422,57 +622,40 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { gasLimit: gasLimit, data: hex"" }); + + // Get updated proof inputs. (bytes32 stateRoot, bytes32 storageRoot, , , bytes[] memory withdrawalProof) = ffi - .getFinalizeWithdrawalTransactionInputs(insufficientGasTx); + .getProveWithdrawalTransactionInputs(insufficientGasTx); Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({ version: bytes32(0), stateRoot: stateRoot, messagePasserStorageRoot: storageRoot, latestBlockhash: bytes32(0) }); + vm.mockCall( address(op.L2_ORACLE()), abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), abi.encode(Hashing.hashOutputRootProof(outputRootProof), _proposedBlockNumber) ); - vm.expectRevert("OptimismPortal: insufficient gas to finalize withdrawal"); - op.finalizeWithdrawalTransaction{ gas: gasLimit }( + + op.proveWithdrawalTransaction( insufficientGasTx, _proposedBlockNumber, outputRootProof, withdrawalProof ); - } - - // Test: finalizeWithdrawalTransaction reverts if the proof is invalid due to non-existence of - // the withdrawal. - function test_finalizeWithdrawalTransaction_revertsOninvalidWithdrawalProof() external { - // modify the default test values to invalidate the proof. - _defaultTx.data = hex"abcd"; - vm.expectRevert("OptimismPortal: invalid withdrawal inclusion proof"); - op.finalizeWithdrawalTransaction( - _defaultTx, - _proposedBlockNumber, - _outputRootProof, - _withdrawalProof - ); - } - // Utility function used in the subsequent test. This is necessary to assert that the - // reentrant call will revert. - function callPortalAndExpectRevert() external payable { - 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. - bytes[] memory proof = new bytes[](1); - op.finalizeWithdrawalTransaction(_defaultTx, 0, _outputRootProof, proof); - // Assert that the withdrawal was not finalized. - assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx))); + vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1); + vm.expectRevert("OptimismPortal: insufficient gas to finalize withdrawal"); + op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx); } // Test: finalizeWithdrawalTransaction reverts if a sub-call attempts to finalize another // withdrawal. - function test_finalizeWithdrawalTransaction_revertsOnReentrancy() external { + function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external { uint256 bobBalanceBefore = address(bob).balance; + // Copy and modify the default test values to attempt a reentrant call by first calling to // this contract's callPortalAndExpectRevert() function above. Types.WithdrawalTransaction memory _testTx = _defaultTx; @@ -486,7 +669,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { bytes32 outputRoot, bytes32 withdrawalHash, bytes[] memory withdrawalProof - ) = ffi.getFinalizeWithdrawalTransactionInputs(_testTx); + ) = ffi.getProveWithdrawalTransactionInputs(_testTx); Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({ version: bytes32(0), stateRoot: stateRoot, @@ -502,35 +685,36 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { abi.encode(Types.OutputProposal(outputRoot, finalizedTimestamp)) ); - // Assert that this contract is called with the expected data (i.e. the function signature of - // callPortalAndExpectRevert). - vm.expectCall(address(this), _testTx.data); vm.expectEmit(true, true, true, true); - // Assert that the withdrawal should be finalized, and that the sub-call passes (because the - // assertions in callPortalAndExpectRevert pass). - emit WithdrawalFinalized(withdrawalHash, true); - op.finalizeWithdrawalTransaction( + emit WithdrawalProven(withdrawalHash, alice, address(this)); + op.proveWithdrawalTransaction( _testTx, _proposedBlockNumber, outputRootProof, withdrawalProof ); + + vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1); + vm.expectCall(address(this), _testTx.data); + vm.expectEmit(true, true, true, true); + emit WithdrawalFinalized(withdrawalHash, true); + op.finalizeWithdrawalTransaction(_testTx); + // Ensure that bob's balance was not changed by the reentrant call. assert(address(bob).balance == bobBalanceBefore); } - function test_finalizeWithdrawalTransaction_differential( + function test_finalizeWithdrawalTransaction_differential_success( address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes memory _data ) external { - // Cannot call the optimism portal - vm.assume(_target != address(op)); - // Total ETH supply is currently about 120M ETH. - vm.assume(_value < 200_000_000 ether); + vm.assume(_target != address(op)); // Cannot call the optimism portal. + vm.assume(_value < 200_000_000 ether); // Total ETH supply is currently ~120M ETH. vm.assume(_gasLimit < 50_000_000); + uint256 _nonce = messagePasser.nonce(); Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({ nonce: _nonce, @@ -546,7 +730,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { bytes32 outputRoot, bytes32 withdrawalHash, bytes[] memory withdrawalProof - ) = ffi.getFinalizeWithdrawalTransactionInputs(_tx); + ) = ffi.getProveWithdrawalTransactionInputs(_tx); Types.OutputRootProof memory proof = Types.OutputRootProof({ version: bytes32(uint256(0)), @@ -571,11 +755,12 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { vm.deal(_tx.sender, _tx.value); vm.prank(_tx.sender); messagePasser.initiateWithdrawal{ value: _tx.value }(_tx.target, _tx.gasLimit, _tx.data); + // Ensure that the sentMessages is correct assertEq(messagePasser.sentMessages(withdrawalHash), true); - vm.warp(op.FINALIZATION_PERIOD_SECONDS() + 1); - op.finalizeWithdrawalTransaction( + vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1); + op.proveWithdrawalTransaction( _tx, 100, // l2BlockNumber proof, @@ -594,7 +779,7 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { proxy = Proxy(payable(address(op))); } - function test_initValuesOnProxy() external { + function test_params_initValuesOnProxy_success() external { (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = OptimismPortal( payable(address(proxy)) ).params(); @@ -603,17 +788,17 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { assertEq(prevBlockNum, initialBlockNum); } - function test_cannotInitProxy() external { + function test_initialize_cannotInitProxy_reverts() external { vm.expectRevert("Initializable: contract is already initialized"); OptimismPortal(payable(proxy)).initialize(); } - function test_cannotInitImpl() external { + function test_initialize_cannotInitImpl_reverts() external { vm.expectRevert("Initializable: contract is already initialized"); OptimismPortal(opImpl).initialize(); } - function test_upgrading() external { + function test_upgradeToAndCall_upgrading_success() external { // Check an unused slot before upgrading. bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21))); assertEq(bytes32(0), slot21Before); diff --git a/packages/contracts-bedrock/scripts/differential-testing.ts b/packages/contracts-bedrock/scripts/differential-testing.ts index 5741275e5b025..468be1562112d 100644 --- a/packages/contracts-bedrock/scripts/differential-testing.ts +++ b/packages/contracts-bedrock/scripts/differential-testing.ts @@ -165,7 +165,7 @@ const command = args[0] process.stdout.write(output) break } - case 'getFinalizeWithdrawalTransactionInputs': { + case 'getProveWithdrawalTransactionInputs': { const nonce = BigNumber.from(args[1]) const sender = args[2] const target = args[3] diff --git a/packages/sdk/src/cross-chain-messenger.ts b/packages/sdk/src/cross-chain-messenger.ts index 132f3fac87c96..6160a8fa432c3 100644 --- a/packages/sdk/src/cross-chain-messenger.ts +++ b/packages/sdk/src/cross-chain-messenger.ts @@ -52,6 +52,8 @@ import { StateRoot, StateRootBatch, IBridgeAdapter, + ProvenWithdrawal, + WithdrawalEntry, } from './interfaces' import { toSignerOrProvider, @@ -550,7 +552,30 @@ export class CrossChainMessenger { return MessageStatus.STATE_ROOT_NOT_PUBLISHED } - timestamp = output.l1Timestamp + // Fetch the receipt for the resolved CrossChainMessage + const _receipt = await this.l2Provider.getTransactionReceipt( + resolved.transactionHash + ) + + // Get the withdrawal hash for the receipt + const [_, withdrawalHash] = this.getWithdrawalFromReceipt( + _receipt, + resolved + ) + + // Attempt to fetch the proven withdrawal + const provenWithdrawal = await this.getProvenWithdrawal( + withdrawalHash + ) + + // If the withdrawal hash has not been proven on L1, + // return `READY_TO_PROVE` + if (provenWithdrawal.timestamp.eq(BigNumber.from(0))) { + return MessageStatus.READY_TO_PROVE + } + + // Set the timestamp to the provenWithdrawal's timestamp + timestamp = provenWithdrawal.timestamp.toNumber() } else { const stateRoot = await this.getMessageStateRoot(resolved) if (stateRoot === null) { @@ -892,6 +917,24 @@ export class CrossChainMessenger { return challengePeriod.toNumber() } + /** + * Queries the OptimismPortal contract's `provenWithdrawals` mapping + * for a ProvenWithdrawal that matches the passed withdrawalHash + * + * Note: This function is bedrock-specific. + * + * @returns A ProvenWithdrawal object + */ + public async getProvenWithdrawal( + withdrawalHash: string + ): Promise { + if (!this.bedrock) { + throw new Error('message proving only applies after the bedrock upgrade') + } + + return this.contracts.l1.OptimismPortal.provenWithdrawals(withdrawalHash) + } + /** * Returns the Bedrock output root that corresponds to the given message. * @@ -1212,41 +1255,9 @@ export class CrossChainMessenger { resolved.transactionHash ) - interface WithdrawalEntry { - MessagePassed: any - } - - // Handle multiple withdrawals in the same tx - const logs: Partial<{ number: WithdrawalEntry }> = {} - for (const [i, log] of Object.entries(receipt.logs)) { - if (log.address === this.contracts.l2.BedrockMessagePasser.address) { - const decoded = - this.contracts.l2.L2ToL1MessagePasser.interface.parseLog(log) - // Find the withdrawal initiated events - if (decoded.name === 'MessagePassed') { - logs[log.logIndex] = { - MessagePassed: decoded.args, - } - } - } - } - - // TODO(tynes): be able to handle transactions that do multiple withdrawals - // in a single transaction. Right now just go for the first one. - const withdrawal = Object.values(logs)[0] - if (!withdrawal) { - throw new Error( - `Cannot find withdrawal logs for ${resolved.transactionHash}` - ) - } - - const withdrawalHash = hashWithdrawal( - withdrawal.MessagePassed.nonce, - withdrawal.MessagePassed.sender, - withdrawal.MessagePassed.target, - withdrawal.MessagePassed.value, - withdrawal.MessagePassed.gasLimit, - withdrawal.MessagePassed.data + const [withdrawal, withdrawalHash] = this.getWithdrawalFromReceipt( + receipt, + resolved ) // Sanity check @@ -1311,6 +1322,58 @@ export class CrossChainMessenger { ] } + /** + * Helper function that gets a withdrawal and a withdrawal hash from the logs + * of a L2 to L2 CrossChainMessage and its transaction receipt. + * + * TODO: Process multiple withdrawals in a single transaction. + */ + public getWithdrawalFromReceipt( + receipt: TransactionReceipt, + message: CrossChainMessage + ): [WithdrawalEntry, string] { + // Handle multiple withdrawals in the same tx + const logs: Partial<{ number: WithdrawalEntry }> = {} + for (const [_, log] of Object.entries(receipt.logs)) { + if (log.address === this.contracts.l2.BedrockMessagePasser.address) { + const decoded = + this.contracts.l2.L2ToL1MessagePasser.interface.parseLog(log) + // Find the withdrawal initiated events + if (decoded.name === 'MessagePassed') { + logs[log.logIndex] = { + MessagePassed: decoded.args, + } + } + } + } + + // TODO(tynes): be able to handle transactions that do multiple withdrawals + // in a single transaction. Right now just go for the first one. + const withdrawal = Object.values(logs)[0] + if (!withdrawal) { + throw new Error( + `Cannot find withdrawal logs for ${message.transactionHash}` + ) + } + + const withdrawalHash = hashWithdrawal( + withdrawal.MessagePassed.nonce, + withdrawal.MessagePassed.sender, + withdrawal.MessagePassed.target, + withdrawal.MessagePassed.value, + withdrawal.MessagePassed.gasLimit, + withdrawal.MessagePassed.data + ) + + if (withdrawalHash !== withdrawal.MessagePassed.withdrawalHash) { + throw new Error( + 'Locally computed withdrawal hash is not equal to the withdrawal hash computed on-chain!' + ) + } + + return [withdrawal, withdrawalHash] + } + /** * Sends a given cross chain message. Where the message is sent depends on the direction attached * to the message itself. @@ -1366,6 +1429,28 @@ export class CrossChainMessenger { ) } + /** + * Proves a cross chain message that was sent from L2 to L1. Only applicable for L2 to L1 + * messages. + * + * @param message Message to finalize. + * @param opts Additional options. + * @param opts.signer Optional signer to use to send the transaction. + * @param opts.overrides Optional transaction overrides. + * @returns Transaction response for the finalization transaction. + */ + public async proveMessage( + message: MessageLike, + opts?: { + signer?: Signer + overrides?: Overrides + } + ): Promise { + return (opts?.signer || this.l1Signer).sendTransaction( + await this.populateTransaction.proveMessage(message, opts) + ) + } + /** * Finalizes a cross chain message that was sent from L2 to L1. Only applicable for L2 to L1 * messages. Will throw an error if the message has not completed its challenge period yet. @@ -1639,6 +1724,57 @@ export class CrossChainMessenger { } }, + /** + * Generates a message proving transaction that can be signed and executed. Only + * applicable for L2 to L1 messages. + * + * @param message Message to generate the proving transaction for. + * @param opts Additional options. + * @param opts.overrides Optional transaction overrides. + * @returns Transaction that can be signed and executed to prove the message. + */ + proveMessage: async ( + message: MessageLike, + opts?: { + overrides?: PayableOverrides + } + ): Promise => { + const resolved = await this.toCrossChainMessage(message) + if (resolved.direction === MessageDirection.L1_TO_L2) { + throw new Error('cannot finalize L1 to L2 message') + } + + if (!this.bedrock) { + throw new Error( + 'message proving only applies after the bedrock upgrade' + ) + } + + const [proof, output, withdrawalTx] = await this.getBedrockMessageProof( + message + ) + + return this.contracts.l1.OptimismPortal.populateTransaction.proveWithdrawalTransaction( + [ + withdrawalTx.messageNonce, + withdrawalTx.sender, + withdrawalTx.target, + withdrawalTx.value, + withdrawalTx.minGasLimit, + withdrawalTx.message, + ], + output.l2BlockNumber, + [ + proof.outputRootProof.version, + proof.outputRootProof.stateRoot, + proof.outputRootProof.messagePasserStorageRoot, + proof.outputRootProof.latestBlockhash, + ], + proof.withdrawalProof, + opts?.overrides || {} + ) + }, + /** * Generates a message finalization transaction that can be signed and executed. Only * applicable for L2 to L1 messages. Will throw an error if the message has not completed @@ -1661,9 +1797,7 @@ export class CrossChainMessenger { } if (this.bedrock) { - const [proof, output, withdrawalTx] = await this.getBedrockMessageProof( - message - ) + const [, , withdrawalTx] = await this.getBedrockMessageProof(message) return this.contracts.l1.OptimismPortal.populateTransaction.finalizeWithdrawalTransaction( [ @@ -1674,14 +1808,6 @@ export class CrossChainMessenger { withdrawalTx.minGasLimit, withdrawalTx.message, ], - output.l2BlockNumber, - [ - proof.outputRootProof.version, - proof.outputRootProof.stateRoot, - proof.outputRootProof.messagePasserStorageRoot, - proof.outputRootProof.latestBlockhash, - ], - proof.withdrawalProof, opts?.overrides || {} ) } else { @@ -1882,6 +2008,25 @@ export class CrossChainMessenger { ) }, + /** + * Estimates gas required to prove a cross chain message. Only applies to L2 to L1 messages. + * + * @param message Message to generate the proving transaction for. + * @param opts Additional options. + * @param opts.overrides Optional transaction overrides. + * @returns Gas estimate for the transaction. + */ + proveMessage: async ( + message: MessageLike, + opts?: { + overrides?: CallOverrides + } + ): Promise => { + return this.l1Provider.estimateGas( + await this.populateTransaction.proveMessage(message, opts) + ) + }, + /** * Estimates gas required to finalize a cross chain message. Only applies to L2 to L1 messages. * diff --git a/packages/sdk/src/interfaces/types.ts b/packages/sdk/src/interfaces/types.ts index 08b86dcab3fd2..bfec4ef86648c 100644 --- a/packages/sdk/src/interfaces/types.ts +++ b/packages/sdk/src/interfaces/types.ts @@ -143,7 +143,12 @@ export enum MessageStatus { STATE_ROOT_NOT_PUBLISHED, /** - * Message is an L2 to L1 message and awaiting the challenge period. + * Message is ready to be proved on L1 to initiate the challenge period. + */ + READY_TO_PROVE, + + /** + * Message is a proved L2 to L1 message and is undergoing the challenge period. */ IN_CHALLENGE_PERIOD, @@ -215,6 +220,14 @@ export interface TokenBridgeMessage { transactionHash: string } +/** + * Represents a withdrawal entry within the logs of a L2 to L1 + * CrossChainMessage + */ +export interface WithdrawalEntry { + MessagePassed: any +} + /** * Enum describing the status of a CrossDomainMessage message receipt. */ @@ -231,6 +244,15 @@ export interface MessageReceipt { transactionReceipt: TransactionReceipt } +/** + * ProvenWithdrawal in OptimismPortal + */ +export interface ProvenWithdrawal { + outputRoot: string + timestamp: BigNumber + l2BlockNumber: BigNumber +} + /** * Header for a state root batch. */ diff --git a/packages/sdk/tasks/deposit-erc20.ts b/packages/sdk/tasks/deposit-erc20.ts index c12cd18680f78..f478dcffe3bc9 100644 --- a/packages/sdk/tasks/deposit-erc20.ts +++ b/packages/sdk/tasks/deposit-erc20.ts @@ -304,17 +304,29 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.') const now = Math.floor(Date.now() / 1000) + console.log('Waiting for message to be able to be proved') + await messenger.waitForMessageStatus(withdraw, MessageStatus.READY_TO_PROVE) + + console.log('Proving withdrawal...') + const prove = await messenger.proveMessage(withdraw) + const proveReceipt = await prove.wait() + console.log(proveReceipt) + if (proveReceipt.status !== 1) { + throw new Error('Prove withdrawal transaction reverted') + } + console.log('Waiting for message to be able to be relayed') await messenger.waitForMessageStatus( withdraw, MessageStatus.READY_FOR_RELAY ) + console.log('Finalizing withdrawal...') const finalize = await messenger.finalizeMessage(withdraw) - const receipt = await finalize.wait() + const finalizeReceipt = await finalize.wait() console.log(`Took ${Math.floor(Date.now() / 1000) - now} seconds`) - for (const log of receipt.logs) { + for (const log of finalizeReceipt.logs) { switch (log.address) { case OptimismPortal.address: { const parsed = OptimismPortal.interface.parseLog(log) diff --git a/packages/sdk/tasks/deposit-eth.ts b/packages/sdk/tasks/deposit-eth.ts index 8c4bdf35f2651..70de210abadaa 100644 --- a/packages/sdk/tasks/deposit-eth.ts +++ b/packages/sdk/tasks/deposit-eth.ts @@ -229,8 +229,30 @@ task('deposit-eth', 'Deposits WETH9 onto L2.') `Withdrawal on L2 complete: ${ethWithdrawReceipt.transactionHash}` ) - console.log('Waiting to be able to withdraw') - const interval = setInterval(async () => { + console.log('Waiting to be able to prove withdrawal') + const proveInterval = setInterval(async () => { + const currentStatus = await messenger.getMessageStatus(ethWithdrawReceipt) + console.log(`Message status: ${MessageStatus[currentStatus]}`) + }, 3000) + + try { + await messenger.waitForMessageStatus( + ethWithdrawReceipt, + MessageStatus.READY_TO_PROVE + ) + } finally { + clearInterval(proveInterval) + } + + console.log('Proving eth withdrawal...') + const ethProve = await messenger.proveMessage(ethWithdrawReceipt) + const ethProveReceipt = await ethProve.wait() + if (ethProveReceipt.status !== 1) { + throw new Error('Prove withdrawal transaction reverted') + } + + console.log('Waiting to be able to finalize withdrawal') + const finalizeInterval = setInterval(async () => { const currentStatus = await messenger.getMessageStatus(ethWithdrawReceipt) console.log(`Message status: ${MessageStatus[currentStatus]}`) }, 3000) @@ -241,9 +263,10 @@ task('deposit-eth', 'Deposits WETH9 onto L2.') MessageStatus.READY_FOR_RELAY ) } finally { - clearInterval(interval) + clearInterval(finalizeInterval) } + console.log('Finalizing eth withdrawal...') const ethFinalize = await messenger.finalizeMessage(ethWithdrawReceipt) const ethFinalizeReceipt = await ethFinalize.wait() if (ethFinalizeReceipt.status !== 1) { diff --git a/packages/sdk/tasks/finalize-withdrawal.ts b/packages/sdk/tasks/finalize-withdrawal.ts index 4abfb5c7499f0..da617ff694177 100644 --- a/packages/sdk/tasks/finalize-withdrawal.ts +++ b/packages/sdk/tasks/finalize-withdrawal.ts @@ -87,7 +87,25 @@ task('finalize-withdrawal', 'Finalize a withdrawal') const status = await messenger.getMessageStatus(txHash) console.log(`Status: ${MessageStatus[status]}`) - if (status === MessageStatus.READY_FOR_RELAY) { + if (status === MessageStatus.READY_TO_PROVE) { + const proveTx = await messenger.proveMessage(txHash) + const proveReceipt = await proveTx.wait() + console.log('Prove receipt', proveReceipt) + + const finalizeInterval = setInterval(async () => { + const currentStatus = await messenger.getMessageStatus(txHash) + console.log(`Message status: ${MessageStatus[currentStatus]}`) + }, 3000) + + try { + await messenger.waitForMessageStatus( + txHash, + MessageStatus.READY_FOR_RELAY + ) + } finally { + clearInterval(finalizeInterval) + } + const tx = await messenger.finalizeMessage(txHash) const receipt = await tx.wait() console.log(receipt)