diff --git a/go.mod b/go.mod index 3232ef0d42ce..3ff8ebb344ed 100644 --- a/go.mod +++ b/go.mod @@ -250,9 +250,9 @@ require ( rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/ethereum/go-ethereum v1.14.11 => github.com/ethereum-optimism/op-geth v1.101411.1-rc.2 +replace github.com/ethereum/go-ethereum v1.14.11 => github.com/ethereum-optimism/op-geth v1.101411.1-rc.5 -//replace github.com/ethereum/go-ethereum => ../op-geth +//replace github.com/ethereum/go-ethereum => ../go-ethereum // replace github.com/ethereum-optimism/superchain-registry/superchain => ../superchain-registry/superchain diff --git a/go.sum b/go.sum index b183dc9ae47d..616fb9b7d453 100644 --- a/go.sum +++ b/go.sum @@ -187,8 +187,8 @@ github.com/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/u github.com/elastic/gosigar v0.14.3/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs= -github.com/ethereum-optimism/op-geth v1.101411.1-rc.2 h1:nOeSTzcFWUCvJO1MJ5AyI26dqR1F7vYgz2jNNKuEtoE= -github.com/ethereum-optimism/op-geth v1.101411.1-rc.2/go.mod h1:7S4pp8KHBmEmKkRjL1BPOc6jY9hW+64YeMUjR3RVLw4= +github.com/ethereum-optimism/op-geth v1.101411.1-rc.5 h1:LDSP85xTczjDYMBK0mOF5mzpZifLGz1TTW/6NgQsytc= +github.com/ethereum-optimism/op-geth v1.101411.1-rc.5/go.mod h1:7S4pp8KHBmEmKkRjL1BPOc6jY9hW+64YeMUjR3RVLw4= github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240910145426-b3905c89e8ac h1:hCIrLuOPV3FJfMDvXeOhCC3uQNvFoMIIlkT2mN2cfeg= github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240910145426-b3905c89e8ac/go.mod h1:XaVXL9jg8BcyOeugECgIUGa9Y3DjYJj71RHmb5qon6M= github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= diff --git a/op-chain-ops/interopgen/recipe.go b/op-chain-ops/interopgen/recipe.go index 85f429eb793a..8983ee72da8e 100644 --- a/op-chain-ops/interopgen/recipe.go +++ b/op-chain-ops/interopgen/recipe.go @@ -109,6 +109,7 @@ func prefundL2Accounts(l1Cfg *L1Config, l2Cfg *L2Config, addrs devkeys.Addresses l1Cfg.Prefund[l2Cfg.BatchSenderAddress] = Ether(10_000_000) l1Cfg.Prefund[l2Cfg.Deployer] = Ether(10_000_000) l1Cfg.Prefund[l2Cfg.FinalSystemOwner] = Ether(10_000_000) + l1Cfg.Prefund[l2Cfg.SystemConfigOwner] = Ether(10_000_000) proposer, err := addrs.Address(devkeys.ChainOperatorKey{ ChainID: new(big.Int).SetUint64(l2Cfg.L2ChainID), Role: devkeys.ProposerRole, diff --git a/op-deployer/pkg/deployer/integration_test/apply_test.go b/op-deployer/pkg/deployer/integration_test/apply_test.go index e0b34dc8ea6a..f123953a3ea4 100644 --- a/op-deployer/pkg/deployer/integration_test/apply_test.go +++ b/op-deployer/pkg/deployer/integration_test/apply_test.go @@ -400,7 +400,7 @@ func TestInteropDeployment(t *testing.T) { chainState := st.Chains[0] depManagerSlot := common.HexToHash("0x1708e077affb93e89be2665fb0fb72581be66f84dc00d25fed755ae911905b1c") checkImmutable(t, st.L1StateDump.Data.Accounts, st.ImplementationsDeployment.SystemConfigImplAddress, depManagerSlot) - proxyAdminOwnerHash := common.BytesToHash(intent.Chains[0].Roles.L1ProxyAdminOwner.Bytes()) + proxyAdminOwnerHash := common.BytesToHash(intent.Chains[0].Roles.SystemConfigOwner.Bytes()) checkStorageSlot(t, st.L1StateDump.Data.Accounts, chainState.SystemConfigProxyAddress, depManagerSlot, proxyAdminOwnerHash) } diff --git a/op-e2e/interop/contracts/emit.go b/op-e2e/interop/contracts/bindings/emit/emit.go similarity index 99% rename from op-e2e/interop/contracts/emit.go rename to op-e2e/interop/contracts/bindings/emit/emit.go index ceae2412659b..7755ef5fd18f 100644 --- a/op-e2e/interop/contracts/emit.go +++ b/op-e2e/interop/contracts/bindings/emit/emit.go @@ -26,7 +26,6 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription - _ = abi.ConvertType ) // EmitMetaData contains all meta data concerning the Emit contract. @@ -157,11 +156,11 @@ func NewEmitFilterer(address common.Address, filterer bind.ContractFilterer) (*E // bindEmit binds a generic wrapper to an already deployed contract. func bindEmit(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := EmitMetaData.GetAbi() + parsed, err := abi.JSON(strings.NewReader(EmitABI)) if err != nil { return nil, err } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/op-e2e/interop/contracts/bindings/inbox/inbox.go b/op-e2e/interop/contracts/bindings/inbox/inbox.go new file mode 100644 index 000000000000..f73fd56355e4 --- /dev/null +++ b/op-e2e/interop/contracts/bindings/inbox/inbox.go @@ -0,0 +1,231 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package inbox + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// Identifier is an auto generated low-level Go binding around an user-defined struct. +type Identifier struct { + Origin common.Address + BlockNumber *big.Int + LogIndex *big.Int + Timestamp *big.Int + ChainId *big.Int +} + +// InboxMetaData contains all meta data concerning the Inbox contract. +var InboxMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"executeMessage\",\"inputs\":[{\"name\":\"_id\",\"type\":\"tuple\",\"internalType\":\"structIdentifier\",\"components\":[{\"name\":\"origin\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"blockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"logIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"chainId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"_target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_message\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"validateMessage\",\"inputs\":[{\"name\":\"_id\",\"type\":\"tuple\",\"internalType\":\"structIdentifier\",\"components\":[{\"name\":\"origin\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"blockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"logIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"chainId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"name\":\"_msgHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"}]", +} + +// InboxABI is the input ABI used to generate the binding from. +// Deprecated: Use InboxMetaData.ABI instead. +var InboxABI = InboxMetaData.ABI + +// Inbox is an auto generated Go binding around an Ethereum contract. +type Inbox struct { + InboxCaller // Read-only binding to the contract + InboxTransactor // Write-only binding to the contract + InboxFilterer // Log filterer for contract events +} + +// InboxCaller is an auto generated read-only Go binding around an Ethereum contract. +type InboxCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// InboxTransactor is an auto generated write-only Go binding around an Ethereum contract. +type InboxTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// InboxFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type InboxFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// InboxSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type InboxSession struct { + Contract *Inbox // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// InboxCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type InboxCallerSession struct { + Contract *InboxCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// InboxTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type InboxTransactorSession struct { + Contract *InboxTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// InboxRaw is an auto generated low-level Go binding around an Ethereum contract. +type InboxRaw struct { + Contract *Inbox // Generic contract binding to access the raw methods on +} + +// InboxCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type InboxCallerRaw struct { + Contract *InboxCaller // Generic read-only contract binding to access the raw methods on +} + +// InboxTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type InboxTransactorRaw struct { + Contract *InboxTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewInbox creates a new instance of Inbox, bound to a specific deployed contract. +func NewInbox(address common.Address, backend bind.ContractBackend) (*Inbox, error) { + contract, err := bindInbox(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Inbox{InboxCaller: InboxCaller{contract: contract}, InboxTransactor: InboxTransactor{contract: contract}, InboxFilterer: InboxFilterer{contract: contract}}, nil +} + +// NewInboxCaller creates a new read-only instance of Inbox, bound to a specific deployed contract. +func NewInboxCaller(address common.Address, caller bind.ContractCaller) (*InboxCaller, error) { + contract, err := bindInbox(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &InboxCaller{contract: contract}, nil +} + +// NewInboxTransactor creates a new write-only instance of Inbox, bound to a specific deployed contract. +func NewInboxTransactor(address common.Address, transactor bind.ContractTransactor) (*InboxTransactor, error) { + contract, err := bindInbox(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &InboxTransactor{contract: contract}, nil +} + +// NewInboxFilterer creates a new log filterer instance of Inbox, bound to a specific deployed contract. +func NewInboxFilterer(address common.Address, filterer bind.ContractFilterer) (*InboxFilterer, error) { + contract, err := bindInbox(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &InboxFilterer{contract: contract}, nil +} + +// bindInbox binds a generic wrapper to an already deployed contract. +func bindInbox(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(InboxABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Inbox *InboxRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Inbox.Contract.InboxCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Inbox *InboxRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Inbox.Contract.InboxTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Inbox *InboxRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Inbox.Contract.InboxTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Inbox *InboxCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Inbox.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Inbox *InboxTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Inbox.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Inbox *InboxTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Inbox.Contract.contract.Transact(opts, method, params...) +} + +// ExecuteMessage is a paid mutator transaction binding the contract method 0x5984c53e. +// +// Solidity: function executeMessage((address,uint256,uint256,uint256,uint256) _id, address _target, bytes _message) payable returns() +func (_Inbox *InboxTransactor) ExecuteMessage(opts *bind.TransactOpts, _id Identifier, _target common.Address, _message []byte) (*types.Transaction, error) { + return _Inbox.contract.Transact(opts, "executeMessage", _id, _target, _message) +} + +// ExecuteMessage is a paid mutator transaction binding the contract method 0x5984c53e. +// +// Solidity: function executeMessage((address,uint256,uint256,uint256,uint256) _id, address _target, bytes _message) payable returns() +func (_Inbox *InboxSession) ExecuteMessage(_id Identifier, _target common.Address, _message []byte) (*types.Transaction, error) { + return _Inbox.Contract.ExecuteMessage(&_Inbox.TransactOpts, _id, _target, _message) +} + +// ExecuteMessage is a paid mutator transaction binding the contract method 0x5984c53e. +// +// Solidity: function executeMessage((address,uint256,uint256,uint256,uint256) _id, address _target, bytes _message) payable returns() +func (_Inbox *InboxTransactorSession) ExecuteMessage(_id Identifier, _target common.Address, _message []byte) (*types.Transaction, error) { + return _Inbox.Contract.ExecuteMessage(&_Inbox.TransactOpts, _id, _target, _message) +} + +// ValidateMessage is a paid mutator transaction binding the contract method 0xab4d6f75. +// +// Solidity: function validateMessage((address,uint256,uint256,uint256,uint256) _id, bytes32 _msgHash) returns() +func (_Inbox *InboxTransactor) ValidateMessage(opts *bind.TransactOpts, _id Identifier, _msgHash [32]byte) (*types.Transaction, error) { + return _Inbox.contract.Transact(opts, "validateMessage", _id, _msgHash) +} + +// ValidateMessage is a paid mutator transaction binding the contract method 0xab4d6f75. +// +// Solidity: function validateMessage((address,uint256,uint256,uint256,uint256) _id, bytes32 _msgHash) returns() +func (_Inbox *InboxSession) ValidateMessage(_id Identifier, _msgHash [32]byte) (*types.Transaction, error) { + return _Inbox.Contract.ValidateMessage(&_Inbox.TransactOpts, _id, _msgHash) +} + +// ValidateMessage is a paid mutator transaction binding the contract method 0xab4d6f75. +// +// Solidity: function validateMessage((address,uint256,uint256,uint256,uint256) _id, bytes32 _msgHash) returns() +func (_Inbox *InboxTransactorSession) ValidateMessage(_id Identifier, _msgHash [32]byte) (*types.Transaction, error) { + return _Inbox.Contract.ValidateMessage(&_Inbox.TransactOpts, _id, _msgHash) +} diff --git a/op-e2e/interop/contracts/bindings/systemconfig/systemconfig.go b/op-e2e/interop/contracts/bindings/systemconfig/systemconfig.go new file mode 100644 index 000000000000..9e29cc4700e5 --- /dev/null +++ b/op-e2e/interop/contracts/bindings/systemconfig/systemconfig.go @@ -0,0 +1,201 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package systemconfig + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// SystemconfigMetaData contains all meta data concerning the Systemconfig contract. +var SystemconfigMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"addDependency\",\"inputs\":[{\"name\":\"_chainId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"}]", +} + +// SystemconfigABI is the input ABI used to generate the binding from. +// Deprecated: Use SystemconfigMetaData.ABI instead. +var SystemconfigABI = SystemconfigMetaData.ABI + +// Systemconfig is an auto generated Go binding around an Ethereum contract. +type Systemconfig struct { + SystemconfigCaller // Read-only binding to the contract + SystemconfigTransactor // Write-only binding to the contract + SystemconfigFilterer // Log filterer for contract events +} + +// SystemconfigCaller is an auto generated read-only Go binding around an Ethereum contract. +type SystemconfigCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// SystemconfigTransactor is an auto generated write-only Go binding around an Ethereum contract. +type SystemconfigTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// SystemconfigFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type SystemconfigFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// SystemconfigSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type SystemconfigSession struct { + Contract *Systemconfig // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// SystemconfigCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type SystemconfigCallerSession struct { + Contract *SystemconfigCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// SystemconfigTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type SystemconfigTransactorSession struct { + Contract *SystemconfigTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// SystemconfigRaw is an auto generated low-level Go binding around an Ethereum contract. +type SystemconfigRaw struct { + Contract *Systemconfig // Generic contract binding to access the raw methods on +} + +// SystemconfigCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type SystemconfigCallerRaw struct { + Contract *SystemconfigCaller // Generic read-only contract binding to access the raw methods on +} + +// SystemconfigTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type SystemconfigTransactorRaw struct { + Contract *SystemconfigTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewSystemconfig creates a new instance of Systemconfig, bound to a specific deployed contract. +func NewSystemconfig(address common.Address, backend bind.ContractBackend) (*Systemconfig, error) { + contract, err := bindSystemconfig(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Systemconfig{SystemconfigCaller: SystemconfigCaller{contract: contract}, SystemconfigTransactor: SystemconfigTransactor{contract: contract}, SystemconfigFilterer: SystemconfigFilterer{contract: contract}}, nil +} + +// NewSystemconfigCaller creates a new read-only instance of Systemconfig, bound to a specific deployed contract. +func NewSystemconfigCaller(address common.Address, caller bind.ContractCaller) (*SystemconfigCaller, error) { + contract, err := bindSystemconfig(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &SystemconfigCaller{contract: contract}, nil +} + +// NewSystemconfigTransactor creates a new write-only instance of Systemconfig, bound to a specific deployed contract. +func NewSystemconfigTransactor(address common.Address, transactor bind.ContractTransactor) (*SystemconfigTransactor, error) { + contract, err := bindSystemconfig(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &SystemconfigTransactor{contract: contract}, nil +} + +// NewSystemconfigFilterer creates a new log filterer instance of Systemconfig, bound to a specific deployed contract. +func NewSystemconfigFilterer(address common.Address, filterer bind.ContractFilterer) (*SystemconfigFilterer, error) { + contract, err := bindSystemconfig(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &SystemconfigFilterer{contract: contract}, nil +} + +// bindSystemconfig binds a generic wrapper to an already deployed contract. +func bindSystemconfig(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(SystemconfigABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Systemconfig *SystemconfigRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Systemconfig.Contract.SystemconfigCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Systemconfig *SystemconfigRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Systemconfig.Contract.SystemconfigTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Systemconfig *SystemconfigRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Systemconfig.Contract.SystemconfigTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Systemconfig *SystemconfigCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Systemconfig.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Systemconfig *SystemconfigTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Systemconfig.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Systemconfig *SystemconfigTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Systemconfig.Contract.contract.Transact(opts, method, params...) +} + +// AddDependency is a paid mutator transaction binding the contract method 0xa89c793c. +// +// Solidity: function addDependency(uint256 _chainId) returns() +func (_Systemconfig *SystemconfigTransactor) AddDependency(opts *bind.TransactOpts, _chainId *big.Int) (*types.Transaction, error) { + return _Systemconfig.contract.Transact(opts, "addDependency", _chainId) +} + +// AddDependency is a paid mutator transaction binding the contract method 0xa89c793c. +// +// Solidity: function addDependency(uint256 _chainId) returns() +func (_Systemconfig *SystemconfigSession) AddDependency(_chainId *big.Int) (*types.Transaction, error) { + return _Systemconfig.Contract.AddDependency(&_Systemconfig.TransactOpts, _chainId) +} + +// AddDependency is a paid mutator transaction binding the contract method 0xa89c793c. +// +// Solidity: function addDependency(uint256 _chainId) returns() +func (_Systemconfig *SystemconfigTransactorSession) AddDependency(_chainId *big.Int) (*types.Transaction, error) { + return _Systemconfig.Contract.AddDependency(&_Systemconfig.TransactOpts, _chainId) +} diff --git a/op-e2e/interop/contracts/build/ICrossL2Inbox.sol/ICrossL2Inbox.abi b/op-e2e/interop/contracts/build/ICrossL2Inbox.sol/ICrossL2Inbox.abi new file mode 100644 index 000000000000..b724169ec6fa --- /dev/null +++ b/op-e2e/interop/contracts/build/ICrossL2Inbox.sol/ICrossL2Inbox.abi @@ -0,0 +1,97 @@ +[ + { + "type": "function", + "name": "executeMessage", + "inputs": [ + { + "name": "_id", + "type": "tuple", + "internalType": "struct Identifier", + "components": [ + { + "name": "origin", + "type": "address", + "internalType": "address" + }, + { + "name": "blockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "logIndex", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "timestamp", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "chainId", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "_target", + "type": "address", + "internalType": "address" + }, + { + "name": "_message", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "validateMessage", + "inputs": [ + { + "name": "_id", + "type": "tuple", + "internalType": "struct Identifier", + "components": [ + { + "name": "origin", + "type": "address", + "internalType": "address" + }, + { + "name": "blockNumber", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "logIndex", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "timestamp", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "chainId", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "_msgHash", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + } +] diff --git a/op-e2e/interop/contracts/build/ICrossL2Inbox.sol/ICrossL2Inbox.bin b/op-e2e/interop/contracts/build/ICrossL2Inbox.sol/ICrossL2Inbox.bin new file mode 100644 index 000000000000..ec687260b851 --- /dev/null +++ b/op-e2e/interop/contracts/build/ICrossL2Inbox.sol/ICrossL2Inbox.bin @@ -0,0 +1 @@ +0x diff --git a/op-e2e/interop/contracts/build/ICrossL2Inbox.sol/ICrossL2Inbox.json b/op-e2e/interop/contracts/build/ICrossL2Inbox.sol/ICrossL2Inbox.json new file mode 100644 index 000000000000..96c8d6ddb036 --- /dev/null +++ b/op-e2e/interop/contracts/build/ICrossL2Inbox.sol/ICrossL2Inbox.json @@ -0,0 +1 @@ +{"abi":[{"type":"function","name":"executeMessage","inputs":[{"name":"_id","type":"tuple","internalType":"struct Identifier","components":[{"name":"origin","type":"address","internalType":"address"},{"name":"blockNumber","type":"uint256","internalType":"uint256"},{"name":"logIndex","type":"uint256","internalType":"uint256"},{"name":"timestamp","type":"uint256","internalType":"uint256"},{"name":"chainId","type":"uint256","internalType":"uint256"}]},{"name":"_target","type":"address","internalType":"address"},{"name":"_message","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"validateMessage","inputs":[{"name":"_id","type":"tuple","internalType":"struct Identifier","components":[{"name":"origin","type":"address","internalType":"address"},{"name":"blockNumber","type":"uint256","internalType":"uint256"},{"name":"logIndex","type":"uint256","internalType":"uint256"},{"name":"timestamp","type":"uint256","internalType":"uint256"},{"name":"chainId","type":"uint256","internalType":"uint256"}]},{"name":"_msgHash","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"deployedBytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"methodIdentifiers":{"executeMessage((address,uint256,uint256,uint256,uint256),address,bytes)":"5984c53e","validateMessage((address,uint256,uint256,uint256,uint256),bytes32)":"ab4d6f75"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"origin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"logIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"}],\"internalType\":\"struct Identifier\",\"name\":\"_id\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"}],\"name\":\"executeMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"origin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"logIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"}],\"internalType\":\"struct Identifier\",\"name\":\"_id\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"_msgHash\",\"type\":\"bytes32\"}],\"name\":\"validateMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"executeMessage((address,uint256,uint256,uint256,uint256),address,bytes)\":{\"params\":{\"_id\":\"An Identifier pointing to the initiating message.\",\"_message\":\"The message payload, matching the initiating message.\",\"_target\":\"Account that is called with _msg.\"}},\"validateMessage((address,uint256,uint256,uint256,uint256),bytes32)\":{\"params\":{\"_id\":\"Identifier of the message.\",\"_msgHash\":\"Hash of the message payload to call target with.\"}}},\"title\":\"ICrossL2Inbox\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"executeMessage((address,uint256,uint256,uint256,uint256),address,bytes)\":{\"notice\":\"Executes a cross chain message on the destination chain.\"},\"validateMessage((address,uint256,uint256,uint256,uint256),bytes32)\":{\"notice\":\"Validates a cross chain message on the destination chain and emits an ExecutingMessage event. This function is useful for applications that understand the schema of the _message payload and want to process it in a custom way.\"}},\"notice\":\"Interface for the CrossL2Inbox contract.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/ICrossL2Inbox.sol\":\"ICrossL2Inbox\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"src/ICrossL2Inbox.sol\":{\"keccak256\":\"0x97daf76e4a10b96d8062e71df352cbfa7577593fa96676fd43b40f4a0aca9b7f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://74518c974318070da4e118cd28aa86d7f0702ed8cccc39d60906b93197687248\",\"dweb:/ipfs/QmWimBXYsDWDtNgzhjaLUx4xEiTMvbx5635E2TfNBKoV1E\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.25+commit.b61c2a91"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct Identifier","name":"_id","type":"tuple","components":[{"internalType":"address","name":"origin","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"logIndex","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"chainId","type":"uint256"}]},{"internalType":"address","name":"_target","type":"address"},{"internalType":"bytes","name":"_message","type":"bytes"}],"stateMutability":"payable","type":"function","name":"executeMessage"},{"inputs":[{"internalType":"struct Identifier","name":"_id","type":"tuple","components":[{"internalType":"address","name":"origin","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"logIndex","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"chainId","type":"uint256"}]},{"internalType":"bytes32","name":"_msgHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function","name":"validateMessage"}],"devdoc":{"kind":"dev","methods":{"executeMessage((address,uint256,uint256,uint256,uint256),address,bytes)":{"params":{"_id":"An Identifier pointing to the initiating message.","_message":"The message payload, matching the initiating message.","_target":"Account that is called with _msg."}},"validateMessage((address,uint256,uint256,uint256,uint256),bytes32)":{"params":{"_id":"Identifier of the message.","_msgHash":"Hash of the message payload to call target with."}}},"version":1},"userdoc":{"kind":"user","methods":{"executeMessage((address,uint256,uint256,uint256,uint256),address,bytes)":{"notice":"Executes a cross chain message on the destination chain."},"validateMessage((address,uint256,uint256,uint256,uint256),bytes32)":{"notice":"Validates a cross chain message on the destination chain and emits an ExecutingMessage event. This function is useful for applications that understand the schema of the _message payload and want to process it in a custom way."}},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/ICrossL2Inbox.sol":"ICrossL2Inbox"},"evmVersion":"cancun","libraries":{}},"sources":{"src/ICrossL2Inbox.sol":{"keccak256":"0x97daf76e4a10b96d8062e71df352cbfa7577593fa96676fd43b40f4a0aca9b7f","urls":["bzz-raw://74518c974318070da4e118cd28aa86d7f0702ed8cccc39d60906b93197687248","dweb:/ipfs/QmWimBXYsDWDtNgzhjaLUx4xEiTMvbx5635E2TfNBKoV1E"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user","methods":{"executeMessage((address,uint256,uint256,uint256,uint256),address,bytes)":{"notice":"Executes a cross chain message on the destination chain."},"validateMessage((address,uint256,uint256,uint256,uint256),bytes32)":{"notice":"Validates a cross chain message on the destination chain and emits an ExecutingMessage event. This function is useful for applications that understand the schema of the _message payload and want to process it in a custom way."}},"notice":"Interface for the CrossL2Inbox contract."},"devdoc":{"version":1,"kind":"dev","methods":{"executeMessage((address,uint256,uint256,uint256,uint256),address,bytes)":{"params":{"_id":"An Identifier pointing to the initiating message.","_message":"The message payload, matching the initiating message.","_target":"Account that is called with _msg."}},"validateMessage((address,uint256,uint256,uint256,uint256),bytes32)":{"params":{"_id":"Identifier of the message.","_msgHash":"Hash of the message payload to call target with."}}},"title":"ICrossL2Inbox"},"ast":{"absolutePath":"src/ICrossL2Inbox.sol","id":35,"exportedSymbols":{"ICrossL2Inbox":[34],"Identifier":[12]},"nodeType":"SourceUnit","src":"32:1153:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","^","0.8",".0"]},{"id":12,"nodeType":"StructDefinition","src":"57:132:0","nodes":[],"canonicalName":"Identifier","members":[{"constant":false,"id":3,"mutability":"mutable","name":"origin","nameLocation":"89:6:0","nodeType":"VariableDeclaration","scope":12,"src":"81:14:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":2,"name":"address","nodeType":"ElementaryTypeName","src":"81:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"blockNumber","nameLocation":"109:11:0","nodeType":"VariableDeclaration","scope":12,"src":"101:19:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":4,"name":"uint256","nodeType":"ElementaryTypeName","src":"101:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"},{"constant":false,"id":7,"mutability":"mutable","name":"logIndex","nameLocation":"134:8:0","nodeType":"VariableDeclaration","scope":12,"src":"126:16:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":6,"name":"uint256","nodeType":"ElementaryTypeName","src":"126:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"},{"constant":false,"id":9,"mutability":"mutable","name":"timestamp","nameLocation":"156:9:0","nodeType":"VariableDeclaration","scope":12,"src":"148:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":8,"name":"uint256","nodeType":"ElementaryTypeName","src":"148:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"},{"constant":false,"id":11,"mutability":"mutable","name":"chainId","nameLocation":"179:7:0","nodeType":"VariableDeclaration","scope":12,"src":"171:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":10,"name":"uint256","nodeType":"ElementaryTypeName","src":"171:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"name":"Identifier","nameLocation":"64:10:0","scope":35,"visibility":"public"},{"id":34,"nodeType":"ContractDefinition","src":"269:915:0","nodes":[{"id":24,"nodeType":"FunctionDefinition","src":"577:108:0","nodes":[],"documentation":{"id":14,"nodeType":"StructuredDocumentation","src":"300:272:0","text":"@notice Executes a cross chain message on the destination chain.\n @param _id An Identifier pointing to the initiating message.\n @param _target Account that is called with _msg.\n @param _message The message payload, matching the initiating message."},"functionSelector":"5984c53e","implemented":false,"kind":"function","modifiers":[],"name":"executeMessage","nameLocation":"586:14:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":17,"mutability":"mutable","name":"_id","nameLocation":"621:3:0","nodeType":"VariableDeclaration","scope":24,"src":"601:23:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_struct$_Identifier_$12_calldata_ptr","typeString":"struct Identifier"},"typeName":{"id":16,"nodeType":"UserDefinedTypeName","pathNode":{"id":15,"name":"Identifier","nameLocations":["601:10:0"],"nodeType":"IdentifierPath","referencedDeclaration":12,"src":"601:10:0"},"referencedDeclaration":12,"src":"601:10:0","typeDescriptions":{"typeIdentifier":"t_struct$_Identifier_$12_storage_ptr","typeString":"struct Identifier"}},"visibility":"internal"},{"constant":false,"id":19,"mutability":"mutable","name":"_target","nameLocation":"634:7:0","nodeType":"VariableDeclaration","scope":24,"src":"626:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":18,"name":"address","nodeType":"ElementaryTypeName","src":"626:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"_message","nameLocation":"658:8:0","nodeType":"VariableDeclaration","scope":24,"src":"643:23:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes"},"typeName":{"id":20,"name":"bytes","nodeType":"ElementaryTypeName","src":"643:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"600:67:0"},"returnParameters":{"id":23,"nodeType":"ParameterList","parameters":[],"src":"684:0:0"},"scope":34,"stateMutability":"payable","virtual":false,"visibility":"external"},{"id":33,"nodeType":"FunctionDefinition","src":"1105:77:0","nodes":[],"documentation":{"id":25,"nodeType":"StructuredDocumentation","src":"691:409:0","text":"@notice Validates a cross chain message on the destination chain\n and emits an ExecutingMessage event. This function is useful\n for applications that understand the schema of the _message payload and want to\n process it in a custom way.\n @param _id Identifier of the message.\n @param _msgHash Hash of the message payload to call target with."},"functionSelector":"ab4d6f75","implemented":false,"kind":"function","modifiers":[],"name":"validateMessage","nameLocation":"1114:15:0","parameters":{"id":31,"nodeType":"ParameterList","parameters":[{"constant":false,"id":28,"mutability":"mutable","name":"_id","nameLocation":"1150:3:0","nodeType":"VariableDeclaration","scope":33,"src":"1130:23:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_struct$_Identifier_$12_calldata_ptr","typeString":"struct Identifier"},"typeName":{"id":27,"nodeType":"UserDefinedTypeName","pathNode":{"id":26,"name":"Identifier","nameLocations":["1130:10:0"],"nodeType":"IdentifierPath","referencedDeclaration":12,"src":"1130:10:0"},"referencedDeclaration":12,"src":"1130:10:0","typeDescriptions":{"typeIdentifier":"t_struct$_Identifier_$12_storage_ptr","typeString":"struct Identifier"}},"visibility":"internal"},{"constant":false,"id":30,"mutability":"mutable","name":"_msgHash","nameLocation":"1163:8:0","nodeType":"VariableDeclaration","scope":33,"src":"1155:16:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"},"typeName":{"id":29,"name":"bytes32","nodeType":"ElementaryTypeName","src":"1155:7:0","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}},"visibility":"internal"}],"src":"1129:43:0"},"returnParameters":{"id":32,"nodeType":"ParameterList","parameters":[],"src":"1181:0:0"},"scope":34,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ICrossL2Inbox","contractDependencies":[],"contractKind":"interface","documentation":{"id":13,"nodeType":"StructuredDocumentation","src":"191:78:0","text":"@title ICrossL2Inbox\n @notice Interface for the CrossL2Inbox contract."},"fullyImplemented":false,"linearizedBaseContracts":[34],"name":"ICrossL2Inbox","nameLocation":"279:13:0","scope":35,"usedErrors":[],"usedEvents":[]}],"license":"MIT"},"id":0} \ No newline at end of file diff --git a/op-e2e/interop/contracts/build/ISystemConfig.sol/ISystemConfig.abi b/op-e2e/interop/contracts/build/ISystemConfig.sol/ISystemConfig.abi new file mode 100644 index 000000000000..7a7bffc2ca65 --- /dev/null +++ b/op-e2e/interop/contracts/build/ISystemConfig.sol/ISystemConfig.abi @@ -0,0 +1,15 @@ +[ + { + "type": "function", + "name": "addDependency", + "inputs": [ + { + "name": "_chainId", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + } +] diff --git a/op-e2e/interop/contracts/build/ISystemConfig.sol/ISystemConfig.bin b/op-e2e/interop/contracts/build/ISystemConfig.sol/ISystemConfig.bin new file mode 100644 index 000000000000..ec687260b851 --- /dev/null +++ b/op-e2e/interop/contracts/build/ISystemConfig.sol/ISystemConfig.bin @@ -0,0 +1 @@ +0x diff --git a/op-e2e/interop/contracts/build/ISystemConfig.sol/ISystemConfig.json b/op-e2e/interop/contracts/build/ISystemConfig.sol/ISystemConfig.json new file mode 100644 index 000000000000..fef67d0a40fd --- /dev/null +++ b/op-e2e/interop/contracts/build/ISystemConfig.sol/ISystemConfig.json @@ -0,0 +1 @@ +{"abi":[{"type":"function","name":"addDependency","inputs":[{"name":"_chainId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"deployedBytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"methodIdentifiers":{"addDependency(uint256)":"a89c793c"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_chainId\",\"type\":\"uint256\"}],\"name\":\"addDependency\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addDependency(uint256)\":{\"params\":{\"_chainId\":\"Chain ID of chain to add.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addDependency(uint256)\":{\"notice\":\"Adds a chain to the interop dependency set. Can only be called by the dependency manager.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/ISystemConfig.sol\":\"ISystemConfig\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"src/ISystemConfig.sol\":{\"keccak256\":\"0x764ea7e528e9e5ab907515b4da22738a49a3d5d8ffb948def86d0cbb9e7765be\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9307f5fd1e826f8d059f4aa9141c360aef54612ba8562ec996e7f078ef1d1cf2\",\"dweb:/ipfs/QmbzFSWWLoQUyeuD6U7detgjPy36L3DHJp9BPpaUZqVs68\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.25+commit.b61c2a91"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"addDependency"}],"devdoc":{"kind":"dev","methods":{"addDependency(uint256)":{"params":{"_chainId":"Chain ID of chain to add."}}},"version":1},"userdoc":{"kind":"user","methods":{"addDependency(uint256)":{"notice":"Adds a chain to the interop dependency set. Can only be called by the dependency manager."}},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/ISystemConfig.sol":"ISystemConfig"},"evmVersion":"cancun","libraries":{}},"sources":{"src/ISystemConfig.sol":{"keccak256":"0x764ea7e528e9e5ab907515b4da22738a49a3d5d8ffb948def86d0cbb9e7765be","urls":["bzz-raw://9307f5fd1e826f8d059f4aa9141c360aef54612ba8562ec996e7f078ef1d1cf2","dweb:/ipfs/QmbzFSWWLoQUyeuD6U7detgjPy36L3DHJp9BPpaUZqVs68"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user","methods":{"addDependency(uint256)":{"notice":"Adds a chain to the interop dependency set. Can only be called by the dependency manager."}}},"devdoc":{"version":1,"kind":"dev","methods":{"addDependency(uint256)":{"params":{"_chainId":"Chain ID of chain to add."}}}},"ast":{"absolutePath":"src/ISystemConfig.sol","id":9,"exportedSymbols":{"ISystemConfig":[8]},"nodeType":"SourceUnit","src":"32:264:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","^","0.8",".0"]},{"id":8,"nodeType":"ContractDefinition","src":"57:238:0","nodes":[{"id":7,"nodeType":"FunctionDefinition","src":"243:50:0","nodes":[],"documentation":{"id":2,"nodeType":"StructuredDocumentation","src":"87:151:0","text":"@notice Adds a chain to the interop dependency set. Can only be called by the dependency manager.\n @param _chainId Chain ID of chain to add."},"functionSelector":"a89c793c","implemented":false,"kind":"function","modifiers":[],"name":"addDependency","nameLocation":"252:13:0","parameters":{"id":5,"nodeType":"ParameterList","parameters":[{"constant":false,"id":4,"mutability":"mutable","name":"_chainId","nameLocation":"274:8:0","nodeType":"VariableDeclaration","scope":7,"src":"266:16:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":3,"name":"uint256","nodeType":"ElementaryTypeName","src":"266:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"265:18:0"},"returnParameters":{"id":6,"nodeType":"ParameterList","parameters":[],"src":"292:0:0"},"scope":8,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ISystemConfig","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[8],"name":"ISystemConfig","nameLocation":"67:13:0","scope":9,"usedErrors":[],"usedEvents":[]}],"license":"MIT"},"id":0} \ No newline at end of file diff --git a/op-e2e/interop/contracts/build/emit.sol/EmitEvent.abi b/op-e2e/interop/contracts/build/emit.sol/EmitEvent.abi new file mode 100644 index 000000000000..d30fa8fca93b --- /dev/null +++ b/op-e2e/interop/contracts/build/emit.sol/EmitEvent.abi @@ -0,0 +1,28 @@ +[ + { + "type": "function", + "name": "emitData", + "inputs": [ + { + "name": "_data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "event", + "name": "DataEmitted", + "inputs": [ + { + "name": "_data", + "type": "bytes", + "indexed": true, + "internalType": "bytes" + } + ], + "anonymous": false + } +] diff --git a/op-e2e/interop/contracts/build/emit.sol/EmitEvent.bin b/op-e2e/interop/contracts/build/emit.sol/EmitEvent.bin new file mode 100644 index 000000000000..f4c15ab05dca --- /dev/null +++ b/op-e2e/interop/contracts/build/emit.sol/EmitEvent.bin @@ -0,0 +1 @@ +0x6080604052348015600e575f80fd5b5060ff8061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063d836083e14602a575b5f80fd5b60396035366004607c565b603b565b005b8181604051604992919060e3565b604051908190038120907fe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c905f90a25050565b5f8060208385031215608c575f80fd5b823567ffffffffffffffff8082111560a2575f80fd5b818501915085601f83011260b4575f80fd5b81358181111560c1575f80fd5b86602082850101111560d1575f80fd5b60209290920196919550909350505050565b818382375f910190815291905056fea164736f6c6343000819000a diff --git a/op-e2e/interop/contracts/build/emit.sol/EmitEvent.json b/op-e2e/interop/contracts/build/emit.sol/EmitEvent.json new file mode 100644 index 000000000000..465823afa330 --- /dev/null +++ b/op-e2e/interop/contracts/build/emit.sol/EmitEvent.json @@ -0,0 +1 @@ +{"abi":[{"type":"function","name":"emitData","inputs":[{"name":"_data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"DataEmitted","inputs":[{"name":"_data","type":"bytes","indexed":true,"internalType":"bytes"}],"anonymous":false}],"bytecode":{"object":"0x6080604052348015600e575f80fd5b5060ff8061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063d836083e14602a575b5f80fd5b60396035366004607c565b603b565b005b8181604051604992919060e3565b604051908190038120907fe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c905f90a25050565b5f8060208385031215608c575f80fd5b823567ffffffffffffffff8082111560a2575f80fd5b818501915085601f83011260b4575f80fd5b81358181111560c1575f80fd5b86602082850101111560d1575f80fd5b60209290920196919550909350505050565b818382375f910190815291905056fea164736f6c6343000819000a","sourceMap":"58:278:1:-:0;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x6080604052348015600e575f80fd5b50600436106026575f3560e01c8063d836083e14602a575b5f80fd5b60396035366004607c565b603b565b005b8181604051604992919060e3565b604051908190038120907fe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c905f90a25050565b5f8060208385031215608c575f80fd5b823567ffffffffffffffff8082111560a2575f80fd5b818501915085601f83011260b4575f80fd5b81358181111560c1575f80fd5b86602082850101111560d1575f80fd5b60209290920196919550909350505050565b818382375f910190815291905056fea164736f6c6343000819000a","sourceMap":"58:278:1:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;245:89;;;;;;:::i;:::-;;:::i;:::-;;;321:5;;309:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;;245:89;;:::o;14:591:2:-;84:6;92;145:2;133:9;124:7;120:23;116:32;113:52;;;161:1;158;151:12;113:52;201:9;188:23;230:18;271:2;263:6;260:14;257:34;;;287:1;284;277:12;257:34;325:6;314:9;310:22;300:32;;370:7;363:4;359:2;355:13;351:27;341:55;;392:1;389;382:12;341:55;432:2;419:16;458:2;450:6;447:14;444:34;;;474:1;471;464:12;444:34;519:7;514:2;505:6;501:2;497:15;493:24;490:37;487:57;;;540:1;537;530:12;487:57;571:2;563:11;;;;;593:6;;-1:-1:-1;14:591:2;;-1:-1:-1;;;;14:591:2:o;610:271::-;793:6;785;780:3;767:33;749:3;819:16;;844:13;;;819:16;610:271;-1:-1:-1;610:271:2:o","linkReferences":{}},"methodIdentifiers":{"emitData(bytes)":"d836083e"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"DataEmitted\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"emitData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/emit.sol\":\"EmitEvent\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"src/emit.sol\":{\"keccak256\":\"0xe078378fd445ed0cbbf1087c5013110412ab6a44850af24a15bcde945467accc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://66c218de0059688c75903c2ba6d4066661dc6f5fa17a329dd7c385d151f3993a\",\"dweb:/ipfs/Qmby4S4N44naZ2miw3Tgdpq5Qbj4DwzJbcGapgqtd7qd26\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.25+commit.b61c2a91"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes","indexed":true}],"type":"event","name":"DataEmitted","anonymous":false},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"emitData"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/emit.sol":"EmitEvent"},"evmVersion":"cancun","libraries":{}},"sources":{"src/emit.sol":{"keccak256":"0xe078378fd445ed0cbbf1087c5013110412ab6a44850af24a15bcde945467accc","urls":["bzz-raw://66c218de0059688c75903c2ba6d4066661dc6f5fa17a329dd7c385d151f3993a","dweb:/ipfs/Qmby4S4N44naZ2miw3Tgdpq5Qbj4DwzJbcGapgqtd7qd26"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"src/emit.sol","id":52,"exportedSymbols":{"EmitEvent":[51]},"nodeType":"SourceUnit","src":"32:305:1","nodes":[{"id":36,"nodeType":"PragmaDirective","src":"32:24:1","nodes":[],"literals":["solidity","^","0.8",".15"]},{"id":51,"nodeType":"ContractDefinition","src":"58:278:1","nodes":[{"id":40,"nodeType":"EventDefinition","src":"133:39:1","nodes":[],"anonymous":false,"eventSelector":"e00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c","name":"DataEmitted","nameLocation":"139:11:1","parameters":{"id":39,"nodeType":"ParameterList","parameters":[{"constant":false,"id":38,"indexed":true,"mutability":"mutable","name":"_data","nameLocation":"165:5:1","nodeType":"VariableDeclaration","scope":40,"src":"151:19:1","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":37,"name":"bytes","nodeType":"ElementaryTypeName","src":"151:5:1","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"150:21:1"}},{"id":50,"nodeType":"FunctionDefinition","src":"245:89:1","nodes":[],"body":{"id":49,"nodeType":"Block","src":"294:40:1","nodes":[],"statements":[{"eventCall":{"arguments":[{"id":46,"name":"_data","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":42,"src":"321:5:1","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes calldata"}],"id":45,"name":"DataEmitted","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":40,"src":"309:11:1","typeDescriptions":{"typeIdentifier":"t_function_event_nonpayable$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory)"}},"id":47,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"309:18:1","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":48,"nodeType":"EmitStatement","src":"304:23:1"}]},"functionSelector":"d836083e","implemented":true,"kind":"function","modifiers":[],"name":"emitData","nameLocation":"254:8:1","parameters":{"id":43,"nodeType":"ParameterList","parameters":[{"constant":false,"id":42,"mutability":"mutable","name":"_data","nameLocation":"278:5:1","nodeType":"VariableDeclaration","scope":50,"src":"263:20:1","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes"},"typeName":{"id":41,"name":"bytes","nodeType":"ElementaryTypeName","src":"263:5:1","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"262:22:1"},"returnParameters":{"id":44,"nodeType":"ParameterList","parameters":[],"src":"294:0:1"},"scope":51,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"EmitEvent","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[51],"name":"EmitEvent","nameLocation":"67:9:1","scope":52,"usedErrors":[],"usedEvents":[40]}],"license":"MIT"},"id":1} \ No newline at end of file diff --git a/op-e2e/interop/contracts/generate.sh b/op-e2e/interop/contracts/generate.sh index bba960153ec6..d6107df9cc86 100755 --- a/op-e2e/interop/contracts/generate.sh +++ b/op-e2e/interop/contracts/generate.sh @@ -9,4 +9,21 @@ cat EmitEvent.json | jq -r '.bytecode.object' > EmitEvent.bin cat EmitEvent.json | jq '.abi' > EmitEvent.abi cd ../.. -abigen --abi ./build/emit.sol/EmitEvent.abi --bin ./build/emit.sol/EmitEvent.bin --pkg emit --out ./emit.go +mkdir -p bindings/emit +abigen --abi ./build/emit.sol/EmitEvent.abi --bin ./build/emit.sol/EmitEvent.bin --pkg emit --out ./bindings/emit/emit.go + +cd build/ICrossL2Inbox.sol +cat ICrossL2Inbox.json | jq -r '.bytecode.object' > ICrossL2Inbox.bin +cat ICrossL2Inbox.json | jq '.abi' > ICrossL2Inbox.abi +cd ../.. + +mkdir -p bindings/inbox +abigen --abi ./build/ICrossL2Inbox.sol/ICrossL2Inbox.abi --bin ./build/ICrossL2Inbox.sol/ICrossL2Inbox.bin --pkg inbox --out ./bindings/inbox/inbox.go + +cd build/ISystemConfig.sol +cat ISystemConfig.json | jq -r '.bytecode.object' > ISystemConfig.bin +cat ISystemConfig.json | jq '.abi' > ISystemConfig.abi +cd ../.. + +mkdir -p bindings/systemconfig +abigen --abi ./build/ISystemConfig.sol/ISystemConfig.abi --bin ./build/ISystemConfig.sol/ISystemConfig.bin --pkg systemconfig --out ./bindings/systemconfig/systemconfig.go diff --git a/op-e2e/interop/contracts/src/ICrossL2Inbox.sol b/op-e2e/interop/contracts/src/ICrossL2Inbox.sol new file mode 100644 index 000000000000..780b43d9753b --- /dev/null +++ b/op-e2e/interop/contracts/src/ICrossL2Inbox.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +struct Identifier { + address origin; + uint256 blockNumber; + uint256 logIndex; + uint256 timestamp; + uint256 chainId; +} + +/// @title ICrossL2Inbox +/// @notice Interface for the CrossL2Inbox contract. +interface ICrossL2Inbox { + + /// @notice Executes a cross chain message on the destination chain. + /// @param _id An Identifier pointing to the initiating message. + /// @param _target Account that is called with _msg. + /// @param _message The message payload, matching the initiating message. + function executeMessage(Identifier calldata _id, address _target, bytes calldata _message) external payable; + + /// @notice Validates a cross chain message on the destination chain + /// and emits an ExecutingMessage event. This function is useful + /// for applications that understand the schema of the _message payload and want to + /// process it in a custom way. + /// @param _id Identifier of the message. + /// @param _msgHash Hash of the message payload to call target with. + function validateMessage(Identifier calldata _id, bytes32 _msgHash) external; +} diff --git a/op-e2e/interop/contracts/src/ISystemConfig.sol b/op-e2e/interop/contracts/src/ISystemConfig.sol new file mode 100644 index 000000000000..fd14f919b2d0 --- /dev/null +++ b/op-e2e/interop/contracts/src/ISystemConfig.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface ISystemConfig { + /// @notice Adds a chain to the interop dependency set. Can only be called by the dependency manager. + /// @param _chainId Chain ID of chain to add. + function addDependency(uint256 _chainId) external; +} diff --git a/op-e2e/interop/interop_test.go b/op-e2e/interop/interop_test.go index 6724f468be51..65efa9b84209 100644 --- a/op-e2e/interop/interop_test.go +++ b/op-e2e/interop/interop_test.go @@ -7,6 +7,11 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-service/dial" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -157,8 +162,6 @@ func TestInteropTrivial_EmitLogs(t *testing.T) { } msgPayload = append(msgPayload, log.Data...) expectedHash := common.BytesToHash(crypto.Keccak256(msgPayload)) - // convert payload hash to log hash - logHash := types.PayloadHashToLogHash(expectedHash, log.Address) // get block for the log (for timestamp) ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) @@ -170,16 +173,16 @@ func TestInteropTrivial_EmitLogs(t *testing.T) { identifier := types.Identifier{ Origin: log.Address, BlockNumber: log.BlockNumber, - LogIndex: uint64(log.Index), + LogIndex: uint32(log.Index), Timestamp: block.Time(), ChainID: types.ChainIDFromBig(s2.ChainID(chainID)), } - safety, error := supervisor.CheckMessage(context.Background(), + safety, err := supervisor.CheckMessage(context.Background(), identifier, - logHash, + expectedHash, ) - require.ErrorIs(t, error, expectedError) + require.ErrorIs(t, err, expectedError) // the supervisor could progress the safety level more quickly than we expect, // which is why we check for a minimum safety level require.True(t, safety.AtLeastAsSafe(expectedSafety), "log: %v should be at least %s, but is %s", log, expectedSafety.String(), safety.String()) @@ -194,3 +197,98 @@ func TestInteropTrivial_EmitLogs(t *testing.T) { } setupAndRun(t, test) } + +func TestInteropBlockBuilding(t *testing.T) { + logger := testlog.Logger(t, log.LevelInfo) + oplog.SetGlobalLogHandler(logger.Handler()) + + test := func(t *testing.T, s2 SuperSystem) { + ids := s2.L2IDs() + chainA := ids[0] + chainB := ids[1] + // We will initiate on chain A, and execute on chain B + s2.DeployEmitterContract(chainA, "Alice") + + // Add chain A as dependency to chain B, + // such that we can execute a message on B that was initiated on A. + depRec := s2.AddDependency(chainB, s2.ChainID(chainA)) + t.Logf("Dependency set in L1 block %d", depRec.BlockNumber) + + rollupClA, err := dial.DialRollupClientWithTimeout(context.Background(), time.Second*15, logger, s2.OpNode(chainA).UserRPC().RPC()) + require.NoError(t, err) + + // Now wait for the dependency to be visible in the L2 (receipt needs to be picked up) + require.Eventually(t, func() bool { + status, err := rollupClA.SyncStatus(context.Background()) + require.NoError(t, err) + return status.CrossUnsafeL2.L1Origin.Number >= depRec.BlockNumber.Uint64() + }, time.Second*30, time.Second, "wait for L1 origin to match dependency L1 block") + t.Log("Dependency information has been processed in L2 block") + + // emit log on chain A + emitRec := s2.EmitData(chainA, "Alice", "hello world") + t.Logf("Emitted a log event in block %d", emitRec.BlockNumber.Uint64()) + + // Wait for initiating side to become cross-unsafe + require.Eventually(t, func() bool { + status, err := rollupClA.SyncStatus(context.Background()) + require.NoError(t, err) + return status.CrossUnsafeL2.Number >= emitRec.BlockNumber.Uint64() + }, time.Second*60, time.Second, "wait for emitted data to become cross-unsafe") + t.Logf("Reached cross-unsafe block %d", emitRec.BlockNumber.Uint64()) + + // Identify the log + require.Len(t, emitRec.Logs, 1) + ev := emitRec.Logs[0] + ethCl := s2.L2GethClient(chainA) + header, err := ethCl.HeaderByHash(context.Background(), emitRec.BlockHash) + require.NoError(t, err) + identifier := types.Identifier{ + Origin: ev.Address, + BlockNumber: ev.BlockNumber, + LogIndex: uint32(ev.Index), + Timestamp: header.Time, + ChainID: types.ChainIDFromBig(s2.ChainID(chainA)), + } + + msgPayload := types.LogToMessagePayload(ev) + payloadHash := crypto.Keccak256Hash(msgPayload) + logHash := types.PayloadHashToLogHash(payloadHash, identifier.Origin) + t.Logf("expected payload hash: %s", payloadHash) + t.Logf("expected log hash: %s", logHash) + + invalidPayload := []byte("test invalid message") + invalidPayloadHash := crypto.Keccak256Hash(invalidPayload) + invalidLogHash := types.PayloadHashToLogHash(invalidPayloadHash, identifier.Origin) + t.Logf("invalid payload hash: %s", invalidPayloadHash) + t.Logf("invalid log hash: %s", invalidLogHash) + + // submit executing txs on B + + t.Log("Testing invalid message") + { + bobAddr := s2.Address(chainA, "Bob") // direct it to a random account without code + ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) + defer cancel() + // Send an executing message, but with different payload. + // We expect the miner to be unable to include this tx, and confirmation to thus time out. + _, err := s2.ExecuteMessage(ctx, chainB, "Alice", identifier, bobAddr, invalidPayload) + require.NotNil(t, err) + require.ErrorIs(t, err, ctx.Err()) + require.ErrorIs(t, ctx.Err(), context.DeadlineExceeded) + } + + t.Log("Testing valid message now") + { + bobAddr := s2.Address(chainA, "Bob") // direct it to a random account without code + ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) + defer cancel() + // Send an executing message with the correct identifier / payload + rec, err := s2.ExecuteMessage(ctx, chainB, "Alice", identifier, bobAddr, msgPayload) + require.NoError(t, err, "expecting tx to be confirmed") + t.Logf("confirmed executing msg in block %s", rec.BlockNumber) + } + t.Log("Done") + } + setupAndRun(t, test) +} diff --git a/op-e2e/interop/supersystem.go b/op-e2e/interop/supersystem.go index 2d063174bdae..9f78c543bdcf 100644 --- a/op-e2e/interop/supersystem.go +++ b/op-e2e/interop/supersystem.go @@ -11,6 +11,12 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-e2e/interop/contracts/bindings/systemconfig" + "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum/go-ethereum/eth/ethconfig" + gn "github.com/ethereum/go-ethereum/node" + "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -33,7 +39,8 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/opnode" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/services" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/setuputils" - emit "github.com/ethereum-optimism/optimism/op-e2e/interop/contracts" + "github.com/ethereum-optimism/optimism/op-e2e/interop/contracts/bindings/emit" + "github.com/ethereum-optimism/optimism/op-e2e/interop/contracts/bindings/inbox" "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" "github.com/ethereum-optimism/optimism/op-node/node" "github.com/ethereum-optimism/optimism/op-node/p2p" @@ -96,6 +103,17 @@ type SuperSystem interface { DeployEmitterContract(network string, username string) common.Address // Use the Emitter Contract to emit an Event Log EmitData(network string, username string, data string) *types.Receipt + // AddDependency adds a dependency (by chain ID) to the given chain + AddDependency(network string, dep *big.Int) *types.Receipt + // ExecuteMessage calls the CrossL2Inbox executeMessage function + ExecuteMessage( + ctx context.Context, + id string, + sender string, + msgIdentifier supervisortypes.Identifier, + target common.Address, + message []byte, + ) (*types.Receipt, error) // Access a contract on a network by name Contract(network string, contractName string) interface{} } @@ -121,6 +139,7 @@ type interopE2ESystem struct { beacon *fakebeacon.FakeBeacon l1 *geth.GethInstance l2s map[string]l2Set + l1GethClient *ethclient.Client l2GethClients map[string]*ethclient.Client supervisor *supervisor.SupervisorService superClient *sources.SupervisorClient @@ -200,6 +219,7 @@ func (s *interopE2ESystem) prepareL1() (*fakebeacon.FakeBeacon, *geth.GethInstan require.NoError(s.t, err) require.NoError(s.t, l1Geth.Node.Start()) s.t.Cleanup(func() { + s.t.Logf("Closing L1 geth") _ = l1Geth.Close() }) return bcn, l1Geth @@ -239,11 +259,17 @@ func (s *interopE2ESystem) newOperatorKeysForL2(l2Out *interopgen.L2Output) map[ func (s *interopE2ESystem) newGethForL2(id string, l2Out *interopgen.L2Output) *geth.GethInstance { jwtPath := writeDefaultJWT(s.t) name := "l2-" + id - l2Geth, err := geth.InitL2(name, l2Out.Genesis, jwtPath) + l2Geth, err := geth.InitL2(name, l2Out.Genesis, jwtPath, + func(ethCfg *ethconfig.Config, nodeCfg *gn.Config) error { + ethCfg.InteropMessageRPC = s.supervisor.RPC() + return nil + }) require.NoError(s.t, err) require.NoError(s.t, l2Geth.Node.Start()) s.t.Cleanup(func() { - _ = l2Geth.Close() + s.t.Logf("Closing L2 geth of chain %s", id) + closeErr := l2Geth.Close() + s.t.Logf("Closed L2 geth of chain %s: %v", id, closeErr) }) return l2Geth } @@ -306,7 +332,9 @@ func (s *interopE2ESystem) newNodeForL2( s.t.Cleanup(func() { ctx, cancel := context.WithCancel(context.Background()) cancel() // force-quit + s.t.Logf("Closing op-node of chain %s", id) _ = opNode.Stop(ctx) + s.t.Logf("Closed op-node of chain %s", id) }) return opNode } @@ -390,7 +418,9 @@ func (s *interopE2ESystem) newBatcherForL2( s.t.Cleanup(func() { ctx, cancel := context.WithCancel(context.Background()) cancel() // force-quit + s.t.Logf("Closing batcher of chain %s", id) _ = batcher.Stop(ctx) + s.t.Logf("Closed batcher of chain %s", id) }) return batcher } @@ -471,7 +501,9 @@ func (s *interopE2ESystem) prepareSupervisor() *supervisor.SupervisorService { s.t.Cleanup(func() { ctx, cancel := context.WithCancel(context.Background()) cancel() // force-quit - _ = super.Stop(ctx) + s.t.Logf("Closing supervisor") + closeErr := super.Stop(ctx) + s.t.Logf("Closed supervisor: %v", closeErr) }) return super } @@ -503,12 +535,23 @@ func (s *interopE2ESystem) prepare(t *testing.T, w worldResourcePaths) { s.beacon, s.l1 = s.prepareL1() s.l2s = s.prepareL2s() + s.prepareContracts() + // add the L2 RPCs to the supervisor now that the L2s are created ctx := context.Background() for _, l2 := range s.l2s { err := s.SupervisorClient().AddL2RPC(ctx, l2.l2Geth.UserRPC().RPC()) require.NoError(s.t, err, "failed to add L2 RPC to supervisor") } + + // Try to close the op-supervisor first + s.t.Cleanup(func() { + ctx, cancel := context.WithCancel(context.Background()) + cancel() // force-quit + s.t.Logf("Closing supervisor") + closeErr := s.supervisor.Stop(ctx) + s.t.Logf("Closed supervisor: %v", closeErr) + }) } // AddUser adds a user to the system by creating a user key for each L2. @@ -552,6 +595,44 @@ func (s *interopE2ESystem) prepareL2s() map[string]l2Set { return l2s } +// prepareContracts prepares contract-bindings for the L2s +func (s *interopE2ESystem) prepareContracts() { + // Add bindings to common contracts for each L2 + l1GethClient := s.L1GethClient() + for id, l2Dep := range s.worldDeployment.L2s { + { + contract, err := inbox.NewInbox(predeploys.CrossL2InboxAddr, s.L2GethClient(id)) + require.NoError(s.t, err) + s.l2s[id].contracts["inbox"] = contract + } + { + contract, err := systemconfig.NewSystemconfig(l2Dep.SystemConfigProxy, l1GethClient) + require.NoError(s.t, err) + s.l2s[id].contracts["systemconfig"] = contract + } + } +} + +func (s *interopE2ESystem) L1GethClient() *ethclient.Client { + if s.l1GethClient != nil { + return s.l1GethClient + } + rpcEndpoint := s.l1.UserRPC() + rpcCl := endpoint.DialRPC( + endpoint.PreferAnyRPC, + rpcEndpoint, + func(v string) *rpc.Client { + logger := testlog.Logger(s.t, log.LevelInfo) + cl, err := dial.DialRPCClientWithTimeout(context.Background(), 30*time.Second, logger, v) + require.NoError(s.t, err, "failed to dial L1 eth node instance") + return cl + }) + nodeClient := ethclient.NewClient(rpcCl) + // register the client so it can be reused + s.l1GethClient = nodeClient + return nodeClient +} + func (s *interopE2ESystem) L2GethClient(id string) *ethclient.Client { // guard: check if the client already exists and return it in that case nodeClient, ok := s.l2GethClients[id] @@ -639,6 +720,64 @@ func (s *interopE2ESystem) SendL2Tx( newApply) } +func (s *interopE2ESystem) ExecuteMessage( + ctx context.Context, + id string, + sender string, + msgIdentifier supervisortypes.Identifier, + target common.Address, + message []byte, +) (*types.Receipt, error) { + secret := s.UserKey(id, sender) + auth, err := bind.NewKeyedTransactorWithChainID(&secret, s.l2s[id].chainID) + + require.NoError(s.t, err) + + auth.GasLimit = uint64(3000_000) + auth.GasPrice = big.NewInt(20_000_000_000) + + contract := s.Contract(id, "inbox").(*inbox.Inbox) + identifier := inbox.Identifier{ + Origin: msgIdentifier.Origin, + BlockNumber: new(big.Int).SetUint64(msgIdentifier.BlockNumber), + LogIndex: new(big.Int).SetUint64(uint64(msgIdentifier.LogIndex)), + Timestamp: new(big.Int).SetUint64(msgIdentifier.Timestamp), + ChainId: msgIdentifier.ChainID.ToBig(), + } + tx, err := contract.InboxTransactor.ExecuteMessage(auth, identifier, target, message) + require.NoError(s.t, err) + s.logger.Info("Executing message", "tx", tx.Hash(), "to", tx.To(), "target", target, "data", hexutil.Bytes(tx.Data())) + return bind.WaitMined(ctx, s.L2GethClient(id), tx) +} + +func (s *interopE2ESystem) AddDependency(id string, dep *big.Int) *types.Receipt { + // There is a note in OPContractsManagerInterop that the proxy-admin is used for now, + // even though it should be a separate dependency-set-manager address. + secret, err := s.hdWallet.Secret(devkeys.ChainOperatorKey{ + ChainID: s.l2s[id].chainID, + Role: devkeys.SystemConfigOwner, + }) + require.NoError(s.t, err) + + auth, err := bind.NewKeyedTransactorWithChainID(secret, s.worldOutput.L1.Genesis.Config.ChainID) + require.NoError(s.t, err) + + balance, err := s.l1GethClient.BalanceAt(context.Background(), crypto.PubkeyToAddress(secret.PublicKey), nil) + require.NoError(s.t, err) + require.False(s.t, balance.Sign() == 0, "system config owner needs a balance") + + auth.GasLimit = uint64(3000000) + auth.GasPrice = big.NewInt(20000000000) + + contract := s.Contract(id, "systemconfig").(*systemconfig.Systemconfig) + tx, err := contract.SystemconfigTransactor.AddDependency(auth, dep) + require.NoError(s.t, err) + + receipt, err := wait.ForReceiptOK(context.Background(), s.L1GethClient(), tx.Hash()) + require.NoError(s.t, err) + return receipt +} + func (s *interopE2ESystem) DeployEmitterContract( id string, sender string, diff --git a/op-supervisor/supervisor/backend/backend.go b/op-supervisor/supervisor/backend/backend.go index d4328f6932c7..cd824bfa6d31 100644 --- a/op-supervisor/supervisor/backend/backend.go +++ b/op-supervisor/supervisor/backend/backend.go @@ -267,6 +267,7 @@ func (su *SupervisorBackend) Stop(ctx context.Context) error { if !su.started.CompareAndSwap(true, false) { return errAlreadyStopped } + su.logger.Info("Closing supervisor backend") // close all processors for id, processor := range su.chainProcessors { su.logger.Info("stopping chain processor", "chainID", id) @@ -308,24 +309,27 @@ func (su *SupervisorBackend) DependencySet() depset.DependencySet { // Query methods // ---------------------------- -func (su *SupervisorBackend) CheckMessage(identifier types.Identifier, logHash common.Hash) (types.SafetyLevel, error) { +func (su *SupervisorBackend) CheckMessage(identifier types.Identifier, payloadHash common.Hash) (types.SafetyLevel, error) { su.mu.RLock() defer su.mu.RUnlock() + logHash := types.PayloadHashToLogHash(payloadHash, identifier.Origin) chainID := identifier.ChainID blockNum := identifier.BlockNumber logIdx := identifier.LogIndex - _, err := su.chainDBs.Check(chainID, blockNum, uint32(logIdx), logHash) + _, err := su.chainDBs.Check(chainID, blockNum, logIdx, logHash) if errors.Is(err, types.ErrFuture) { + su.logger.Debug("Future message", "identifier", identifier, "payloadHash", payloadHash, "err", err) return types.LocalUnsafe, nil } if errors.Is(err, types.ErrConflict) { + su.logger.Debug("Conflicting message", "identifier", identifier, "payloadHash", payloadHash, "err", err) return types.Invalid, nil } if err != nil { return types.Invalid, fmt.Errorf("failed to check log: %w", err) } - return su.chainDBs.Safest(chainID, blockNum, uint32(logIdx)) + return su.chainDBs.Safest(chainID, blockNum, logIdx) } func (su *SupervisorBackend) CheckMessages( @@ -334,12 +338,21 @@ func (su *SupervisorBackend) CheckMessages( su.mu.RLock() defer su.mu.RUnlock() + su.logger.Debug("Checking messages", "count", len(messages), "minSafety", minSafety) + for _, msg := range messages { + su.logger.Debug("Checking message", + "identifier", msg.Identifier, "payloadHash", msg.PayloadHash.String()) safety, err := su.CheckMessage(msg.Identifier, msg.PayloadHash) if err != nil { + su.logger.Error("Check message failed", "err", err, + "identifier", msg.Identifier, "payloadHash", msg.PayloadHash.String()) return fmt.Errorf("failed to check message: %w", err) } if !safety.AtLeastAsSafe(minSafety) { + su.logger.Error("Message is not sufficiently safe", + "safety", safety, "minSafety", minSafety, + "identifier", msg.Identifier, "payloadHash", msg.PayloadHash.String()) return fmt.Errorf("message %v (safety level: %v) does not meet the minimum safety %v", msg.Identifier, safety, diff --git a/op-supervisor/supervisor/backend/db/logs/db.go b/op-supervisor/supervisor/backend/db/logs/db.go index dc98b7472074..5509c5e61df8 100644 --- a/op-supervisor/supervisor/backend/db/logs/db.go +++ b/op-supervisor/supervisor/backend/db/logs/db.go @@ -287,7 +287,7 @@ func (db *DB) Contains(blockNum uint64, logIdx uint32, logHash common.Hash) (typ db.log.Trace("Found initiatingEvent", "blockNum", blockNum, "logIdx", logIdx, "hash", evtHash) // Found the requested block and log index, check if the hash matches if evtHash != logHash { - return types.BlockSeal{}, fmt.Errorf("payload hash mismatch: expected %s, got %s", logHash, evtHash) + return types.BlockSeal{}, fmt.Errorf("payload hash mismatch: expected %s, got %s %w", logHash, evtHash, types.ErrConflict) } // Now find the block seal after the log, to identify where the log was included in. err = iter.TraverseConditional(func(state IteratorState) error { diff --git a/op-supervisor/supervisor/backend/processors/log_processor.go b/op-supervisor/supervisor/backend/processors/log_processor.go index 1434d2a60395..e8adb29ce6bf 100644 --- a/op-supervisor/supervisor/backend/processors/log_processor.go +++ b/op-supervisor/supervisor/backend/processors/log_processor.go @@ -77,18 +77,6 @@ func (p *logProcessor) ProcessLogs(_ context.Context, block eth.BlockRef, rcpts // The address is hashed into the payload hash to save space in the log storage, // and because they represent paired data. func logToLogHash(l *ethTypes.Log) common.Hash { - payloadHash := crypto.Keccak256(logToMessagePayload(l)) + payloadHash := crypto.Keccak256(types.LogToMessagePayload(l)) return types.PayloadHashToLogHash(common.Hash(payloadHash), l.Address) } - -// logToMessagePayload is the data that is hashed to get the logHash -// it is the concatenation of the log's topics and data -// the implementation is based on the interop messaging spec -func logToMessagePayload(l *ethTypes.Log) []byte { - msg := make([]byte, 0) - for _, topic := range l.Topics { - msg = append(msg, topic.Bytes()...) - } - msg = append(msg, l.Data...) - return msg -} diff --git a/op-supervisor/supervisor/service.go b/op-supervisor/supervisor/service.go index 8bccaf1eb82f..7054c7e0ff55 100644 --- a/op-supervisor/supervisor/service.go +++ b/op-supervisor/supervisor/service.go @@ -184,6 +184,7 @@ func (su *SupervisorService) Start(ctx context.Context) error { func (su *SupervisorService) Stop(ctx context.Context) error { if !su.closing.CompareAndSwap(false, true) { + su.log.Warn("Supervisor is already closing") return nil // already closing } su.log.Info("Stopping JSON-RPC server") diff --git a/op-supervisor/supervisor/types/types.go b/op-supervisor/supervisor/types/types.go index b1aab4d081e8..bac2c377bfd7 100644 --- a/op-supervisor/supervisor/types/types.go +++ b/op-supervisor/supervisor/types/types.go @@ -8,6 +8,8 @@ import ( "math/big" "strconv" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/holiman/uint256" "github.com/ethereum/go-ethereum/common" @@ -58,7 +60,7 @@ type Message struct { type Identifier struct { Origin common.Address BlockNumber uint64 - LogIndex uint64 + LogIndex uint32 Timestamp uint64 ChainID ChainID // flat, not a pointer, to make Identifier safe as map key } @@ -88,7 +90,10 @@ func (id *Identifier) UnmarshalJSON(input []byte) error { } id.Origin = dec.Origin id.BlockNumber = uint64(dec.BlockNumber) - id.LogIndex = uint64(dec.LogIndex) + if dec.LogIndex > math.MaxUint32 { + return fmt.Errorf("log index too large: %d", dec.LogIndex) + } + id.LogIndex = uint32(dec.LogIndex) id.Timestamp = uint64(dec.Timestamp) id.ChainID = (ChainID)(dec.ChainID) return nil @@ -190,6 +195,10 @@ func (id ChainID) ToUInt32() (uint32, error) { return uint32(v64), nil } +func (id *ChainID) ToBig() *big.Int { + return (*uint256.Int)(id).ToBig() +} + func (id ChainID) MarshalText() ([]byte, error) { return []byte(id.String()), nil } @@ -264,3 +273,15 @@ func PayloadHashToLogHash(payloadHash common.Hash, addr common.Address) common.H msg = append(msg, payloadHash.Bytes()...) return crypto.Keccak256Hash(msg) } + +// LogToMessagePayload is the data that is hashed to get the payloadHash +// it is the concatenation of the log's topics and data +// the implementation is based on the interop messaging spec +func LogToMessagePayload(l *ethTypes.Log) []byte { + msg := make([]byte, 0) + for _, topic := range l.Topics { + msg = append(msg, topic.Bytes()...) + } + msg = append(msg, l.Data...) + return msg +} diff --git a/op-supervisor/supervisor/types/types_test.go b/op-supervisor/supervisor/types/types_test.go index 50c856bdc794..7e3e0d4843a9 100644 --- a/op-supervisor/supervisor/types/types_test.go +++ b/op-supervisor/supervisor/types/types_test.go @@ -13,7 +13,7 @@ import ( ) func FuzzRoundtripIdentifierJSONMarshal(f *testing.F) { - f.Fuzz(func(t *testing.T, origin []byte, blockNumber uint64, logIndex uint64, timestamp uint64, chainID []byte) { + f.Fuzz(func(t *testing.T, origin []byte, blockNumber uint64, logIndex uint32, timestamp uint64, chainID []byte) { if len(chainID) > 32 { chainID = chainID[:32] } @@ -55,7 +55,19 @@ func TestChainID_String(t *testing.T) { for _, test := range tests { test := test t.Run(test.expected, func(t *testing.T) { - require.Equal(t, test.expected, test.input.String()) + t.Run("String", func(t *testing.T) { + require.Equal(t, test.expected, test.input.String()) + }) + t.Run("MarshalText", func(t *testing.T) { + data, err := test.input.MarshalText() + require.NoError(t, err) + require.Equal(t, test.expected, string(data)) + }) + t.Run("UnmarshalText", func(t *testing.T) { + var id ChainID + require.NoError(t, id.UnmarshalText([]byte(test.expected))) + require.Equal(t, test.input, id) + }) }) } } diff --git a/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol b/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol index 9d541434a397..19de5537b41c 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol @@ -32,12 +32,12 @@ contract OPContractsManagerInterop is OPContractsManager { (IResourceMetering.ResourceConfig memory referenceResourceConfig, ISystemConfig.Addresses memory opChainAddrs) = defaultSystemConfigParams(_selector, _input, _output); - // TODO For now we assume that the dependency manager is the same as the proxy admin owner. + // TODO For now we assume that the dependency manager is the same as system config owner. // This is currently undefined since it's not part of the standard config, so we may need // to update where this value is pulled from in the future. To support a different dependency // manager in this contract without an invasive change of redefining the `Roles` struct, // we will make the change described in https://github.com/ethereum-optimism/optimism/issues/11783. - address dependencyManager = address(_input.roles.opChainProxyAdminOwner); + address dependencyManager = address(_input.roles.systemConfigOwner); return abi.encodeWithSelector( _selector,