diff --git a/.changeset/stupid-worlds-marry.md b/.changeset/stupid-worlds-marry.md new file mode 100644 index 00000000..2e657177 --- /dev/null +++ b/.changeset/stupid-worlds-marry.md @@ -0,0 +1,5 @@ +--- +"@smartcontractkit/mcms": minor +--- + +add timelock converter and inspector helpers diff --git a/.mockery.yaml b/.mockery.yaml index 959cf9e1..6614b171 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -32,6 +32,7 @@ packages: config: dir: "./sdk/ton/mocks" filename: "api.go" + github.com/smartcontractkit/mcms/inspectors: github.com/smartcontractkit/mcms/sdk: github.com/smartcontractkit/mcms/sdk/evm: github.com/smartcontractkit/mcms/sdk/evm/bindings: diff --git a/.tool-versions b/.tool-versions index d480b403..67912758 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,4 +1,4 @@ -golang 1.24.4 +golang 1.25.3 golangci-lint 2.1.6 mockery 2.53.5 nodejs 20.16.0 diff --git a/chainsmetadata/aptos_helpers.go b/chainsmetadata/aptos_helpers.go new file mode 100644 index 00000000..8b337e48 --- /dev/null +++ b/chainsmetadata/aptos_helpers.go @@ -0,0 +1,21 @@ +package chainsmetadata + +import ( + "errors" + + "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" +) + +func AptosRoleFromAction(action types.TimelockAction) (aptos.TimelockRole, error) { + switch action { + case types.TimelockActionBypass: + return aptos.TimelockRoleBypasser, nil + case types.TimelockActionSchedule: + return aptos.TimelockRoleProposer, nil + case types.TimelockActionCancel: + return aptos.TimelockRoleCanceller, nil + default: + return 0, errors.New("unknown timelock action") + } +} diff --git a/chainsmetadata/aptos_helpers_test.go b/chainsmetadata/aptos_helpers_test.go new file mode 100644 index 00000000..eb20466a --- /dev/null +++ b/chainsmetadata/aptos_helpers_test.go @@ -0,0 +1,64 @@ +package chainsmetadata + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/mcms/sdk/aptos" + mcmsTypes "github.com/smartcontractkit/mcms/types" +) + +func TestAptosRoleFromAction(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + action mcmsTypes.TimelockAction + expectedRole aptos.TimelockRole + expectError bool + }{ + { + name: "bypass action returns bypasser role", + action: mcmsTypes.TimelockActionBypass, + expectedRole: aptos.TimelockRoleBypasser, + expectError: false, + }, + { + name: "schedule action returns proposer role", + action: mcmsTypes.TimelockActionSchedule, + expectedRole: aptos.TimelockRoleProposer, + expectError: false, + }, + { + name: "cancel action returns canceller role", + action: mcmsTypes.TimelockActionCancel, + expectedRole: aptos.TimelockRoleCanceller, + expectError: false, + }, + { + name: "unknown action returns error", + action: mcmsTypes.TimelockAction("unknown"), + expectedRole: 0, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + role, err := AptosRoleFromAction(tt.action) + + if tt.expectError { + require.Error(t, err) + assert.Equal(t, "unknown timelock action", err.Error()) + assert.Equal(t, tt.expectedRole, role) + } else { + require.NoError(t, err) + assert.Equal(t, tt.expectedRole, role) + } + }) + } +} diff --git a/chainsmetadata/sui_helpers.go b/chainsmetadata/sui_helpers.go new file mode 100644 index 00000000..b4d21467 --- /dev/null +++ b/chainsmetadata/sui_helpers.go @@ -0,0 +1,24 @@ +package chainsmetadata + +import ( + "encoding/json" + "fmt" + + "github.com/smartcontractkit/mcms/sdk/sui" + "github.com/smartcontractkit/mcms/types" +) + +func SuiMetadata(chainMetadata types.ChainMetadata) (sui.AdditionalFieldsMetadata, error) { + var metadata sui.AdditionalFieldsMetadata + err := json.Unmarshal([]byte(chainMetadata.AdditionalFields), &metadata) + if err != nil { + return sui.AdditionalFieldsMetadata{}, fmt.Errorf("error unmarshaling sui chain metadata: %w", err) + } + + err = metadata.Validate() + if err != nil { + return sui.AdditionalFieldsMetadata{}, fmt.Errorf("error validating sui chain metadata: %w", err) + } + + return metadata, nil +} diff --git a/chainsmetadata/sui_helpers_test.go b/chainsmetadata/sui_helpers_test.go new file mode 100644 index 00000000..a1ba9248 --- /dev/null +++ b/chainsmetadata/sui_helpers_test.go @@ -0,0 +1,77 @@ +package chainsmetadata + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/mcms/sdk/sui" + "github.com/smartcontractkit/mcms/types" +) + +func TestSuiMetadata(t *testing.T) { + t.Parallel() + + validMetadata := types.ChainMetadata{ + AdditionalFields: []byte(`{"mcms_package_id":"0x1","role":1,"account_obj":"0x2","registry_obj":"0x3","timelock_obj":"0x4","deployer_state_obj":"0x5"}`), + } + + tests := []struct { + name string + metadata types.ChainMetadata + expectError bool + errorMsg string + }{ + { + name: "valid metadata returns success", + metadata: validMetadata, + }, + { + name: "invalid JSON returns error", + metadata: types.ChainMetadata{ + AdditionalFields: []byte(`{"mcms_package_id":"0x1","role":1`), + }, + expectError: true, + errorMsg: "error unmarshaling sui chain metadata", + }, + { + name: "missing required fields returns validation error", + metadata: types.ChainMetadata{ + AdditionalFields: []byte(`{"role":1}`), + }, + expectError: true, + errorMsg: "error validating sui chain metadata", + }, + { + name: "empty additional fields returns unmarshaling error", + metadata: types.ChainMetadata{ + AdditionalFields: nil, + }, + expectError: true, + errorMsg: "error unmarshaling sui chain metadata", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + metadata, err := SuiMetadata(tt.metadata) + if tt.expectError { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.errorMsg) + assert.Equal(t, sui.AdditionalFieldsMetadata{}, metadata) + + return + } + + require.NoError(t, err) + assert.Equal(t, "0x1", metadata.McmsPackageID) + assert.Equal(t, sui.TimelockRole(1), metadata.Role) + assert.Equal(t, "0x2", metadata.AccountObj) + assert.Equal(t, "0x3", metadata.RegistryObj) + assert.Equal(t, "0x4", metadata.TimelockObj) + }) + } +} diff --git a/converters/converters.go b/converters/converters.go new file mode 100644 index 00000000..5f0af5b4 --- /dev/null +++ b/converters/converters.go @@ -0,0 +1,41 @@ +package proposalutils + +import ( + "fmt" + + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/sdk/evm" + "github.com/smartcontractkit/mcms/sdk/solana" + "github.com/smartcontractkit/mcms/types" +) + +// BuildConverters constructs a map of chain selectors to their respective timelock converters based on the provided timelock proposal. +func BuildConverters(proposal mcms.TimelockProposal) (map[types.ChainSelector]sdk.TimelockConverter, error) { + converters := make(map[types.ChainSelector]sdk.TimelockConverter) + for chainMeta := range proposal.ChainMetadata { + fam, err := types.GetChainSelectorFamily(chainMeta) + if err != nil { + return nil, fmt.Errorf("error getting chain family: %w", err) + } + + var converter sdk.TimelockConverter + switch fam { + case chainsel.FamilyEVM: + converter = evm.NewTimelockConverter() + case chainsel.FamilySolana: + converter = solana.NewTimelockConverter() + case chainsel.FamilyAptos: + converter = aptos.NewTimelockConverter() + default: + return nil, fmt.Errorf("unsupported chain family %s", fam) + } + + converters[chainMeta] = converter + } + + return converters, nil +} diff --git a/docs/docs/contributing/integrating-new-chain-guide.md b/docs/docs/contributing/integrating-new-chain-guide.md index 432faed8..fe8ac5da 100644 --- a/docs/docs/contributing/integrating-new-chain-guide.md +++ b/docs/docs/contributing/integrating-new-chain-guide.md @@ -43,6 +43,18 @@ All chain family integrations must implement interfaces defined in the `/sdk` fo | `TimelockInspector` | **Required** | Query timelock contract state | [timelock_inspector.go](https://github.com/smartcontractkit/mcms/blob/main/sdk/timelock_inspector.go) | | `TimelockConverter` | **Required** | Convert batch operations to timelock operations | [timelock_converter.go](https://github.com/smartcontractkit/mcms/blob/main/sdk/timelock_converter.go) | +### ChainAccess Registry Adapter + +The MCMS SDK intentionally avoids importing chain-registry implementations (for example, the Chainlink Deployments Framework). Instead, shared tooling must expose the `ChainAccess` interface defined in [`sdk/chainclient.go`](https://github.com/smartcontractkit/mcms/blob/main/sdk/chainclient.go) so inspectors and proposal tooling can fetch RPC clients without pulling in external dependencies. + +Your adapter should: + +- Implement `Selectors() []uint64` and the per-family lookup helpers (`EVMClient`, `SolanaClient`, `AptosClient`, `Sui`) by delegating to your registry. +- Return chain clients that satisfy `bind.ContractBackend`/`bind.DeployBackend` for EVM, `*solrpc.Client` for Solana, `aptoslib.AptosRpcClient` for Aptos, and `(sui.ISuiAPI, SuiSigner)` for Sui, etc. +- Live in the repository that already depends on your registry (e.g., CLDF or deployment tooling) so `mcms` itself stays agnostic. + +This boundary keeps MCMS reusable across environments while still allowing downstream systems to map their chain catalogs into MCMS inspectors. + ## Required Interfaces ### Executor Interface @@ -360,6 +372,7 @@ Use the `/sdk/errors/` package for standardized error handling: Each interface implementation needs a corresponding `_test.go` file with comprehensive coverage (>80%). Test all public methods with both success and failure cases using table-driven tests. Mock external dependencies (RPC clients, contracts) in `sdk//mocks/`. **Test Examples:** + - [EVM Tests](https://github.com/smartcontractkit/mcms/blob/main/sdk/evm/executor_test.go) | [Mock Examples](https://github.com/smartcontractkit/mcms/tree/main/sdk/evm/mocks) - [Solana Tests](https://github.com/smartcontractkit/mcms/blob/main/sdk/solana/encoder_test.go) | [Mocks](https://github.com/smartcontractkit/mcms/tree/main/sdk/solana/mocks) - [Aptos Tests](https://github.com/smartcontractkit/mcms/blob/main/sdk/aptos/inspector_test.go) | [Mocks](https://github.com/smartcontractkit/mcms/tree/main/sdk/aptos/mocks) @@ -368,19 +381,20 @@ Each interface implementation needs a corresponding `_test.go` file with compreh Create test suite under `/e2e/tests//` covering: -| Test Category | Example | Key Coverage | -|---------------|---------|--------------| -| **Config Management** | [solana/set_config.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/set_config.go) | Set/update config, retrieve and verify, clearRoot flag | -| **Root Operations** | [solana/set_root.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/set_root.go) | Set root with signatures, quorum requirements, expiration | -| **Operation Execution** | [solana/execute.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/execute.go) | Execute with valid proof, verify effects, test invalid proofs | -| **Contract Inspection** | [solana/inspection.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/inspection.go) | Query config, op count, root, metadata | -| **Simulation** (optional) | [solana/simulator.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/simulator.go) | Simulate valid/invalid ops, verify no state changes | -| **Timelock Conversion** (optional) | [solana/timelock_converter.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/timelock_converter.go) | Convert batch to timelock ops, verify IDs and actions | -| **Timelock Execution** (optional) | [solana/timelock_execution.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/timelock_execution.go) | Schedule with delay, execute after delay, predecessors | -| **Timelock Inspection** (optional) | [solana/timelock_inspection.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/timelock_inspection.go) | Query roles, operation status, minimum delay | -| **Timelock Cancellation** (optional) | [aptos/timelock_cancel.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/aptos/timelock_cancel.go) | Cancel pending ops, verify cancellation | +| Test Category | Example | Key Coverage | +|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------| +| **Config Management** | [solana/set_config.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/set_config.go) | Set/update config, retrieve and verify, clearRoot flag | +| **Root Operations** | [solana/set_root.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/set_root.go) | Set root with signatures, quorum requirements, expiration | +| **Operation Execution** | [solana/execute.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/execute.go) | Execute with valid proof, verify effects, test invalid proofs | +| **Contract Inspection** | [solana/inspection.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/inspection.go) | Query config, op count, root, metadata | +| **Simulation** (optional) | [solana/simulator.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/simulator.go) | Simulate valid/invalid ops, verify no state changes | +| **Timelock Conversion** (optional) | [solana/timelock_converter.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/timelock_converter.go) | Convert batch to timelock ops, verify IDs and actions | +| **Timelock Execution** (optional) | [solana/timelock_execution.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/timelock_execution.go) | Schedule with delay, execute after delay, predecessors | +| **Timelock Inspection** (optional) | [solana/timelock_inspection.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/solana/timelock_inspection.go) | Query roles, operation status, minimum delay | +| **Timelock Cancellation** (optional) | [aptos/timelock_cancel.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/aptos/timelock_cancel.go) | Cancel pending ops, verify cancellation | **Test Suite Setup:** + 1. Create `e2e/config..toml` ([example](https://github.com/smartcontractkit/mcms/blob/main/e2e/config.evm.toml)) 2. Update [e2e/tests/setup.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/setup.go) with blockchain node and RPC clients 3. Add suite to [e2e/tests/runner_test.go](https://github.com/smartcontractkit/mcms/blob/main/e2e/tests/runner_test.go) diff --git a/inspectors/inspectors.go b/inspectors/inspectors.go new file mode 100644 index 00000000..4ca06898 --- /dev/null +++ b/inspectors/inspectors.go @@ -0,0 +1,91 @@ +package inspectors + +import ( + "fmt" + + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/mcms/chainsmetadata" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/sdk/evm" + "github.com/smartcontractkit/mcms/sdk/solana" + sdkSui "github.com/smartcontractkit/mcms/sdk/sui" + "github.com/smartcontractkit/mcms/types" +) + +// BuildInspectors gets a map of inspectors for the given chain metadata and chain clients +func BuildInspectors( + chains sdk.ChainAccess, + chainMetadata map[types.ChainSelector]types.ChainMetadata, + action types.TimelockAction) (map[types.ChainSelector]sdk.Inspector, error) { + inspectors := map[types.ChainSelector]sdk.Inspector{} + for chainSelector, metadata := range chainMetadata { + inspector, err := BuildInspector(chains, chainSelector, action, metadata) + if err != nil { + return nil, err + } + inspectors[chainSelector] = inspector + } + + return inspectors, nil +} + +// BuildInspector constructs a chain-family-specific Inspector from ChainAccess plus metadata. +func BuildInspector( + chains sdk.ChainAccess, + selector types.ChainSelector, + action types.TimelockAction, + metadata types.ChainMetadata, +) (sdk.Inspector, error) { + if chains == nil { + return nil, fmt.Errorf("chain access is required") + } + + family, err := types.GetChainSelectorFamily(selector) + if err != nil { + return nil, fmt.Errorf("error getting chain family: %w", err) + } + + rawSelector := uint64(selector) + switch family { + case chainsel.FamilyEVM: + client, ok := chains.EVMClient(rawSelector) + if !ok { + return nil, fmt.Errorf("missing EVM chain client for selector %d", rawSelector) + } + + return evm.NewInspector(client), nil + case chainsel.FamilySolana: + client, ok := chains.SolanaClient(rawSelector) + if !ok { + return nil, fmt.Errorf("missing Solana chain client for selector %d", rawSelector) + } + + return solana.NewInspector(client), nil + case chainsel.FamilyAptos: + client, ok := chains.AptosClient(rawSelector) + if !ok { + return nil, fmt.Errorf("missing Aptos chain client for selector %d", rawSelector) + } + role, err := chainsmetadata.AptosRoleFromAction(action) + if err != nil { + return nil, fmt.Errorf("error determining aptos role: %w", err) + } + + return aptos.NewInspector(client, role), nil + case chainsel.FamilySui: + client, signer, ok := chains.SuiClient(rawSelector) + if !ok { + return nil, fmt.Errorf("missing Sui chain client for selector %d", rawSelector) + } + suiMetadata, err := chainsmetadata.SuiMetadata(metadata) + if err != nil { + return nil, fmt.Errorf("error parsing sui metadata: %w", err) + } + + return sdkSui.NewInspector(client, signer, suiMetadata.McmsPackageID, suiMetadata.Role) + default: + return nil, fmt.Errorf("unsupported chain family %s", family) + } +} diff --git a/inspectors/inspectors_test.go b/inspectors/inspectors_test.go new file mode 100644 index 00000000..12135db0 --- /dev/null +++ b/inspectors/inspectors_test.go @@ -0,0 +1,77 @@ +package inspectors + +import ( + "testing" + + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/mcms/sdk/mocks" + mcmsTypes "github.com/smartcontractkit/mcms/types" +) + +func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + chainMetadata map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata + chainAccess *mocks.ChainAccess + setup func(access *mocks.ChainAccess) + expectErr bool + errContains string + expectedInspectorsCount int + }{ + { + name: "empty input", + chainMetadata: map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata{}, + chainAccess: mocks.NewChainAccess(t), + expectErr: false, + }, + { + name: "missing chain client", + chainMetadata: map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata{ + 1: {MCMAddress: "0xabc", StartingOpCount: 0}, + }, + chainAccess: mocks.NewChainAccess(t), + expectErr: true, + errContains: "error getting chain family: chain family not found for selector 1", + }, + { + name: "valid input", + chainMetadata: map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata{ + mcmsTypes.ChainSelector(chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector): {MCMAddress: "0xabc", StartingOpCount: 0}, + mcmsTypes.ChainSelector(chainsel.SOLANA_DEVNET.Selector): {MCMAddress: "0xabc", StartingOpCount: 0}, + }, + chainAccess: mocks.NewChainAccess(t), + expectErr: false, + setup: func(access *mocks.ChainAccess) { + access.EXPECT().EVMClient(mock.Anything).Return(nil, true) + access.EXPECT().SolanaClient(mock.Anything).Return(nil, true) + }, + expectedInspectorsCount: 2, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + if tc.chainAccess == nil { + tc.chainAccess = mocks.NewChainAccess(t) + } + if tc.expectedInspectorsCount > 0 { + tc.setup(tc.chainAccess) + } + + inspectors, err := BuildInspectors(tc.chainAccess, tc.chainMetadata, mcmsTypes.TimelockActionSchedule) + if tc.expectErr { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errContains) + } else { + require.NoError(t, err) + require.Len(t, inspectors, tc.expectedInspectorsCount) + } + }) + } +} diff --git a/inspectors/mocks/inspector_fetcher.go b/inspectors/mocks/inspector_fetcher.go new file mode 100644 index 00000000..59ceff29 --- /dev/null +++ b/inspectors/mocks/inspector_fetcher.go @@ -0,0 +1,96 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mocks + +import ( + sdk "github.com/smartcontractkit/mcms/sdk" + mock "github.com/stretchr/testify/mock" + + types "github.com/smartcontractkit/mcms/types" +) + +// InspectorFetcher is an autogenerated mock type for the InspectorFetcher type +type InspectorFetcher struct { + mock.Mock +} + +type InspectorFetcher_Expecter struct { + mock *mock.Mock +} + +func (_m *InspectorFetcher) EXPECT() *InspectorFetcher_Expecter { + return &InspectorFetcher_Expecter{mock: &_m.Mock} +} + +// FetchInspectors provides a mock function with given fields: chainMetadata, action +func (_m *InspectorFetcher) FetchInspectors(chainMetadata map[types.ChainSelector]types.ChainMetadata, action types.TimelockAction) (map[types.ChainSelector]sdk.Inspector, error) { + ret := _m.Called(chainMetadata, action) + + if len(ret) == 0 { + panic("no return value specified for FetchInspectors") + } + + var r0 map[types.ChainSelector]sdk.Inspector + var r1 error + if rf, ok := ret.Get(0).(func(map[types.ChainSelector]types.ChainMetadata, types.TimelockAction) (map[types.ChainSelector]sdk.Inspector, error)); ok { + return rf(chainMetadata, action) + } + if rf, ok := ret.Get(0).(func(map[types.ChainSelector]types.ChainMetadata, types.TimelockAction) map[types.ChainSelector]sdk.Inspector); ok { + r0 = rf(chainMetadata, action) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[types.ChainSelector]sdk.Inspector) + } + } + + if rf, ok := ret.Get(1).(func(map[types.ChainSelector]types.ChainMetadata, types.TimelockAction) error); ok { + r1 = rf(chainMetadata, action) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// InspectorFetcher_FetchInspectors_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FetchInspectors' +type InspectorFetcher_FetchInspectors_Call struct { + *mock.Call +} + +// FetchInspectors is a helper method to define mock.On call +// - chainMetadata map[types.ChainSelector]types.ChainMetadata +// - action types.TimelockAction +func (_e *InspectorFetcher_Expecter) FetchInspectors(chainMetadata interface{}, action interface{}) *InspectorFetcher_FetchInspectors_Call { + return &InspectorFetcher_FetchInspectors_Call{Call: _e.mock.On("FetchInspectors", chainMetadata, action)} +} + +func (_c *InspectorFetcher_FetchInspectors_Call) Run(run func(chainMetadata map[types.ChainSelector]types.ChainMetadata, action types.TimelockAction)) *InspectorFetcher_FetchInspectors_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(map[types.ChainSelector]types.ChainMetadata), args[1].(types.TimelockAction)) + }) + return _c +} + +func (_c *InspectorFetcher_FetchInspectors_Call) Return(_a0 map[types.ChainSelector]sdk.Inspector, _a1 error) *InspectorFetcher_FetchInspectors_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *InspectorFetcher_FetchInspectors_Call) RunAndReturn(run func(map[types.ChainSelector]types.ChainMetadata, types.TimelockAction) (map[types.ChainSelector]sdk.Inspector, error)) *InspectorFetcher_FetchInspectors_Call { + _c.Call.Return(run) + return _c +} + +// NewInspectorFetcher creates a new instance of InspectorFetcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewInspectorFetcher(t interface { + mock.TestingT + Cleanup(func()) +}) *InspectorFetcher { + mock := &InspectorFetcher{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sdk/chainclient.go b/sdk/chainclient.go new file mode 100644 index 00000000..2568bce4 --- /dev/null +++ b/sdk/chainclient.go @@ -0,0 +1,30 @@ +package sdk + +import ( + aptoslib "github.com/aptos-labs/aptos-go-sdk" + "github.com/block-vision/sui-go-sdk/sui" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + solrpc "github.com/gagliardetto/solana-go/rpc" +) + +// TODO: this interface should come from chainlink-sui when available +type SuiSigner interface { + // Sign signs the given message and returns the serialized signature. + Sign(message []byte) ([]string, error) + + // GetAddress returns the Sui address derived from the signer's public key + GetAddress() (string, error) +} + +type ContractDeployBackend interface { + bind.ContractBackend + bind.DeployBackend +} + +type ChainAccess interface { + Selectors() []uint64 + EVMClient(selector uint64) (ContractDeployBackend, bool) + SolanaClient(selector uint64) (*solrpc.Client, bool) + AptosClient(selector uint64) (aptoslib.AptosRpcClient, bool) + SuiClient(selector uint64) (sui.ISuiAPI, SuiSigner, bool) +} diff --git a/sdk/evm/configurer.go b/sdk/evm/configurer.go index e7cdc8e8..c24e17df 100644 --- a/sdk/evm/configurer.go +++ b/sdk/evm/configurer.go @@ -17,12 +17,12 @@ var _ sdk.Configurer = &Configurer{} // Configurer configures the MCM contract for EVM chains. type Configurer struct { - client ContractDeployBackend + client sdk.ContractDeployBackend auth *bind.TransactOpts } // NewConfigurer creates a new Configurer for EVM chains. -func NewConfigurer(client ContractDeployBackend, auth *bind.TransactOpts, +func NewConfigurer(client sdk.ContractDeployBackend, auth *bind.TransactOpts, ) *Configurer { return &Configurer{ client: client, diff --git a/sdk/evm/execution_error.go b/sdk/evm/execution_error.go index b7c15891..291b724a 100644 --- a/sdk/evm/execution_error.go +++ b/sdk/evm/execution_error.go @@ -18,6 +18,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" gethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/sdk/evm/bindings" ) @@ -239,7 +240,7 @@ func BuildExecutionError( txPreview *gethtypes.Transaction, opts *bind.TransactOpts, contractAddr common.Address, - client ContractDeployBackend, + client sdk.ContractDeployBackend, timelockAddr common.Address, timelockCallData []byte, ) *ExecutionError { @@ -614,7 +615,7 @@ func getUnderlyingRevertReason( timelockAddr common.Address, timelockCallData []byte, opts *bind.TransactOpts, - client ContractDeployBackend, + client sdk.ContractDeployBackend, ) (string, string) { if timelockAddr == (common.Address{}) || len(timelockCallData) == 0 || client == nil || opts == nil { return "", "" diff --git a/sdk/evm/execution_error_test.go b/sdk/evm/execution_error_test.go index f1418a33..9484800b 100644 --- a/sdk/evm/execution_error_test.go +++ b/sdk/evm/execution_error_test.go @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/sdk/evm/bindings" "github.com/smartcontractkit/mcms/sdk/evm/mocks" ) @@ -1399,7 +1400,7 @@ func TestGetUnderlyingRevertReason(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - var client ContractDeployBackend + var client sdk.ContractDeployBackend if tt.setupMock != nil { mockClient := mocks.NewContractDeployBackend(t) tt.setupMock(mockClient) diff --git a/sdk/evm/executor.go b/sdk/evm/executor.go index 2cc3e556..c9318cf6 100644 --- a/sdk/evm/executor.go +++ b/sdk/evm/executor.go @@ -12,6 +12,7 @@ import ( chain_selectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/sdk/evm/bindings" "github.com/smartcontractkit/mcms/types" ) @@ -24,7 +25,7 @@ type Executor struct { } // NewExecutor creates a new Executor for EVM chains -func NewExecutor(encoder *Encoder, client ContractDeployBackend, auth *bind.TransactOpts) *Executor { +func NewExecutor(encoder *Encoder, client sdk.ContractDeployBackend, auth *bind.TransactOpts) *Executor { return &Executor{ Encoder: encoder, Inspector: NewInspector(client), diff --git a/sdk/evm/inspector.go b/sdk/evm/inspector.go index db215a47..e253b90f 100644 --- a/sdk/evm/inspector.go +++ b/sdk/evm/inspector.go @@ -16,11 +16,11 @@ var _ sdk.Inspector = (*Inspector)(nil) // Inspector is an Inspector implementation for EVM chains, giving access to the state of the MCMS contract type Inspector struct { ConfigTransformer - client ContractDeployBackend + client sdk.ContractDeployBackend } // NewInspector creates a new Inspector for EVM chains -func NewInspector(client ContractDeployBackend) *Inspector { +func NewInspector(client sdk.ContractDeployBackend) *Inspector { return &Inspector{ ConfigTransformer: ConfigTransformer{}, client: client, diff --git a/sdk/evm/simulator.go b/sdk/evm/simulator.go index d049abce..c7ad29bc 100644 --- a/sdk/evm/simulator.go +++ b/sdk/evm/simulator.go @@ -1,15 +1,15 @@ package evm import ( + "context" "encoding/json" "errors" "math/big" - "context" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/sdk/evm/bindings" "github.com/smartcontractkit/mcms/types" ) @@ -19,7 +19,7 @@ type Simulator struct { *Inspector } -func NewSimulator(encoder *Encoder, client ContractDeployBackend) (*Simulator, error) { +func NewSimulator(encoder *Encoder, client sdk.ContractDeployBackend) (*Simulator, error) { if encoder == nil { return nil, errors.New("Simulator was created without an encoder") } diff --git a/sdk/evm/simulator_test.go b/sdk/evm/simulator_test.go index da8b5894..150b6999 100644 --- a/sdk/evm/simulator_test.go +++ b/sdk/evm/simulator_test.go @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms/internal/testutils/chaintest" + "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/sdk/evm" evm_mocks "github.com/smartcontractkit/mcms/sdk/evm/mocks" "github.com/smartcontractkit/mcms/types" @@ -30,7 +31,7 @@ func TestNewSimulator(t *testing.T) { tests := []struct { name string encoder *evm.Encoder - client evm.ContractDeployBackend + client sdk.ContractDeployBackend wantErr error wantErrMsg string }{ diff --git a/sdk/evm/timelock_executor.go b/sdk/evm/timelock_executor.go index 7bade02e..9deb69de 100644 --- a/sdk/evm/timelock_executor.go +++ b/sdk/evm/timelock_executor.go @@ -21,12 +21,12 @@ var _ sdk.TimelockExecutor = (*TimelockExecutor)(nil) // TimelockExecutor is an Executor implementation for EVM chains for accessing the RBACTimelock contract type TimelockExecutor struct { TimelockInspector - client ContractDeployBackend + client sdk.ContractDeployBackend auth *bind.TransactOpts } // NewTimelockExecutor creates a new TimelockExecutor -func NewTimelockExecutor(client ContractDeployBackend, auth *bind.TransactOpts) *TimelockExecutor { +func NewTimelockExecutor(client sdk.ContractDeployBackend, auth *bind.TransactOpts) *TimelockExecutor { return &TimelockExecutor{ TimelockInspector: *NewTimelockInspector(client), client: client, diff --git a/sdk/evm/timelock_inspector.go b/sdk/evm/timelock_inspector.go index bff04547..e3825724 100644 --- a/sdk/evm/timelock_inspector.go +++ b/sdk/evm/timelock_inspector.go @@ -16,11 +16,11 @@ var _ sdk.TimelockInspector = (*TimelockInspector)(nil) // TimelockInspector is an Inspector implementation for EVM chains for accessing the RBACTimelock contract type TimelockInspector struct { - client ContractDeployBackend + client sdk.ContractDeployBackend } // NewTimelockInspector creates a new TimelockInspector -func NewTimelockInspector(client ContractDeployBackend) *TimelockInspector { +func NewTimelockInspector(client sdk.ContractDeployBackend) *TimelockInspector { return &TimelockInspector{ client: client, } diff --git a/sdk/evm/utils.go b/sdk/evm/utils.go index f238534f..33948401 100644 --- a/sdk/evm/utils.go +++ b/sdk/evm/utils.go @@ -1,14 +1,12 @@ package evm import ( + "github.com/ethereum/go-ethereum/common" cselectors "github.com/smartcontractkit/chain-selectors" sdkerrors "github.com/smartcontractkit/mcms/sdk/errors" "github.com/smartcontractkit/mcms/types" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/mcms/sdk/evm/bindings" ) @@ -20,11 +18,6 @@ const ( SimulatedEVMChainID = 1337 ) -type ContractDeployBackend interface { - bind.ContractBackend - bind.DeployBackend -} - // transformHashes transforms a slice of common.Hash to a slice of [32]byte. func transformHashes(hashes []common.Hash) [][32]byte { bs := make([][32]byte, 0, len(hashes)) diff --git a/sdk/mocks/chain_access.go b/sdk/mocks/chain_access.go new file mode 100644 index 00000000..31a49a19 --- /dev/null +++ b/sdk/mocks/chain_access.go @@ -0,0 +1,329 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mocks + +import ( + aptos "github.com/aptos-labs/aptos-go-sdk" + mock "github.com/stretchr/testify/mock" + + rpc "github.com/gagliardetto/solana-go/rpc" + + sdk "github.com/smartcontractkit/mcms/sdk" + + sui "github.com/block-vision/sui-go-sdk/sui" +) + +// ChainAccess is an autogenerated mock type for the ChainAccess type +type ChainAccess struct { + mock.Mock +} + +type ChainAccess_Expecter struct { + mock *mock.Mock +} + +func (_m *ChainAccess) EXPECT() *ChainAccess_Expecter { + return &ChainAccess_Expecter{mock: &_m.Mock} +} + +// AptosClient provides a mock function with given fields: selector +func (_m *ChainAccess) AptosClient(selector uint64) (aptos.AptosRpcClient, bool) { + ret := _m.Called(selector) + + if len(ret) == 0 { + panic("no return value specified for AptosClient") + } + + var r0 aptos.AptosRpcClient + var r1 bool + if rf, ok := ret.Get(0).(func(uint64) (aptos.AptosRpcClient, bool)); ok { + return rf(selector) + } + if rf, ok := ret.Get(0).(func(uint64) aptos.AptosRpcClient); ok { + r0 = rf(selector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(aptos.AptosRpcClient) + } + } + + if rf, ok := ret.Get(1).(func(uint64) bool); ok { + r1 = rf(selector) + } else { + r1 = ret.Get(1).(bool) + } + + return r0, r1 +} + +// ChainAccess_AptosClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AptosClient' +type ChainAccess_AptosClient_Call struct { + *mock.Call +} + +// AptosClient is a helper method to define mock.On call +// - selector uint64 +func (_e *ChainAccess_Expecter) AptosClient(selector interface{}) *ChainAccess_AptosClient_Call { + return &ChainAccess_AptosClient_Call{Call: _e.mock.On("AptosClient", selector)} +} + +func (_c *ChainAccess_AptosClient_Call) Run(run func(selector uint64)) *ChainAccess_AptosClient_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(uint64)) + }) + return _c +} + +func (_c *ChainAccess_AptosClient_Call) Return(_a0 aptos.AptosRpcClient, _a1 bool) *ChainAccess_AptosClient_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ChainAccess_AptosClient_Call) RunAndReturn(run func(uint64) (aptos.AptosRpcClient, bool)) *ChainAccess_AptosClient_Call { + _c.Call.Return(run) + return _c +} + +// EVMClient provides a mock function with given fields: selector +func (_m *ChainAccess) EVMClient(selector uint64) (sdk.ContractDeployBackend, bool) { + ret := _m.Called(selector) + + if len(ret) == 0 { + panic("no return value specified for EVMClient") + } + + var r0 sdk.ContractDeployBackend + var r1 bool + if rf, ok := ret.Get(0).(func(uint64) (sdk.ContractDeployBackend, bool)); ok { + return rf(selector) + } + if rf, ok := ret.Get(0).(func(uint64) sdk.ContractDeployBackend); ok { + r0 = rf(selector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(sdk.ContractDeployBackend) + } + } + + if rf, ok := ret.Get(1).(func(uint64) bool); ok { + r1 = rf(selector) + } else { + r1 = ret.Get(1).(bool) + } + + return r0, r1 +} + +// ChainAccess_EVMClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EVMClient' +type ChainAccess_EVMClient_Call struct { + *mock.Call +} + +// EVMClient is a helper method to define mock.On call +// - selector uint64 +func (_e *ChainAccess_Expecter) EVMClient(selector interface{}) *ChainAccess_EVMClient_Call { + return &ChainAccess_EVMClient_Call{Call: _e.mock.On("EVMClient", selector)} +} + +func (_c *ChainAccess_EVMClient_Call) Run(run func(selector uint64)) *ChainAccess_EVMClient_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(uint64)) + }) + return _c +} + +func (_c *ChainAccess_EVMClient_Call) Return(_a0 sdk.ContractDeployBackend, _a1 bool) *ChainAccess_EVMClient_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ChainAccess_EVMClient_Call) RunAndReturn(run func(uint64) (sdk.ContractDeployBackend, bool)) *ChainAccess_EVMClient_Call { + _c.Call.Return(run) + return _c +} + +// Selectors provides a mock function with no fields +func (_m *ChainAccess) Selectors() []uint64 { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Selectors") + } + + var r0 []uint64 + if rf, ok := ret.Get(0).(func() []uint64); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]uint64) + } + } + + return r0 +} + +// ChainAccess_Selectors_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Selectors' +type ChainAccess_Selectors_Call struct { + *mock.Call +} + +// Selectors is a helper method to define mock.On call +func (_e *ChainAccess_Expecter) Selectors() *ChainAccess_Selectors_Call { + return &ChainAccess_Selectors_Call{Call: _e.mock.On("Selectors")} +} + +func (_c *ChainAccess_Selectors_Call) Run(run func()) *ChainAccess_Selectors_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ChainAccess_Selectors_Call) Return(_a0 []uint64) *ChainAccess_Selectors_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ChainAccess_Selectors_Call) RunAndReturn(run func() []uint64) *ChainAccess_Selectors_Call { + _c.Call.Return(run) + return _c +} + +// SolanaClient provides a mock function with given fields: selector +func (_m *ChainAccess) SolanaClient(selector uint64) (*rpc.Client, bool) { + ret := _m.Called(selector) + + if len(ret) == 0 { + panic("no return value specified for SolanaClient") + } + + var r0 *rpc.Client + var r1 bool + if rf, ok := ret.Get(0).(func(uint64) (*rpc.Client, bool)); ok { + return rf(selector) + } + if rf, ok := ret.Get(0).(func(uint64) *rpc.Client); ok { + r0 = rf(selector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rpc.Client) + } + } + + if rf, ok := ret.Get(1).(func(uint64) bool); ok { + r1 = rf(selector) + } else { + r1 = ret.Get(1).(bool) + } + + return r0, r1 +} + +// ChainAccess_SolanaClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SolanaClient' +type ChainAccess_SolanaClient_Call struct { + *mock.Call +} + +// SolanaClient is a helper method to define mock.On call +// - selector uint64 +func (_e *ChainAccess_Expecter) SolanaClient(selector interface{}) *ChainAccess_SolanaClient_Call { + return &ChainAccess_SolanaClient_Call{Call: _e.mock.On("SolanaClient", selector)} +} + +func (_c *ChainAccess_SolanaClient_Call) Run(run func(selector uint64)) *ChainAccess_SolanaClient_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(uint64)) + }) + return _c +} + +func (_c *ChainAccess_SolanaClient_Call) Return(_a0 *rpc.Client, _a1 bool) *ChainAccess_SolanaClient_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ChainAccess_SolanaClient_Call) RunAndReturn(run func(uint64) (*rpc.Client, bool)) *ChainAccess_SolanaClient_Call { + _c.Call.Return(run) + return _c +} + +// SuiClient provides a mock function with given fields: selector +func (_m *ChainAccess) SuiClient(selector uint64) (sui.ISuiAPI, sdk.SuiSigner, bool) { + ret := _m.Called(selector) + + if len(ret) == 0 { + panic("no return value specified for SuiClient") + } + + var r0 sui.ISuiAPI + var r1 sdk.SuiSigner + var r2 bool + if rf, ok := ret.Get(0).(func(uint64) (sui.ISuiAPI, sdk.SuiSigner, bool)); ok { + return rf(selector) + } + if rf, ok := ret.Get(0).(func(uint64) sui.ISuiAPI); ok { + r0 = rf(selector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(sui.ISuiAPI) + } + } + + if rf, ok := ret.Get(1).(func(uint64) sdk.SuiSigner); ok { + r1 = rf(selector) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(sdk.SuiSigner) + } + } + + if rf, ok := ret.Get(2).(func(uint64) bool); ok { + r2 = rf(selector) + } else { + r2 = ret.Get(2).(bool) + } + + return r0, r1, r2 +} + +// ChainAccess_SuiClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SuiClient' +type ChainAccess_SuiClient_Call struct { + *mock.Call +} + +// SuiClient is a helper method to define mock.On call +// - selector uint64 +func (_e *ChainAccess_Expecter) SuiClient(selector interface{}) *ChainAccess_SuiClient_Call { + return &ChainAccess_SuiClient_Call{Call: _e.mock.On("SuiClient", selector)} +} + +func (_c *ChainAccess_SuiClient_Call) Run(run func(selector uint64)) *ChainAccess_SuiClient_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(uint64)) + }) + return _c +} + +func (_c *ChainAccess_SuiClient_Call) Return(_a0 sui.ISuiAPI, _a1 sdk.SuiSigner, _a2 bool) *ChainAccess_SuiClient_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *ChainAccess_SuiClient_Call) RunAndReturn(run func(uint64) (sui.ISuiAPI, sdk.SuiSigner, bool)) *ChainAccess_SuiClient_Call { + _c.Call.Return(run) + return _c +} + +// NewChainAccess creates a new instance of ChainAccess. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewChainAccess(t interface { + mock.TestingT + Cleanup(func()) +}) *ChainAccess { + mock := &ChainAccess{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sdk/mocks/contract_deploy_backend.go b/sdk/mocks/contract_deploy_backend.go new file mode 100644 index 00000000..fd248d1b --- /dev/null +++ b/sdk/mocks/contract_deploy_backend.go @@ -0,0 +1,736 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + common "github.com/ethereum/go-ethereum/common" + + ethereum "github.com/ethereum/go-ethereum" + + mock "github.com/stretchr/testify/mock" + + types "github.com/ethereum/go-ethereum/core/types" +) + +// ContractDeployBackend is an autogenerated mock type for the ContractDeployBackend type +type ContractDeployBackend struct { + mock.Mock +} + +type ContractDeployBackend_Expecter struct { + mock *mock.Mock +} + +func (_m *ContractDeployBackend) EXPECT() *ContractDeployBackend_Expecter { + return &ContractDeployBackend_Expecter{mock: &_m.Mock} +} + +// CallContract provides a mock function with given fields: ctx, call, blockNumber +func (_m *ContractDeployBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { + ret := _m.Called(ctx, call, blockNumber) + + if len(ret) == 0 { + panic("no return value specified for CallContract") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg, *big.Int) ([]byte, error)); ok { + return rf(ctx, call, blockNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg, *big.Int) []byte); ok { + r0 = rf(ctx, call, blockNumber) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, ethereum.CallMsg, *big.Int) error); ok { + r1 = rf(ctx, call, blockNumber) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractDeployBackend_CallContract_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CallContract' +type ContractDeployBackend_CallContract_Call struct { + *mock.Call +} + +// CallContract is a helper method to define mock.On call +// - ctx context.Context +// - call ethereum.CallMsg +// - blockNumber *big.Int +func (_e *ContractDeployBackend_Expecter) CallContract(ctx interface{}, call interface{}, blockNumber interface{}) *ContractDeployBackend_CallContract_Call { + return &ContractDeployBackend_CallContract_Call{Call: _e.mock.On("CallContract", ctx, call, blockNumber)} +} + +func (_c *ContractDeployBackend_CallContract_Call) Run(run func(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int)) *ContractDeployBackend_CallContract_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(ethereum.CallMsg), args[2].(*big.Int)) + }) + return _c +} + +func (_c *ContractDeployBackend_CallContract_Call) Return(_a0 []byte, _a1 error) *ContractDeployBackend_CallContract_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractDeployBackend_CallContract_Call) RunAndReturn(run func(context.Context, ethereum.CallMsg, *big.Int) ([]byte, error)) *ContractDeployBackend_CallContract_Call { + _c.Call.Return(run) + return _c +} + +// CodeAt provides a mock function with given fields: ctx, contract, blockNumber +func (_m *ContractDeployBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { + ret := _m.Called(ctx, contract, blockNumber) + + if len(ret) == 0 { + panic("no return value specified for CodeAt") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) ([]byte, error)); ok { + return rf(ctx, contract, blockNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) []byte); ok { + r0 = rf(ctx, contract, blockNumber) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { + r1 = rf(ctx, contract, blockNumber) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractDeployBackend_CodeAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CodeAt' +type ContractDeployBackend_CodeAt_Call struct { + *mock.Call +} + +// CodeAt is a helper method to define mock.On call +// - ctx context.Context +// - contract common.Address +// - blockNumber *big.Int +func (_e *ContractDeployBackend_Expecter) CodeAt(ctx interface{}, contract interface{}, blockNumber interface{}) *ContractDeployBackend_CodeAt_Call { + return &ContractDeployBackend_CodeAt_Call{Call: _e.mock.On("CodeAt", ctx, contract, blockNumber)} +} + +func (_c *ContractDeployBackend_CodeAt_Call) Run(run func(ctx context.Context, contract common.Address, blockNumber *big.Int)) *ContractDeployBackend_CodeAt_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address), args[2].(*big.Int)) + }) + return _c +} + +func (_c *ContractDeployBackend_CodeAt_Call) Return(_a0 []byte, _a1 error) *ContractDeployBackend_CodeAt_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractDeployBackend_CodeAt_Call) RunAndReturn(run func(context.Context, common.Address, *big.Int) ([]byte, error)) *ContractDeployBackend_CodeAt_Call { + _c.Call.Return(run) + return _c +} + +// EstimateGas provides a mock function with given fields: ctx, call +func (_m *ContractDeployBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) { + ret := _m.Called(ctx, call) + + if len(ret) == 0 { + panic("no return value specified for EstimateGas") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg) (uint64, error)); ok { + return rf(ctx, call) + } + if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg) uint64); ok { + r0 = rf(ctx, call) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, ethereum.CallMsg) error); ok { + r1 = rf(ctx, call) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractDeployBackend_EstimateGas_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EstimateGas' +type ContractDeployBackend_EstimateGas_Call struct { + *mock.Call +} + +// EstimateGas is a helper method to define mock.On call +// - ctx context.Context +// - call ethereum.CallMsg +func (_e *ContractDeployBackend_Expecter) EstimateGas(ctx interface{}, call interface{}) *ContractDeployBackend_EstimateGas_Call { + return &ContractDeployBackend_EstimateGas_Call{Call: _e.mock.On("EstimateGas", ctx, call)} +} + +func (_c *ContractDeployBackend_EstimateGas_Call) Run(run func(ctx context.Context, call ethereum.CallMsg)) *ContractDeployBackend_EstimateGas_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(ethereum.CallMsg)) + }) + return _c +} + +func (_c *ContractDeployBackend_EstimateGas_Call) Return(_a0 uint64, _a1 error) *ContractDeployBackend_EstimateGas_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractDeployBackend_EstimateGas_Call) RunAndReturn(run func(context.Context, ethereum.CallMsg) (uint64, error)) *ContractDeployBackend_EstimateGas_Call { + _c.Call.Return(run) + return _c +} + +// FilterLogs provides a mock function with given fields: ctx, q +func (_m *ContractDeployBackend) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { + ret := _m.Called(ctx, q) + + if len(ret) == 0 { + panic("no return value specified for FilterLogs") + } + + var r0 []types.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery) ([]types.Log, error)); ok { + return rf(ctx, q) + } + if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery) []types.Log); ok { + r0 = rf(ctx, q) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]types.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, ethereum.FilterQuery) error); ok { + r1 = rf(ctx, q) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractDeployBackend_FilterLogs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterLogs' +type ContractDeployBackend_FilterLogs_Call struct { + *mock.Call +} + +// FilterLogs is a helper method to define mock.On call +// - ctx context.Context +// - q ethereum.FilterQuery +func (_e *ContractDeployBackend_Expecter) FilterLogs(ctx interface{}, q interface{}) *ContractDeployBackend_FilterLogs_Call { + return &ContractDeployBackend_FilterLogs_Call{Call: _e.mock.On("FilterLogs", ctx, q)} +} + +func (_c *ContractDeployBackend_FilterLogs_Call) Run(run func(ctx context.Context, q ethereum.FilterQuery)) *ContractDeployBackend_FilterLogs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(ethereum.FilterQuery)) + }) + return _c +} + +func (_c *ContractDeployBackend_FilterLogs_Call) Return(_a0 []types.Log, _a1 error) *ContractDeployBackend_FilterLogs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractDeployBackend_FilterLogs_Call) RunAndReturn(run func(context.Context, ethereum.FilterQuery) ([]types.Log, error)) *ContractDeployBackend_FilterLogs_Call { + _c.Call.Return(run) + return _c +} + +// HeaderByNumber provides a mock function with given fields: ctx, number +func (_m *ContractDeployBackend) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + ret := _m.Called(ctx, number) + + if len(ret) == 0 { + panic("no return value specified for HeaderByNumber") + } + + var r0 *types.Header + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*types.Header, error)); ok { + return rf(ctx, number) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *types.Header); ok { + r0 = rf(ctx, number) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Header) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { + r1 = rf(ctx, number) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractDeployBackend_HeaderByNumber_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HeaderByNumber' +type ContractDeployBackend_HeaderByNumber_Call struct { + *mock.Call +} + +// HeaderByNumber is a helper method to define mock.On call +// - ctx context.Context +// - number *big.Int +func (_e *ContractDeployBackend_Expecter) HeaderByNumber(ctx interface{}, number interface{}) *ContractDeployBackend_HeaderByNumber_Call { + return &ContractDeployBackend_HeaderByNumber_Call{Call: _e.mock.On("HeaderByNumber", ctx, number)} +} + +func (_c *ContractDeployBackend_HeaderByNumber_Call) Run(run func(ctx context.Context, number *big.Int)) *ContractDeployBackend_HeaderByNumber_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*big.Int)) + }) + return _c +} + +func (_c *ContractDeployBackend_HeaderByNumber_Call) Return(_a0 *types.Header, _a1 error) *ContractDeployBackend_HeaderByNumber_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractDeployBackend_HeaderByNumber_Call) RunAndReturn(run func(context.Context, *big.Int) (*types.Header, error)) *ContractDeployBackend_HeaderByNumber_Call { + _c.Call.Return(run) + return _c +} + +// PendingCodeAt provides a mock function with given fields: ctx, account +func (_m *ContractDeployBackend) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { + ret := _m.Called(ctx, account) + + if len(ret) == 0 { + panic("no return value specified for PendingCodeAt") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address) ([]byte, error)); ok { + return rf(ctx, account) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address) []byte); ok { + r0 = rf(ctx, account) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address) error); ok { + r1 = rf(ctx, account) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractDeployBackend_PendingCodeAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PendingCodeAt' +type ContractDeployBackend_PendingCodeAt_Call struct { + *mock.Call +} + +// PendingCodeAt is a helper method to define mock.On call +// - ctx context.Context +// - account common.Address +func (_e *ContractDeployBackend_Expecter) PendingCodeAt(ctx interface{}, account interface{}) *ContractDeployBackend_PendingCodeAt_Call { + return &ContractDeployBackend_PendingCodeAt_Call{Call: _e.mock.On("PendingCodeAt", ctx, account)} +} + +func (_c *ContractDeployBackend_PendingCodeAt_Call) Run(run func(ctx context.Context, account common.Address)) *ContractDeployBackend_PendingCodeAt_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address)) + }) + return _c +} + +func (_c *ContractDeployBackend_PendingCodeAt_Call) Return(_a0 []byte, _a1 error) *ContractDeployBackend_PendingCodeAt_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractDeployBackend_PendingCodeAt_Call) RunAndReturn(run func(context.Context, common.Address) ([]byte, error)) *ContractDeployBackend_PendingCodeAt_Call { + _c.Call.Return(run) + return _c +} + +// PendingNonceAt provides a mock function with given fields: ctx, account +func (_m *ContractDeployBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { + ret := _m.Called(ctx, account) + + if len(ret) == 0 { + panic("no return value specified for PendingNonceAt") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address) (uint64, error)); ok { + return rf(ctx, account) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address) uint64); ok { + r0 = rf(ctx, account) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address) error); ok { + r1 = rf(ctx, account) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractDeployBackend_PendingNonceAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PendingNonceAt' +type ContractDeployBackend_PendingNonceAt_Call struct { + *mock.Call +} + +// PendingNonceAt is a helper method to define mock.On call +// - ctx context.Context +// - account common.Address +func (_e *ContractDeployBackend_Expecter) PendingNonceAt(ctx interface{}, account interface{}) *ContractDeployBackend_PendingNonceAt_Call { + return &ContractDeployBackend_PendingNonceAt_Call{Call: _e.mock.On("PendingNonceAt", ctx, account)} +} + +func (_c *ContractDeployBackend_PendingNonceAt_Call) Run(run func(ctx context.Context, account common.Address)) *ContractDeployBackend_PendingNonceAt_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address)) + }) + return _c +} + +func (_c *ContractDeployBackend_PendingNonceAt_Call) Return(_a0 uint64, _a1 error) *ContractDeployBackend_PendingNonceAt_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractDeployBackend_PendingNonceAt_Call) RunAndReturn(run func(context.Context, common.Address) (uint64, error)) *ContractDeployBackend_PendingNonceAt_Call { + _c.Call.Return(run) + return _c +} + +// SendTransaction provides a mock function with given fields: ctx, tx +func (_m *ContractDeployBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error { + ret := _m.Called(ctx, tx) + + if len(ret) == 0 { + panic("no return value specified for SendTransaction") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction) error); ok { + r0 = rf(ctx, tx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ContractDeployBackend_SendTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendTransaction' +type ContractDeployBackend_SendTransaction_Call struct { + *mock.Call +} + +// SendTransaction is a helper method to define mock.On call +// - ctx context.Context +// - tx *types.Transaction +func (_e *ContractDeployBackend_Expecter) SendTransaction(ctx interface{}, tx interface{}) *ContractDeployBackend_SendTransaction_Call { + return &ContractDeployBackend_SendTransaction_Call{Call: _e.mock.On("SendTransaction", ctx, tx)} +} + +func (_c *ContractDeployBackend_SendTransaction_Call) Run(run func(ctx context.Context, tx *types.Transaction)) *ContractDeployBackend_SendTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*types.Transaction)) + }) + return _c +} + +func (_c *ContractDeployBackend_SendTransaction_Call) Return(_a0 error) *ContractDeployBackend_SendTransaction_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ContractDeployBackend_SendTransaction_Call) RunAndReturn(run func(context.Context, *types.Transaction) error) *ContractDeployBackend_SendTransaction_Call { + _c.Call.Return(run) + return _c +} + +// SubscribeFilterLogs provides a mock function with given fields: ctx, q, ch +func (_m *ContractDeployBackend) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { + ret := _m.Called(ctx, q, ch) + + if len(ret) == 0 { + panic("no return value specified for SubscribeFilterLogs") + } + + var r0 ethereum.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery, chan<- types.Log) (ethereum.Subscription, error)); ok { + return rf(ctx, q, ch) + } + if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery, chan<- types.Log) ethereum.Subscription); ok { + r0 = rf(ctx, q, ch) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(ethereum.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, ethereum.FilterQuery, chan<- types.Log) error); ok { + r1 = rf(ctx, q, ch) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractDeployBackend_SubscribeFilterLogs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeFilterLogs' +type ContractDeployBackend_SubscribeFilterLogs_Call struct { + *mock.Call +} + +// SubscribeFilterLogs is a helper method to define mock.On call +// - ctx context.Context +// - q ethereum.FilterQuery +// - ch chan<- types.Log +func (_e *ContractDeployBackend_Expecter) SubscribeFilterLogs(ctx interface{}, q interface{}, ch interface{}) *ContractDeployBackend_SubscribeFilterLogs_Call { + return &ContractDeployBackend_SubscribeFilterLogs_Call{Call: _e.mock.On("SubscribeFilterLogs", ctx, q, ch)} +} + +func (_c *ContractDeployBackend_SubscribeFilterLogs_Call) Run(run func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log)) *ContractDeployBackend_SubscribeFilterLogs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(ethereum.FilterQuery), args[2].(chan<- types.Log)) + }) + return _c +} + +func (_c *ContractDeployBackend_SubscribeFilterLogs_Call) Return(_a0 ethereum.Subscription, _a1 error) *ContractDeployBackend_SubscribeFilterLogs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractDeployBackend_SubscribeFilterLogs_Call) RunAndReturn(run func(context.Context, ethereum.FilterQuery, chan<- types.Log) (ethereum.Subscription, error)) *ContractDeployBackend_SubscribeFilterLogs_Call { + _c.Call.Return(run) + return _c +} + +// SuggestGasPrice provides a mock function with given fields: ctx +func (_m *ContractDeployBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for SuggestGasPrice") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractDeployBackend_SuggestGasPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SuggestGasPrice' +type ContractDeployBackend_SuggestGasPrice_Call struct { + *mock.Call +} + +// SuggestGasPrice is a helper method to define mock.On call +// - ctx context.Context +func (_e *ContractDeployBackend_Expecter) SuggestGasPrice(ctx interface{}) *ContractDeployBackend_SuggestGasPrice_Call { + return &ContractDeployBackend_SuggestGasPrice_Call{Call: _e.mock.On("SuggestGasPrice", ctx)} +} + +func (_c *ContractDeployBackend_SuggestGasPrice_Call) Run(run func(ctx context.Context)) *ContractDeployBackend_SuggestGasPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *ContractDeployBackend_SuggestGasPrice_Call) Return(_a0 *big.Int, _a1 error) *ContractDeployBackend_SuggestGasPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractDeployBackend_SuggestGasPrice_Call) RunAndReturn(run func(context.Context) (*big.Int, error)) *ContractDeployBackend_SuggestGasPrice_Call { + _c.Call.Return(run) + return _c +} + +// SuggestGasTipCap provides a mock function with given fields: ctx +func (_m *ContractDeployBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for SuggestGasTipCap") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractDeployBackend_SuggestGasTipCap_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SuggestGasTipCap' +type ContractDeployBackend_SuggestGasTipCap_Call struct { + *mock.Call +} + +// SuggestGasTipCap is a helper method to define mock.On call +// - ctx context.Context +func (_e *ContractDeployBackend_Expecter) SuggestGasTipCap(ctx interface{}) *ContractDeployBackend_SuggestGasTipCap_Call { + return &ContractDeployBackend_SuggestGasTipCap_Call{Call: _e.mock.On("SuggestGasTipCap", ctx)} +} + +func (_c *ContractDeployBackend_SuggestGasTipCap_Call) Run(run func(ctx context.Context)) *ContractDeployBackend_SuggestGasTipCap_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *ContractDeployBackend_SuggestGasTipCap_Call) Return(_a0 *big.Int, _a1 error) *ContractDeployBackend_SuggestGasTipCap_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractDeployBackend_SuggestGasTipCap_Call) RunAndReturn(run func(context.Context) (*big.Int, error)) *ContractDeployBackend_SuggestGasTipCap_Call { + _c.Call.Return(run) + return _c +} + +// TransactionReceipt provides a mock function with given fields: ctx, txHash +func (_m *ContractDeployBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + ret := _m.Called(ctx, txHash) + + if len(ret) == 0 { + panic("no return value specified for TransactionReceipt") + } + + var r0 *types.Receipt + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.Receipt, error)); ok { + return rf(ctx, txHash) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *types.Receipt); ok { + r0 = rf(ctx, txHash) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Receipt) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { + r1 = rf(ctx, txHash) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ContractDeployBackend_TransactionReceipt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransactionReceipt' +type ContractDeployBackend_TransactionReceipt_Call struct { + *mock.Call +} + +// TransactionReceipt is a helper method to define mock.On call +// - ctx context.Context +// - txHash common.Hash +func (_e *ContractDeployBackend_Expecter) TransactionReceipt(ctx interface{}, txHash interface{}) *ContractDeployBackend_TransactionReceipt_Call { + return &ContractDeployBackend_TransactionReceipt_Call{Call: _e.mock.On("TransactionReceipt", ctx, txHash)} +} + +func (_c *ContractDeployBackend_TransactionReceipt_Call) Run(run func(ctx context.Context, txHash common.Hash)) *ContractDeployBackend_TransactionReceipt_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Hash)) + }) + return _c +} + +func (_c *ContractDeployBackend_TransactionReceipt_Call) Return(_a0 *types.Receipt, _a1 error) *ContractDeployBackend_TransactionReceipt_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ContractDeployBackend_TransactionReceipt_Call) RunAndReturn(run func(context.Context, common.Hash) (*types.Receipt, error)) *ContractDeployBackend_TransactionReceipt_Call { + _c.Call.Return(run) + return _c +} + +// NewContractDeployBackend creates a new instance of ContractDeployBackend. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewContractDeployBackend(t interface { + mock.TestingT + Cleanup(func()) +}) *ContractDeployBackend { + mock := &ContractDeployBackend{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sdk/mocks/sui_signer.go b/sdk/mocks/sui_signer.go new file mode 100644 index 00000000..52c10a36 --- /dev/null +++ b/sdk/mocks/sui_signer.go @@ -0,0 +1,145 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// SuiSigner is an autogenerated mock type for the SuiSigner type +type SuiSigner struct { + mock.Mock +} + +type SuiSigner_Expecter struct { + mock *mock.Mock +} + +func (_m *SuiSigner) EXPECT() *SuiSigner_Expecter { + return &SuiSigner_Expecter{mock: &_m.Mock} +} + +// GetAddress provides a mock function with no fields +func (_m *SuiSigner) GetAddress() (string, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetAddress") + } + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func() (string, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SuiSigner_GetAddress_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAddress' +type SuiSigner_GetAddress_Call struct { + *mock.Call +} + +// GetAddress is a helper method to define mock.On call +func (_e *SuiSigner_Expecter) GetAddress() *SuiSigner_GetAddress_Call { + return &SuiSigner_GetAddress_Call{Call: _e.mock.On("GetAddress")} +} + +func (_c *SuiSigner_GetAddress_Call) Run(run func()) *SuiSigner_GetAddress_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *SuiSigner_GetAddress_Call) Return(_a0 string, _a1 error) *SuiSigner_GetAddress_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SuiSigner_GetAddress_Call) RunAndReturn(run func() (string, error)) *SuiSigner_GetAddress_Call { + _c.Call.Return(run) + return _c +} + +// Sign provides a mock function with given fields: message +func (_m *SuiSigner) Sign(message []byte) ([]string, error) { + ret := _m.Called(message) + + if len(ret) == 0 { + panic("no return value specified for Sign") + } + + var r0 []string + var r1 error + if rf, ok := ret.Get(0).(func([]byte) ([]string, error)); ok { + return rf(message) + } + if rf, ok := ret.Get(0).(func([]byte) []string); ok { + r0 = rf(message) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + if rf, ok := ret.Get(1).(func([]byte) error); ok { + r1 = rf(message) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SuiSigner_Sign_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Sign' +type SuiSigner_Sign_Call struct { + *mock.Call +} + +// Sign is a helper method to define mock.On call +// - message []byte +func (_e *SuiSigner_Expecter) Sign(message interface{}) *SuiSigner_Sign_Call { + return &SuiSigner_Sign_Call{Call: _e.mock.On("Sign", message)} +} + +func (_c *SuiSigner_Sign_Call) Run(run func(message []byte)) *SuiSigner_Sign_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]byte)) + }) + return _c +} + +func (_c *SuiSigner_Sign_Call) Return(_a0 []string, _a1 error) *SuiSigner_Sign_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SuiSigner_Sign_Call) RunAndReturn(run func([]byte) ([]string, error)) *SuiSigner_Sign_Call { + _c.Call.Return(run) + return _c +} + +// NewSuiSigner creates a new instance of SuiSigner. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSuiSigner(t interface { + mock.TestingT + Cleanup(func()) +}) *SuiSigner { + mock := &SuiSigner{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sdk/sui/mocks/mcms/imcms.go b/sdk/sui/mocks/mcms/imcms.go index 81c3e3d5..55ff6629 100644 --- a/sdk/sui/mocks/mcms/imcms.go +++ b/sdk/sui/mocks/mcms/imcms.go @@ -664,67 +664,6 @@ func (_c *IMcms_DevInspect_Call) RunAndReturn(run func() module_mcms.IMcmsDevIns return _c } -// DispatchTimelockBlockFunction provides a mock function with given fields: ctx, opts, timelock, timelockCallbackParams -func (_m *IMcms) DispatchTimelockBlockFunction(ctx context.Context, opts *bind.CallOpts, timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams) (*models.SuiTransactionBlockResponse, error) { - ret := _m.Called(ctx, opts, timelock, timelockCallbackParams) - - if len(ret) == 0 { - panic("no return value specified for DispatchTimelockBlockFunction") - } - - var r0 *models.SuiTransactionBlockResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) (*models.SuiTransactionBlockResponse, error)); ok { - return rf(ctx, opts, timelock, timelockCallbackParams) - } - if rf, ok := ret.Get(0).(func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) *models.SuiTransactionBlockResponse); ok { - r0 = rf(ctx, opts, timelock, timelockCallbackParams) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*models.SuiTransactionBlockResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) error); ok { - r1 = rf(ctx, opts, timelock, timelockCallbackParams) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// IMcms_DispatchTimelockBlockFunction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DispatchTimelockBlockFunction' -type IMcms_DispatchTimelockBlockFunction_Call struct { - *mock.Call -} - -// DispatchTimelockBlockFunction is a helper method to define mock.On call -// - ctx context.Context -// - opts *bind.CallOpts -// - timelock bind.Object -// - timelockCallbackParams module_mcms.TimelockCallbackParams -func (_e *IMcms_Expecter) DispatchTimelockBlockFunction(ctx interface{}, opts interface{}, timelock interface{}, timelockCallbackParams interface{}) *IMcms_DispatchTimelockBlockFunction_Call { - return &IMcms_DispatchTimelockBlockFunction_Call{Call: _e.mock.On("DispatchTimelockBlockFunction", ctx, opts, timelock, timelockCallbackParams)} -} - -func (_c *IMcms_DispatchTimelockBlockFunction_Call) Run(run func(ctx context.Context, opts *bind.CallOpts, timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams)) *IMcms_DispatchTimelockBlockFunction_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*bind.CallOpts), args[2].(bind.Object), args[3].(module_mcms.TimelockCallbackParams)) - }) - return _c -} - -func (_c *IMcms_DispatchTimelockBlockFunction_Call) Return(_a0 *models.SuiTransactionBlockResponse, _a1 error) *IMcms_DispatchTimelockBlockFunction_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *IMcms_DispatchTimelockBlockFunction_Call) RunAndReturn(run func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) (*models.SuiTransactionBlockResponse, error)) *IMcms_DispatchTimelockBlockFunction_Call { - _c.Call.Return(run) - return _c -} - // DispatchTimelockBypasserExecuteBatch provides a mock function with given fields: ctx, opts, timelockCallbackParams func (_m *IMcms) DispatchTimelockBypasserExecuteBatch(ctx context.Context, opts *bind.CallOpts, timelockCallbackParams module_mcms.TimelockCallbackParams) (*models.SuiTransactionBlockResponse, error) { ret := _m.Called(ctx, opts, timelockCallbackParams) @@ -971,128 +910,6 @@ func (_c *IMcms_DispatchTimelockScheduleBatch_Call) RunAndReturn(run func(contex return _c } -// DispatchTimelockUnblockFunction provides a mock function with given fields: ctx, opts, timelock, timelockCallbackParams -func (_m *IMcms) DispatchTimelockUnblockFunction(ctx context.Context, opts *bind.CallOpts, timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams) (*models.SuiTransactionBlockResponse, error) { - ret := _m.Called(ctx, opts, timelock, timelockCallbackParams) - - if len(ret) == 0 { - panic("no return value specified for DispatchTimelockUnblockFunction") - } - - var r0 *models.SuiTransactionBlockResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) (*models.SuiTransactionBlockResponse, error)); ok { - return rf(ctx, opts, timelock, timelockCallbackParams) - } - if rf, ok := ret.Get(0).(func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) *models.SuiTransactionBlockResponse); ok { - r0 = rf(ctx, opts, timelock, timelockCallbackParams) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*models.SuiTransactionBlockResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) error); ok { - r1 = rf(ctx, opts, timelock, timelockCallbackParams) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// IMcms_DispatchTimelockUnblockFunction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DispatchTimelockUnblockFunction' -type IMcms_DispatchTimelockUnblockFunction_Call struct { - *mock.Call -} - -// DispatchTimelockUnblockFunction is a helper method to define mock.On call -// - ctx context.Context -// - opts *bind.CallOpts -// - timelock bind.Object -// - timelockCallbackParams module_mcms.TimelockCallbackParams -func (_e *IMcms_Expecter) DispatchTimelockUnblockFunction(ctx interface{}, opts interface{}, timelock interface{}, timelockCallbackParams interface{}) *IMcms_DispatchTimelockUnblockFunction_Call { - return &IMcms_DispatchTimelockUnblockFunction_Call{Call: _e.mock.On("DispatchTimelockUnblockFunction", ctx, opts, timelock, timelockCallbackParams)} -} - -func (_c *IMcms_DispatchTimelockUnblockFunction_Call) Run(run func(ctx context.Context, opts *bind.CallOpts, timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams)) *IMcms_DispatchTimelockUnblockFunction_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*bind.CallOpts), args[2].(bind.Object), args[3].(module_mcms.TimelockCallbackParams)) - }) - return _c -} - -func (_c *IMcms_DispatchTimelockUnblockFunction_Call) Return(_a0 *models.SuiTransactionBlockResponse, _a1 error) *IMcms_DispatchTimelockUnblockFunction_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *IMcms_DispatchTimelockUnblockFunction_Call) RunAndReturn(run func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) (*models.SuiTransactionBlockResponse, error)) *IMcms_DispatchTimelockUnblockFunction_Call { - _c.Call.Return(run) - return _c -} - -// DispatchTimelockUpdateMinDelay provides a mock function with given fields: ctx, opts, timelock, timelockCallbackParams -func (_m *IMcms) DispatchTimelockUpdateMinDelay(ctx context.Context, opts *bind.CallOpts, timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams) (*models.SuiTransactionBlockResponse, error) { - ret := _m.Called(ctx, opts, timelock, timelockCallbackParams) - - if len(ret) == 0 { - panic("no return value specified for DispatchTimelockUpdateMinDelay") - } - - var r0 *models.SuiTransactionBlockResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) (*models.SuiTransactionBlockResponse, error)); ok { - return rf(ctx, opts, timelock, timelockCallbackParams) - } - if rf, ok := ret.Get(0).(func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) *models.SuiTransactionBlockResponse); ok { - r0 = rf(ctx, opts, timelock, timelockCallbackParams) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*models.SuiTransactionBlockResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) error); ok { - r1 = rf(ctx, opts, timelock, timelockCallbackParams) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// IMcms_DispatchTimelockUpdateMinDelay_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DispatchTimelockUpdateMinDelay' -type IMcms_DispatchTimelockUpdateMinDelay_Call struct { - *mock.Call -} - -// DispatchTimelockUpdateMinDelay is a helper method to define mock.On call -// - ctx context.Context -// - opts *bind.CallOpts -// - timelock bind.Object -// - timelockCallbackParams module_mcms.TimelockCallbackParams -func (_e *IMcms_Expecter) DispatchTimelockUpdateMinDelay(ctx interface{}, opts interface{}, timelock interface{}, timelockCallbackParams interface{}) *IMcms_DispatchTimelockUpdateMinDelay_Call { - return &IMcms_DispatchTimelockUpdateMinDelay_Call{Call: _e.mock.On("DispatchTimelockUpdateMinDelay", ctx, opts, timelock, timelockCallbackParams)} -} - -func (_c *IMcms_DispatchTimelockUpdateMinDelay_Call) Run(run func(ctx context.Context, opts *bind.CallOpts, timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams)) *IMcms_DispatchTimelockUpdateMinDelay_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*bind.CallOpts), args[2].(bind.Object), args[3].(module_mcms.TimelockCallbackParams)) - }) - return _c -} - -func (_c *IMcms_DispatchTimelockUpdateMinDelay_Call) Return(_a0 *models.SuiTransactionBlockResponse, _a1 error) *IMcms_DispatchTimelockUpdateMinDelay_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *IMcms_DispatchTimelockUpdateMinDelay_Call) RunAndReturn(run func(context.Context, *bind.CallOpts, bind.Object, module_mcms.TimelockCallbackParams) (*models.SuiTransactionBlockResponse, error)) *IMcms_DispatchTimelockUpdateMinDelay_Call { - _c.Call.Return(run) - return _c -} - // Encoder provides a mock function with no fields func (_m *IMcms) Encoder() module_mcms.McmsEncoder { ret := _m.Called() diff --git a/sdk/sui/mocks/mcms/mcmsencoder.go b/sdk/sui/mocks/mcms/mcmsencoder.go index 811711ce..dcf2be7e 100644 --- a/sdk/sui/mocks/mcms/mcmsencoder.go +++ b/sdk/sui/mocks/mcms/mcmsencoder.go @@ -1151,132 +1151,6 @@ func (_c *McmsEncoder_DataWithArgs_Call) RunAndReturn(run func(...interface{}) ( return _c } -// DispatchTimelockBlockFunction provides a mock function with given fields: timelock, timelockCallbackParams -func (_m *McmsEncoder) DispatchTimelockBlockFunction(timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams) (*bind.EncodedCall, error) { - ret := _m.Called(timelock, timelockCallbackParams) - - if len(ret) == 0 { - panic("no return value specified for DispatchTimelockBlockFunction") - } - - var r0 *bind.EncodedCall - var r1 error - if rf, ok := ret.Get(0).(func(bind.Object, module_mcms.TimelockCallbackParams) (*bind.EncodedCall, error)); ok { - return rf(timelock, timelockCallbackParams) - } - if rf, ok := ret.Get(0).(func(bind.Object, module_mcms.TimelockCallbackParams) *bind.EncodedCall); ok { - r0 = rf(timelock, timelockCallbackParams) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*bind.EncodedCall) - } - } - - if rf, ok := ret.Get(1).(func(bind.Object, module_mcms.TimelockCallbackParams) error); ok { - r1 = rf(timelock, timelockCallbackParams) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// McmsEncoder_DispatchTimelockBlockFunction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DispatchTimelockBlockFunction' -type McmsEncoder_DispatchTimelockBlockFunction_Call struct { - *mock.Call -} - -// DispatchTimelockBlockFunction is a helper method to define mock.On call -// - timelock bind.Object -// - timelockCallbackParams module_mcms.TimelockCallbackParams -func (_e *McmsEncoder_Expecter) DispatchTimelockBlockFunction(timelock interface{}, timelockCallbackParams interface{}) *McmsEncoder_DispatchTimelockBlockFunction_Call { - return &McmsEncoder_DispatchTimelockBlockFunction_Call{Call: _e.mock.On("DispatchTimelockBlockFunction", timelock, timelockCallbackParams)} -} - -func (_c *McmsEncoder_DispatchTimelockBlockFunction_Call) Run(run func(timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams)) *McmsEncoder_DispatchTimelockBlockFunction_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(bind.Object), args[1].(module_mcms.TimelockCallbackParams)) - }) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockBlockFunction_Call) Return(_a0 *bind.EncodedCall, _a1 error) *McmsEncoder_DispatchTimelockBlockFunction_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockBlockFunction_Call) RunAndReturn(run func(bind.Object, module_mcms.TimelockCallbackParams) (*bind.EncodedCall, error)) *McmsEncoder_DispatchTimelockBlockFunction_Call { - _c.Call.Return(run) - return _c -} - -// DispatchTimelockBlockFunctionWithArgs provides a mock function with given fields: args -func (_m *McmsEncoder) DispatchTimelockBlockFunctionWithArgs(args ...interface{}) (*bind.EncodedCall, error) { - var _ca []interface{} - _ca = append(_ca, args...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for DispatchTimelockBlockFunctionWithArgs") - } - - var r0 *bind.EncodedCall - var r1 error - if rf, ok := ret.Get(0).(func(...interface{}) (*bind.EncodedCall, error)); ok { - return rf(args...) - } - if rf, ok := ret.Get(0).(func(...interface{}) *bind.EncodedCall); ok { - r0 = rf(args...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*bind.EncodedCall) - } - } - - if rf, ok := ret.Get(1).(func(...interface{}) error); ok { - r1 = rf(args...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// McmsEncoder_DispatchTimelockBlockFunctionWithArgs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DispatchTimelockBlockFunctionWithArgs' -type McmsEncoder_DispatchTimelockBlockFunctionWithArgs_Call struct { - *mock.Call -} - -// DispatchTimelockBlockFunctionWithArgs is a helper method to define mock.On call -// - args ...interface{} -func (_e *McmsEncoder_Expecter) DispatchTimelockBlockFunctionWithArgs(args ...interface{}) *McmsEncoder_DispatchTimelockBlockFunctionWithArgs_Call { - return &McmsEncoder_DispatchTimelockBlockFunctionWithArgs_Call{Call: _e.mock.On("DispatchTimelockBlockFunctionWithArgs", - append([]interface{}{}, args...)...)} -} - -func (_c *McmsEncoder_DispatchTimelockBlockFunctionWithArgs_Call) Run(run func(args ...interface{})) *McmsEncoder_DispatchTimelockBlockFunctionWithArgs_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]interface{}, len(args)-0) - for i, a := range args[0:] { - if a != nil { - variadicArgs[i] = a.(interface{}) - } - } - run(variadicArgs...) - }) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockBlockFunctionWithArgs_Call) Return(_a0 *bind.EncodedCall, _a1 error) *McmsEncoder_DispatchTimelockBlockFunctionWithArgs_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockBlockFunctionWithArgs_Call) RunAndReturn(run func(...interface{}) (*bind.EncodedCall, error)) *McmsEncoder_DispatchTimelockBlockFunctionWithArgs_Call { - _c.Call.Return(run) - return _c -} - // DispatchTimelockBypasserExecuteBatch provides a mock function with given fields: timelockCallbackParams func (_m *McmsEncoder) DispatchTimelockBypasserExecuteBatch(timelockCallbackParams module_mcms.TimelockCallbackParams) (*bind.EncodedCall, error) { ret := _m.Called(timelockCallbackParams) @@ -1783,258 +1657,6 @@ func (_c *McmsEncoder_DispatchTimelockScheduleBatchWithArgs_Call) RunAndReturn(r return _c } -// DispatchTimelockUnblockFunction provides a mock function with given fields: timelock, timelockCallbackParams -func (_m *McmsEncoder) DispatchTimelockUnblockFunction(timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams) (*bind.EncodedCall, error) { - ret := _m.Called(timelock, timelockCallbackParams) - - if len(ret) == 0 { - panic("no return value specified for DispatchTimelockUnblockFunction") - } - - var r0 *bind.EncodedCall - var r1 error - if rf, ok := ret.Get(0).(func(bind.Object, module_mcms.TimelockCallbackParams) (*bind.EncodedCall, error)); ok { - return rf(timelock, timelockCallbackParams) - } - if rf, ok := ret.Get(0).(func(bind.Object, module_mcms.TimelockCallbackParams) *bind.EncodedCall); ok { - r0 = rf(timelock, timelockCallbackParams) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*bind.EncodedCall) - } - } - - if rf, ok := ret.Get(1).(func(bind.Object, module_mcms.TimelockCallbackParams) error); ok { - r1 = rf(timelock, timelockCallbackParams) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// McmsEncoder_DispatchTimelockUnblockFunction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DispatchTimelockUnblockFunction' -type McmsEncoder_DispatchTimelockUnblockFunction_Call struct { - *mock.Call -} - -// DispatchTimelockUnblockFunction is a helper method to define mock.On call -// - timelock bind.Object -// - timelockCallbackParams module_mcms.TimelockCallbackParams -func (_e *McmsEncoder_Expecter) DispatchTimelockUnblockFunction(timelock interface{}, timelockCallbackParams interface{}) *McmsEncoder_DispatchTimelockUnblockFunction_Call { - return &McmsEncoder_DispatchTimelockUnblockFunction_Call{Call: _e.mock.On("DispatchTimelockUnblockFunction", timelock, timelockCallbackParams)} -} - -func (_c *McmsEncoder_DispatchTimelockUnblockFunction_Call) Run(run func(timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams)) *McmsEncoder_DispatchTimelockUnblockFunction_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(bind.Object), args[1].(module_mcms.TimelockCallbackParams)) - }) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockUnblockFunction_Call) Return(_a0 *bind.EncodedCall, _a1 error) *McmsEncoder_DispatchTimelockUnblockFunction_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockUnblockFunction_Call) RunAndReturn(run func(bind.Object, module_mcms.TimelockCallbackParams) (*bind.EncodedCall, error)) *McmsEncoder_DispatchTimelockUnblockFunction_Call { - _c.Call.Return(run) - return _c -} - -// DispatchTimelockUnblockFunctionWithArgs provides a mock function with given fields: args -func (_m *McmsEncoder) DispatchTimelockUnblockFunctionWithArgs(args ...interface{}) (*bind.EncodedCall, error) { - var _ca []interface{} - _ca = append(_ca, args...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for DispatchTimelockUnblockFunctionWithArgs") - } - - var r0 *bind.EncodedCall - var r1 error - if rf, ok := ret.Get(0).(func(...interface{}) (*bind.EncodedCall, error)); ok { - return rf(args...) - } - if rf, ok := ret.Get(0).(func(...interface{}) *bind.EncodedCall); ok { - r0 = rf(args...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*bind.EncodedCall) - } - } - - if rf, ok := ret.Get(1).(func(...interface{}) error); ok { - r1 = rf(args...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// McmsEncoder_DispatchTimelockUnblockFunctionWithArgs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DispatchTimelockUnblockFunctionWithArgs' -type McmsEncoder_DispatchTimelockUnblockFunctionWithArgs_Call struct { - *mock.Call -} - -// DispatchTimelockUnblockFunctionWithArgs is a helper method to define mock.On call -// - args ...interface{} -func (_e *McmsEncoder_Expecter) DispatchTimelockUnblockFunctionWithArgs(args ...interface{}) *McmsEncoder_DispatchTimelockUnblockFunctionWithArgs_Call { - return &McmsEncoder_DispatchTimelockUnblockFunctionWithArgs_Call{Call: _e.mock.On("DispatchTimelockUnblockFunctionWithArgs", - append([]interface{}{}, args...)...)} -} - -func (_c *McmsEncoder_DispatchTimelockUnblockFunctionWithArgs_Call) Run(run func(args ...interface{})) *McmsEncoder_DispatchTimelockUnblockFunctionWithArgs_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]interface{}, len(args)-0) - for i, a := range args[0:] { - if a != nil { - variadicArgs[i] = a.(interface{}) - } - } - run(variadicArgs...) - }) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockUnblockFunctionWithArgs_Call) Return(_a0 *bind.EncodedCall, _a1 error) *McmsEncoder_DispatchTimelockUnblockFunctionWithArgs_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockUnblockFunctionWithArgs_Call) RunAndReturn(run func(...interface{}) (*bind.EncodedCall, error)) *McmsEncoder_DispatchTimelockUnblockFunctionWithArgs_Call { - _c.Call.Return(run) - return _c -} - -// DispatchTimelockUpdateMinDelay provides a mock function with given fields: timelock, timelockCallbackParams -func (_m *McmsEncoder) DispatchTimelockUpdateMinDelay(timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams) (*bind.EncodedCall, error) { - ret := _m.Called(timelock, timelockCallbackParams) - - if len(ret) == 0 { - panic("no return value specified for DispatchTimelockUpdateMinDelay") - } - - var r0 *bind.EncodedCall - var r1 error - if rf, ok := ret.Get(0).(func(bind.Object, module_mcms.TimelockCallbackParams) (*bind.EncodedCall, error)); ok { - return rf(timelock, timelockCallbackParams) - } - if rf, ok := ret.Get(0).(func(bind.Object, module_mcms.TimelockCallbackParams) *bind.EncodedCall); ok { - r0 = rf(timelock, timelockCallbackParams) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*bind.EncodedCall) - } - } - - if rf, ok := ret.Get(1).(func(bind.Object, module_mcms.TimelockCallbackParams) error); ok { - r1 = rf(timelock, timelockCallbackParams) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// McmsEncoder_DispatchTimelockUpdateMinDelay_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DispatchTimelockUpdateMinDelay' -type McmsEncoder_DispatchTimelockUpdateMinDelay_Call struct { - *mock.Call -} - -// DispatchTimelockUpdateMinDelay is a helper method to define mock.On call -// - timelock bind.Object -// - timelockCallbackParams module_mcms.TimelockCallbackParams -func (_e *McmsEncoder_Expecter) DispatchTimelockUpdateMinDelay(timelock interface{}, timelockCallbackParams interface{}) *McmsEncoder_DispatchTimelockUpdateMinDelay_Call { - return &McmsEncoder_DispatchTimelockUpdateMinDelay_Call{Call: _e.mock.On("DispatchTimelockUpdateMinDelay", timelock, timelockCallbackParams)} -} - -func (_c *McmsEncoder_DispatchTimelockUpdateMinDelay_Call) Run(run func(timelock bind.Object, timelockCallbackParams module_mcms.TimelockCallbackParams)) *McmsEncoder_DispatchTimelockUpdateMinDelay_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(bind.Object), args[1].(module_mcms.TimelockCallbackParams)) - }) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockUpdateMinDelay_Call) Return(_a0 *bind.EncodedCall, _a1 error) *McmsEncoder_DispatchTimelockUpdateMinDelay_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockUpdateMinDelay_Call) RunAndReturn(run func(bind.Object, module_mcms.TimelockCallbackParams) (*bind.EncodedCall, error)) *McmsEncoder_DispatchTimelockUpdateMinDelay_Call { - _c.Call.Return(run) - return _c -} - -// DispatchTimelockUpdateMinDelayWithArgs provides a mock function with given fields: args -func (_m *McmsEncoder) DispatchTimelockUpdateMinDelayWithArgs(args ...interface{}) (*bind.EncodedCall, error) { - var _ca []interface{} - _ca = append(_ca, args...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for DispatchTimelockUpdateMinDelayWithArgs") - } - - var r0 *bind.EncodedCall - var r1 error - if rf, ok := ret.Get(0).(func(...interface{}) (*bind.EncodedCall, error)); ok { - return rf(args...) - } - if rf, ok := ret.Get(0).(func(...interface{}) *bind.EncodedCall); ok { - r0 = rf(args...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*bind.EncodedCall) - } - } - - if rf, ok := ret.Get(1).(func(...interface{}) error); ok { - r1 = rf(args...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// McmsEncoder_DispatchTimelockUpdateMinDelayWithArgs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DispatchTimelockUpdateMinDelayWithArgs' -type McmsEncoder_DispatchTimelockUpdateMinDelayWithArgs_Call struct { - *mock.Call -} - -// DispatchTimelockUpdateMinDelayWithArgs is a helper method to define mock.On call -// - args ...interface{} -func (_e *McmsEncoder_Expecter) DispatchTimelockUpdateMinDelayWithArgs(args ...interface{}) *McmsEncoder_DispatchTimelockUpdateMinDelayWithArgs_Call { - return &McmsEncoder_DispatchTimelockUpdateMinDelayWithArgs_Call{Call: _e.mock.On("DispatchTimelockUpdateMinDelayWithArgs", - append([]interface{}{}, args...)...)} -} - -func (_c *McmsEncoder_DispatchTimelockUpdateMinDelayWithArgs_Call) Run(run func(args ...interface{})) *McmsEncoder_DispatchTimelockUpdateMinDelayWithArgs_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]interface{}, len(args)-0) - for i, a := range args[0:] { - if a != nil { - variadicArgs[i] = a.(interface{}) - } - } - run(variadicArgs...) - }) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockUpdateMinDelayWithArgs_Call) Return(_a0 *bind.EncodedCall, _a1 error) *McmsEncoder_DispatchTimelockUpdateMinDelayWithArgs_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *McmsEncoder_DispatchTimelockUpdateMinDelayWithArgs_Call) RunAndReturn(run func(...interface{}) (*bind.EncodedCall, error)) *McmsEncoder_DispatchTimelockUpdateMinDelayWithArgs_Call { - _c.Call.Return(run) - return _c -} - // Execute provides a mock function with given fields: state, clock, role, chainId, multisigAddr, nonce, to, moduleName, functionName, data, proof func (_m *McmsEncoder) Execute(state bind.Object, clock bind.Object, role byte, chainId *big.Int, multisigAddr string, nonce uint64, to string, moduleName string, functionName string, data []byte, proof [][]byte) (*bind.EncodedCall, error) { ret := _m.Called(state, clock, role, chainId, multisigAddr, nonce, to, moduleName, functionName, data, proof) diff --git a/timelock_proposal.go b/timelock_proposal.go index 8cf46367..09562e1a 100644 --- a/timelock_proposal.go +++ b/timelock_proposal.go @@ -15,6 +15,7 @@ import ( chain_selectors "github.com/smartcontractkit/chain-selectors" + inspectorsbuilder "github.com/smartcontractkit/mcms/inspectors" "github.com/smartcontractkit/mcms/internal/utils/safecast" "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/sdk/aptos" @@ -339,6 +340,52 @@ func (m *TimelockProposal) OperationCounts(ctx context.Context) (map[types.Chain return out, nil } +// GetOpCount queries the on-chain MCMS contract for the current op count of the given chain. +func (m *TimelockProposal) GetOpCount( + ctx context.Context, + chains sdk.ChainAccess, + chainSelector types.ChainSelector, +) (uint64, error) { + if m == nil { + return 0, errors.New("nil proposal") + } + + metadata, ok := m.ChainMetadata[chainSelector] + if !ok { + return 0, fmt.Errorf("missing chain metadata for selector %d", chainSelector) + } + + inspector, err := inspectorFactory(m.Action, metadata, chainSelector, chains) + if err != nil { + return 0, err + } + + return inspector.GetOpCount(ctx, metadata.MCMAddress) +} + +type chainInspectorFactoryFunc func( + action types.TimelockAction, + metadata types.ChainMetadata, + chainSelector types.ChainSelector, + chains sdk.ChainAccess, +) (sdk.Inspector, error) + +// inspectorFactory is overridden in tests so we can inject lightweight inspectors +// without dialing real RPC clients for every chain family. The alternative would be to +// mock every chain-specific client (EVM bind.ContractBackend, solrpc.Client, Aptos RPC, Sui API/signers), +// keep those mocks compiling as upstream SDKs change, and make each Inspector constructor +// happy during unit tests—considerably more brittle than swapping the inspector itself. +var inspectorFactory chainInspectorFactoryFunc = defaultInspectorFactory + +func defaultInspectorFactory( + action types.TimelockAction, + metadata types.ChainMetadata, + chainSelector types.ChainSelector, + chains sdk.ChainAccess, +) (sdk.Inspector, error) { + return inspectorsbuilder.BuildInspector(chains, chainSelector, action, metadata) +} + // Merge merges the given timelock proposal with the current one func (m *TimelockProposal) Merge(_ context.Context, other *TimelockProposal) (*TimelockProposal, error) { if m.Version != other.Version { diff --git a/timelock_proposal_test.go b/timelock_proposal_test.go index 2585f20d..25458ada 100644 --- a/timelock_proposal_test.go +++ b/timelock_proposal_test.go @@ -20,11 +20,11 @@ import ( "github.com/smartcontractkit/mcms/internal/testutils/chaintest" "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/sdk/mocks" "github.com/smartcontractkit/mcms/sdk/solana" evmsdk "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/sdk/evm/bindings" - "github.com/smartcontractkit/mcms/sdk/mocks" "github.com/smartcontractkit/mcms/types" ) @@ -306,7 +306,107 @@ func TestNewTimelockProposal(t *testing.T) { } } -func TestWriteTimelockProposal(t *testing.T) { +func TestTimelockProposal_GetOpCount(t *testing.T) { + t.Parallel() + + const selector = types.ChainSelector(123) + baseMetadata := map[types.ChainSelector]types.ChainMetadata{ + selector: { + MCMAddress: "0xabc", + StartingOpCount: 5, + }, + } + + tests := []struct { + name string + proposal *TimelockProposal + setupMock func(t *testing.T) (sdk.Inspector, error) + expectCount uint64 + expectErr string + }{ + { + name: "success with factory override", + proposal: &TimelockProposal{ + BaseProposal: BaseProposal{ + ChainMetadata: baseMetadata, + }, + Action: types.TimelockActionSchedule, + }, + setupMock: func(t *testing.T) (sdk.Inspector, error) { + t.Helper() + + mockInspector := mocks.NewInspector(t) + mockInspector.EXPECT(). + GetOpCount(mock.Anything, baseMetadata[selector].MCMAddress). + Return(uint64(42), nil). + Once() + + return mockInspector, nil + }, + expectCount: 42, + }, + { + name: "error when metadata missing", + proposal: &TimelockProposal{ + BaseProposal: BaseProposal{ + ChainMetadata: map[types.ChainSelector]types.ChainMetadata{}, + }, + }, + expectErr: "missing chain metadata", + }, + { + name: "error bubbling from factory", + proposal: &TimelockProposal{ + BaseProposal: BaseProposal{ + ChainMetadata: baseMetadata, + }, + Action: types.TimelockActionSchedule, + }, + setupMock: func(t *testing.T) (sdk.Inspector, error) { + t.Helper() + + return nil, errors.New("factory boom") + }, + expectErr: "factory boom", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + prevFactory := inspectorFactory + inspectorFactory = func(action types.TimelockAction, metadata types.ChainMetadata, cs types.ChainSelector, chains sdk.ChainAccess) (sdk.Inspector, error) { + if tc.setupMock != nil { + return tc.setupMock(t) + } + defaultInspector := mocks.NewInspector(t) + defaultInspector.EXPECT(). + GetOpCount(mock.Anything, metadata.MCMAddress). + Return(uint64(1), nil). + Once() + + return defaultInspector, nil + } + t.Cleanup(func() { + inspectorFactory = prevFactory + }) + + count, err := tc.proposal.GetOpCount(context.Background(), nil, selector) + if tc.expectErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectErr) + + return + } + + require.NoError(t, err) + require.Equal(t, tc.expectCount, count) + }) + } +} + +func Test_WriteTimelockProposal(t *testing.T) { t.Parallel() tests := []struct {