From 6db60286162749b2593f3cb1a1cb268a594504a7 Mon Sep 17 00:00:00 2001 From: Pablo Date: Wed, 14 Jan 2026 14:52:28 -0600 Subject: [PATCH 01/26] feat: add timelock converter and inspector helpers Signed-off-by: Pablo --- .changeset/stupid-worlds-marry.md | 5 + chainsmetadata/aptos_helpers.go | 21 + chainsmetadata/aptos_helpers_test.go | 64 +++ chainsmetadata/sui_helpers.go | 24 + chainsmetadata/sui_helpers_test.go | 114 +++++ converters/converters.go | 41 ++ inspectors/inspectors.go | 84 +++ inspectors/inspectors_test.go | 88 ++++ mcms | Bin 0 -> 2097054 bytes sdk/chainclient.go | 46 ++ sdk/evm/configurer.go | 4 +- sdk/evm/execution_error.go | 5 +- sdk/evm/execution_error_test.go | 3 +- sdk/evm/executor.go | 3 +- sdk/evm/inspector.go | 4 +- sdk/evm/simulator.go | 6 +- sdk/evm/simulator_test.go | 3 +- sdk/evm/timelock_converter.go | 2 +- sdk/evm/timelock_executor.go | 4 +- sdk/evm/timelock_inspector.go | 4 +- sdk/evm/utils.go | 6 - sdk/mocks/block_chains.go | 223 ++++++++ sdk/mocks/chain_client.go | 82 +++ sdk/mocks/contract_deploy_backend.go | 736 +++++++++++++++++++++++++++ sdk/mocks/evm_chain_client.go | 82 +++ sdk/mocks/solana_chain_client.go | 82 +++ sdk/mocks/sui_chain_client.go | 131 +++++ sdk/mocks/sui_signer.go | 145 ++++++ sdk/sui/mocks/mcms/imcms.go | 183 ------- sdk/sui/mocks/mcms/mcmsencoder.go | 378 -------------- 30 files changed, 1989 insertions(+), 584 deletions(-) create mode 100644 .changeset/stupid-worlds-marry.md create mode 100644 chainsmetadata/aptos_helpers.go create mode 100644 chainsmetadata/aptos_helpers_test.go create mode 100644 chainsmetadata/sui_helpers.go create mode 100644 chainsmetadata/sui_helpers_test.go create mode 100644 converters/converters.go create mode 100644 inspectors/inspectors.go create mode 100644 inspectors/inspectors_test.go create mode 100644 mcms create mode 100644 sdk/chainclient.go create mode 100644 sdk/mocks/block_chains.go create mode 100644 sdk/mocks/chain_client.go create mode 100644 sdk/mocks/contract_deploy_backend.go create mode 100644 sdk/mocks/evm_chain_client.go create mode 100644 sdk/mocks/solana_chain_client.go create mode 100644 sdk/mocks/sui_chain_client.go create mode 100644 sdk/mocks/sui_signer.go diff --git a/.changeset/stupid-worlds-marry.md b/.changeset/stupid-worlds-marry.md new file mode 100644 index 000000000..2e6571774 --- /dev/null +++ b/.changeset/stupid-worlds-marry.md @@ -0,0 +1,5 @@ +--- +"@smartcontractkit/mcms": minor +--- + +add timelock converter and inspector helpers diff --git a/chainsmetadata/aptos_helpers.go b/chainsmetadata/aptos_helpers.go new file mode 100644 index 000000000..8b337e48e --- /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 000000000..eb20466a3 --- /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 000000000..b4d214675 --- /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 000000000..fe036e806 --- /dev/null +++ b/chainsmetadata/sui_helpers_test.go @@ -0,0 +1,114 @@ +package chainsmetadata + +import ( + "encoding/json" + "testing" + + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/sdk/sui" + "github.com/smartcontractkit/mcms/types" +) + +func buildTestProposalWithMetadata(chainSelector types.ChainSelector, additionalFields string) *mcms.TimelockProposal { + builder := mcms.NewTimelockProposalBuilder() + builder.SetVersion("v1"). + SetAction(types.TimelockActionSchedule). + SetValidUntil(4000000000). + AddTimelockAddress(chainSelector, "0x1234567890123456789012345678901234567890"). + AddChainMetadata(chainSelector, types.ChainMetadata{ + AdditionalFields: []byte(additionalFields), + }). + AddOperation(types.BatchOperation{ + ChainSelector: chainSelector, + Transactions: []types.Transaction{ + { + To: "0x1234567890123456789012345678901234567890", + Data: []byte{0x01}, + AdditionalFields: json.RawMessage(`{}`), + }, + }, + }) + proposal, err := builder.Build() + if err != nil { + panic(err) + } + + return proposal +} + +func TestSuiMetadataFromProposal(t *testing.T) { + t.Parallel() + + chainSelector := types.ChainSelector(chainsel.GETH_TESTNET.Selector) + validMetadataJSON := `{"mcms_package_id":"0x1","role":1,"account_obj":"0x2","registry_obj":"0x3","timelock_obj":"0x4","deployer_state_obj":"0x5"}` + invalidJSON := `{"mcms_package_id":"0x1","role":1` + missingFieldsJSON := `{"role":1}` + + tests := []struct { + name string + selector types.ChainSelector + proposal *mcms.TimelockProposal + expectError bool + errorMsg string + }{ + { + name: "valid metadata returns success", + selector: chainSelector, + proposal: buildTestProposalWithMetadata(chainSelector, validMetadataJSON), + expectError: false, + }, + { + name: "invalid JSON returns error", + selector: chainSelector, + proposal: buildTestProposalWithMetadata(chainSelector, invalidJSON), + expectError: true, + errorMsg: "error unmarshaling sui chain metadata", + }, + { + name: "missing required fields returns validation error", + selector: chainSelector, + proposal: buildTestProposalWithMetadata(chainSelector, missingFieldsJSON), + expectError: true, + errorMsg: "error validating sui chain metadata", + }, + { + name: "empty additional fields returns unmarshaling error", + selector: chainSelector, + proposal: buildTestProposalWithMetadata(chainSelector, ""), + expectError: true, + errorMsg: "error unmarshaling sui chain metadata", + }, + { + name: "missing chain selector in metadata", + selector: types.ChainSelector(999), + proposal: buildTestProposalWithMetadata(chainSelector, validMetadataJSON), + 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.proposal.ChainMetadata[tt.selector]) + + if tt.expectError { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.errorMsg) + assert.Equal(t, sui.AdditionalFieldsMetadata{}, metadata) + } else { + 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 000000000..d5fb349b2 --- /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" +) + +// BuildConvertersForTimelockProposal constructs a map of chain selectors to their respective timelock converters based on the provided timelock proposal. +func BuildConvertersForTimelockProposal(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.TimelockConverter{} + case chainsel.FamilySolana: + converter = solana.TimelockConverter{} + 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/inspectors/inspectors.go b/inspectors/inspectors.go new file mode 100644 index 000000000..9db3930ce --- /dev/null +++ b/inspectors/inspectors.go @@ -0,0 +1,84 @@ +package inspectors + +import ( + "fmt" + + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/mcms" + "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" + "github.com/smartcontractkit/mcms/sdk/sui" + "github.com/smartcontractkit/mcms/types" +) + +type InspectorFetcher interface { + FetchInspectors(chainMetadata map[types.ChainSelector]types.ChainMetadata, proposal *mcms.TimelockProposal) (map[types.ChainSelector]sdk.Inspector, error) +} + +var _ InspectorFetcher = (*MCMInspectorFetcher)(nil) + +type MCMInspectorFetcher struct { + chains sdk.BlockChains +} + +func NewMCMInspectorFetcher(chains sdk.BlockChains) *MCMInspectorFetcher { + return &MCMInspectorFetcher{chains: chains} +} + +// FetchInspectors gets a map of inspectors for the given chain metadata and chain clients +func (b *MCMInspectorFetcher) FetchInspectors( + chainMetadata map[types.ChainSelector]types.ChainMetadata, + proposal *mcms.TimelockProposal) (map[types.ChainSelector]sdk.Inspector, error) { + inspectors := map[types.ChainSelector]sdk.Inspector{} + for chainSelector := range chainMetadata { + inspector, err := GetInspectorFromChainSelector(b.chains, uint64(chainSelector), proposal) + if err != nil { + return nil, fmt.Errorf("error getting inspector for chain selector %d: %w", chainSelector, err) + } + inspectors[chainSelector] = inspector + } + + return inspectors, nil +} + +// GetInspectorFromChainSelector returns an inspector for the given chain selector and chain clients +func GetInspectorFromChainSelector(chains sdk.BlockChains, selector uint64, proposal *mcms.TimelockProposal) (sdk.Inspector, error) { + fam, err := types.GetChainSelectorFamily(types.ChainSelector(selector)) + if err != nil { + return nil, fmt.Errorf("error getting chainClient family: %w", err) + } + + action := proposal.Action + var inspector sdk.Inspector + switch fam { + case chainsel.FamilyEVM: + inspector = evm.NewInspector(chains.EVMChains()[selector].GetClient()) + case chainsel.FamilySolana: + inspector = solana.NewInspector(chains.SolanaChains()[selector].GetClient()) + case chainsel.FamilyAptos: + role, err := chainsmetadata.AptosRoleFromAction(action) + if err != nil { + return nil, fmt.Errorf("error getting aptos role from proposal: %w", err) + } + chainClient := chains.AptosChains()[selector] + inspector = aptos.NewInspector(chainClient.GetClient(), role) + case chainsel.FamilySui: + metadata, err := chainsmetadata.SuiMetadata(proposal.ChainMetadata[types.ChainSelector(selector)]) + if err != nil { + return nil, fmt.Errorf("error getting sui metadata from proposal: %w", err) + } + chain := chains.SuiChains()[selector] + inspector, err = sui.NewInspector(chain.GetClient(), chain.GetSigner(), metadata.McmsPackageID, metadata.Role) + if err != nil { + return nil, fmt.Errorf("error creating sui inspector: %w", err) + } + default: + return nil, fmt.Errorf("unsupported chain family %s", fam) + } + + return inspector, nil +} diff --git a/inspectors/inspectors_test.go b/inspectors/inspectors_test.go new file mode 100644 index 000000000..8a402ece6 --- /dev/null +++ b/inspectors/inspectors_test.go @@ -0,0 +1,88 @@ +package inspectors + +import ( + "testing" + + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/sdk" + "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 + chainClientsEVM map[uint64]sdk.EVMChainClient + setup func(evmClients map[uint64]sdk.EVMChainClient, solanaClients map[uint64]sdk.SolanaChainClient) + chainClientsSolana map[uint64]sdk.SolanaChainClient + expectErr bool + errContains string + expectedInspectorsCount int + }{ + { + name: "empty input", + chainMetadata: map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata{}, + chainClientsEVM: map[uint64]sdk.EVMChainClient{ + chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector: mocks.NewEVMChainClient(t), + }, + expectErr: false, + }, + { + name: "missing chain client", + chainMetadata: map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata{ + 1: {MCMAddress: "0xabc", StartingOpCount: 0}, + }, + chainClientsEVM: map[uint64]sdk.EVMChainClient{}, + expectErr: true, + errContains: "error getting inspector for chain selector 1: error getting chainClient 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}, + }, + chainClientsEVM: map[uint64]sdk.EVMChainClient{ + chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector: mocks.NewEVMChainClient(t), + }, + chainClientsSolana: map[uint64]sdk.SolanaChainClient{ + chainsel.SOLANA_DEVNET.Selector: mocks.NewSolanaChainClient(t), + }, + expectErr: false, + setup: func(evmClients map[uint64]sdk.EVMChainClient, solanaClients map[uint64]sdk.SolanaChainClient) { + evmClients[chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector].(*mocks.EVMChainClient).EXPECT().GetClient().Return(nil).Once() + solanaClients[chainsel.SOLANA_DEVNET.Selector].(*mocks.SolanaChainClient).EXPECT().GetClient().Return(nil).Once() + }, + expectedInspectorsCount: 2, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + allChains := mocks.NewBlockChains(t) + + if tc.expectedInspectorsCount > 0 { + tc.setup(tc.chainClientsEVM, tc.chainClientsSolana) + allChains.EXPECT().EVMChains().Return(tc.chainClientsEVM) + allChains.EXPECT().SolanaChains().Return(tc.chainClientsSolana) + } + + builder := NewMCMInspectorFetcher(allChains) + inspectors, err := builder.FetchInspectors(tc.chainMetadata, &mcms.TimelockProposal{}) + 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/mcms b/mcms new file mode 100644 index 0000000000000000000000000000000000000000..415c1678a51a0701a7d94f458a43f594a95a0491 GIT binary patch literal 2097054 zcmXWk1(=l8|2XVn0Z~8%lu%Miy1S9?Zlr5z>FzG+T)L6&u0^`Lm+tQ7e}CWK%XQr@ zurtqd&iTYSGtTPoc^kBE)I5LWdiBy*C|$fr(PD}J?^nkE|Lgz0{NL~Y@1NPTX8r%Z zlQnCOOqp{0@3-|MH*1@?ZNnB#8g)$ExIz0a!EF*ZXx}<}*2K-)W=fwqYx*3CiC) zhu~&y(l%%n+@M3pZta@1YtX(y>ker>0HX*;wFZqqQhW9v>Gn{-Xvp+Kz)v{?fy222frNSf@39elNlgawQjii<=Pz2(p04y}95YzP8uoLVFmCdIH@qim zIQJtyiOE4eDp8G=bYV2(na5Ig63PkAaDzL%V)JCyaM|BHVX@Kty5^m+Vxg2CW#!WahD$wQS@lr@78u!bJ)MA`p)x6s0j; z>B$^+5K0)g2=~3%laxXfry;Ew#wh0VFMBx14Ic3Q4}m}wl9Q4mG^9Br_=nBx;3#K# z&TC>sRv%=e0<~#M2c|HWm8|6|_xU-BwILU6>B?eOvyGj+<|CP-1_HS$Pi5-UoF4RL zAY+-rbat|b+dLrVkAXl=^3amD^kN|M*w1M`@Iy4UNIsgCzF5-kG zB!NIx8ZwbXoZ=myNtIN7kdH#NW;P31$$GZ3gMA$4ELXV0Bfj!|GQERe`GfT2r6|n_ z;V5T$&nHqO*I%eYZMrd!rK}*78{Fp|5mM-B{LHW9rXU^Z$#T|noU=UR4Ke=kc=FST zF-&FyTR6*AJ`$8tj7dX5O45WDjAjBm`HwezAYLlhrWwJE;2+kokqcbr$JEA7Msm`W z){JHX>)6Ci9uX^ze4;3&=}1o&vx+O+BT`zmMFJ9&gZxyY7VQ|tDz6UH%}|9H+jl4c78(o%!^3}ZAqI80D>eVT0KrU|W>!fZ}+ zk;pmpX0lU_+6-kJTiL}cf^w=ovQw84OkgWJc*JXx<z=4J9bc-}EGec^u&(-{&(PvXPfY zOkf6^xx#gR%5Pr$MHA+*kSDz3=K|J{sx+VvgIUf=uJMU*1@&nDq9H?B&PF~GzEB|W zC)MdhA9itwh=1x)6r>o9Xu&W>v7YTb<|WAsD+lV)lm#s39uLW0#GLt??kr(Fw|P$b zqSl4ZbY(MJ`OH@e6w}w~&mi`3kgo(4*DpvxVM@@A{w!iS8`#V~j&XwXTqbe}y_Ga% zq!^`WPFqGZiS=yf4v|W#E3%M}=8R<;p&Z~g;Y+D&Qj?irx-gwt?B_UdNLX4fQIozb zCX)2aFF*zDlaZH zq79>&%xc#0A4hpdxC(NOLUf`p%Q?YmzLBP)^`$x^`Ii%XB77zNg={pVD@$0*Qv#KJ zpPZDVJv~{<1;Tj6TfPyoit$i@Iy7Vequ9tT9+Rl5IZ~TuOkg%=xJ#mHa+kkoNHCq~ z%1-w4Lv{C|5iJ?QYSwd|Xf>SwC`2*(GlZjDrZAiPo7Tt>p{_C{15Ru#sJSCQcjiW(sGB+g7de57Rlt1wIj} zopDp01~j7uy%@qGR&#`NyyqK<|JEyLPDgsMg`Hd`jJJFtYJ2^Ttkh!yGdRgbB6RQ= z3Q~gMOy(2`Iy$=%!W@D+d0j_s8Znc(T;>+3JDU#!7{vj8=_1Ezz$W$(r>ikDj3<1e zW;eOS0>06pyFSBuJ`t{m`%;gcB<`uEY0nN0604WLrxjfYMLb zOk*x@NjO?n>F9TV|Cf*TlnroAhDpX}Y|FV)btYs71 z*~Mk9af8qNI^CT3gOsEqH5tiD9*R($5|pM4Rj5ln>eGm(w4p8S=*(b7@(*Je&s3%{ zgLy3EUski04Q%5gSGd6)9`KBpyeAMM*N8@HvQnA4G$xoCZ66FoEgJVm9+x zz+#rOnhk7Y7yCHO3C?hj*Ssgv4Chy35}SnNqaw9wL~FXzn|=&tIFp#nOlGry#VltX zn>o)VE^~!2Zg7VOJme*Bcu!!aenNbHCmE?IMqL`xobL2uAS0PT2=iFR8aA+l{T$*L zXSu*-u5p9gJmxj;_())u`r|vI5|cP2Bn5?OL3?^IjIm5(Hmg|67PhmCgB;-;_jpg# z*?J(c`IY!2AvtMCM@F)cgKE^GK27OOe+Dp;F^pp})0oA47P6ET{KrvFa)~hR^MF@; zCjJ~_AU!!LOa*GwoKB2k8gp67S~jqkgPi0EFNiVM97#wL{vaJW$;Y3Rpfr`JO+y;d zg7)-e7-N{o6s9wW#jIi@+X-bq2RP1Y&U1+y+~y%4h&a!Ail2!?5|WdajO3;urKmz} z>e85Iw5Ah%8NymFaGC4eeGz2{7q+i(ucu}W(o^f z#(Flhg99Aq5pVfOtOe#r0+N%3qEscAHgupPy&1(~{w0*X?B@t4ILSq>aEm9rB>qD4 zA}OUQPgQEul)vdpUq&;PIsD6dwy=wbJmo!K2wEgo{6Gxil7N(CAupwYPNEKrWj?ZNLA|6h~~7V3j-LzBxW#&1*~QZyV=iS zj&hDmTp^5yJmUj_e~pV6Bqj|R$WJj!Q-NwUq$OSH#XyELmJk-Rik%$cJhynrQ(p3# zcYNX-k(OB#Vw0GZq$ex6DMV>1QlDnDp*wvU!dPZ9pXF>|7kfFv1+H_Cmwez0k(P@E zaY;%V(vy`u6r~KE7|t|a@qy2LBm4^MM>4XKjl2}5993ycXXdk<8@wUB&GYicx_&1k-`xjAJfK z*}?%%bC<__Bgz`rBOS#lM@z=CgmvuV2&cJ3825P0Ya*`oemglRO(({&ls#PH1L4-W z9~r1lLpsohaZF+k^Vmfgk=Ls$auLkm^kEnq*~)GXa*A`@;2D7pYJ&LWr36)}LnDIu zo3YH}C?`2f7|(diSH9aQ*Z76_q#z|}C_zQq)1N`i<6qXYku7ZJB3HS^eID|ZSG*_O zCifu*zmkNcq#`YuC`ehVQ;%-+V+iA!#cs}Uk;gpe9bX8)Ssw8-afnY6Qj(S|a#W)(4GE?l-RZ+j=5v74Tp{Il*C0CsxXUwM@R{&C zyhlPC+R=?8oaQ2Tc*Ilk>@*Ha5W+0Bu!jSj=Q_{%MEG6ydZH79I3y+&naM#OicpR! z)S)pQ=}b3z(uV;IVKh^i%VO5>-EQ|GHAN{;4H~nBU4(LkYux2EABnohbNQ9uNlqs6 zQj{`Oq#iBl$Y4e?j(IF+6Nk9LQ@#)-RPB(QLX@Wt%h|yh?h|gW^&$rGNk?vqFo6&r z@{(}>d9R0gmKouI&mZLo8`;*p+EDT^cQ<%dVwsVpjd?5BIwL*F7(2OqZ=LDB| zz#IPeq06YmAQ5>fOBHI)6hI4)g1IV?nhd(QHWAhp*C&k$XMpGmc1M%j9a9;WIf1D85+=* z?hN2Exi32>GM>pyV=n))jvf4VMXpntzd6n&uJC|Yd?eyk^~=xvP6o0ulyPilA20Yo z#B0`)>@=VilL_HDulYc-FnLT(>M@*gZ09~dUw6)@FlDGkJ%Z^(PiC=#(_G^lQEwO{ z1!zHMrf`=Rd?w;ey_dEe<_zb#NEna#NW@!moy4Rf7saT`3f8iny&U2)H@VLvUh|oV zx8**m$Vg^#lAph5KvP=KnjZ9LFe4eqD%P=+!<^$0FL}o&zES^<8m2S78OAumxX&|Q z^NFCl@|dW^Bo6UNLJHE6heDL41|i(yKF|0-;GVNPKa+qz$V6@mQi zodv956MHzqS;Bb0D?anxeS1B>k(6}gpb!Grv%U+WbXh zTGEAn{KE`ZvW}hn$1yH)lPA3A8<8HW7ZQ=2EaV_Rg(*pSs!)siG^I5i=}b3z(wn{v z;~yq7i^Z&94I9|O0giKqtK8!m@AyWfNA^16l8|I%AQyj9j2bki1AQ3H3|14$1;Tht zp~s%XEatI-P3$0)|2V;8UJ~@g`(LCYH-)Ii3Qq8nm{0BRRG<}yIm3NE67HEkPX`7v ziPuvPsQ`m%=2T;Ms8Ubr5~=*@X9@r3t8cxlZ@M0yHRjOnamGkZD2 zdG7PeE03cH?U=?Ac5;K4M1HNl$V_>H8AJ#liSou;k%*M!qB!NKO*?usoQs5UpBH?f z;#;pV=tLL#GK7iDVkxWG&tcB-h*$jZP8>);Qc{wEOyr^{6{tp2+AxYSEM*nz*v4Lt zbDl8n@rY-<^1PMq+DvDB^It0^_PV{CNbJ@TF z&U1-tJm3khc*l32jG5TvBtOLnW<1lG$5IY+l1tp-1@8&}SzeNiB2=X=!SrAvvslS7 z!gx#Ii@6bxr2Ih!N>iC?w4n>#8Oao8vWJ75TeE&@hNK77zQG?d}O%H}Kk$Eg<4~MwGE$$H%2p5ROALOJUMX5?F z`ZJM5Y~v_rdBt143l}aBlXxT~J%3V-HVhzyrEKFkR|pCU7l=kovXGnNwB&EPGmsIC zXBx9v$_n;yl8apD5wH0!yz3I1G-M$!g(yQ++R%@QEM*J(xy&m*5ix@65Ss)fClh%o zN@W_-k?ss-G_zUBEY5}BvPvic^WdXi9r}(4VnvVmFt$${k+thR+0|h&|DX%kQKj6NM;4O&SnPJ9^NI zp-g2a3t7Q`oZ$|yc*p;K$S{cLBql9c$wyJjQiJ+5qcfujVIiy8%72{XIuCfmSEBzI zF7PWUNKXz5Q<_?|p(_I!$1Ikyf^8h)66>LOH-0 zE^(6wyyhEGV(Ll!PCBwvkdjoPF2Qu5H$$1gMJ{udd%Pm>v$>Iw3>2mqqnXM=*06)a zoaZ(#_(a5C!UcY!I<;s-Fx?r!ROYdQ4eVq;C%MFJp74%9EOR3k@kl`?@==uPG@%>) z8O0c;FrVjyj~&j>Ug_J!ATdd3#~{YAkc~u%BUWUiG?n;^U^+37@l0eXZ}~>FxME35 zI@6EIEao#&e|1k%k%3HPBR?gmPB5+MLU#u84|7<~E>3cl2fQQdZ{Y&Jkd#zpr5H77 zMNcL$pH+l%fEe-g1rm~q>=a`~)Bbm-T)^LDR+~gIJ5{W69D8^jYv4?Y{NbH^rU@Rf5Ae1oP6Zd!X zrYa2xW(^zJO(=&s!)3y_&nrF=K1sO1_r%~gl8}MCl%@ea=*2-!bD8Vh<{?jc!DoI- zDyF0+7bU1mYX%U)LYA|WL)<4QndcIRKS)Ie3Q&@IbYwVVn889;u$^68|!E~e#!x+Oq7cuOFKbs`yA$xlhjQo8>CB(8+~z4?`7XUZij?G`DvjtsA0{%F4IJYPS9rpEB4zM=Ixw6$Y~e7MxW{{< zWz-MJO9lRAJ9{|IRi5%)CcT}O?BfDAdB^ve=+P^5oZ>sY+8q zInOm7^P2Dl#G7A8NCxsziB|l_SuSyxXM7`8LG?g?MlgpJ?BNpG3OUD9mZtPzJWugr zI1r0;3}Ff@IlxtN7ZyjBv70nSaDo85Xgb{ha0z5sP`9K?>56 zi=tGaB^?;aM3xgu!s1@zQGn`f5MXAZ2OEKxVOp zP%iSGpK7@VS;$2xDl?1cyyF{HYpXYc*}*xk@r2LBtRt_mh1PUuG_%;q z4)$}NJG|l}-?vaxBp?OZ`ID;DqYFnl%WWR>iJ+EphIpi<2<50pLt4>=VN7Ke+u6?r z!g#`G; zk8?cb15w(0KAEY;Uj);Qf0)EH=CXqI?BonLdB_L8>tIi%1^pRA2rJpf8E*5KPekqL zzNF+&%21!y^kxiGS;8L9@{G4c=;SO)2L7ZBt?0v4E^(FHJm3ZI`AWpjVn7^z<##fX zgCdlqCiQ7UZ)UNHW85KP7qKBfMW{$K`Z1LiMCod76rwskn7}$taF_7itN|&=N_BcL zk@f839zS$fxAb5Pvw27O9?lVDrXuy|$Y@rwm+QPFN>4dUdWzAI!AxU4CwR$^y{s$w zsX~1^(2LQ`XA`Hn%2Oiuc5VKk8^f8wMhiu$yt z50hBTI`(s&*SzNw5yx0V5|Ejp%;gzrDI92J)7*?>8 z^W5bN@yB~C&FRBp_Hcx&eBy@*){lHtU9#LSrTw@9|dCW(?5Gll2irB;> z8EME$5z0`77PMz5qnXQM*0GBNT;vY#`DupOl9*%^pg84eK^OWnht(Y9GOr0g(>_Q% z@=}QAw4fDjXh&zJ6T%E;GMl+9VFjBw#4%2Bl`x+0jt_j|hgr_u#N&68kd!|tMn(EE zis{VaIH$Ns7>{|+7rqixT^Y<+7P6A< zgmQ}8JR{tE*CG|=s7^gP(3RngW+Kbj$5C$bk(dkA6NRZme?~HuC2Zg@XSm93o)NUr z`tdud$Vw5)Q;Tj)W+Rt)O4LOjO9`6LpHYOcfJ5Bm4Y3zHpHY>LjAJz?c|fEk;R1=t zM{`E9l50d+s=rc;o`kTGv%H|e7H5NP_AFMhfo<&J0LM7PC9ZRq$Gqe{Ux~2Y8Hnh_ zCO%0>NqVx9n}QUh43(%sT^iGZc66pE{Ta$=CNPcJEMysL*u)O@a)=Y0;|e#q&r@FW zk-!e;bfOZIxFjSQsmVxo^71DoC`T1)QJkXh&yy(x0J> zW&+cg%|e#3hE42XFNZk6Ij(S%`#j|}9|`Ohf1(nTxFjSQsmVxo^71DoC`T1)QJWJCO%0> zNqVx9n}QUh43(%sT^iGZc66pE{Ta$=CNPcJEMysL*u)O@a)=Y0;|e#q&r@FWk-%Q@ zCn_-+zyfaakidV&PHHkzlFHPl9V^(%F)nbQH+&=NKF=jT<)}?_+S8Mfgs_m!?B^Pf zh_K&yNJK4KGKhbe%pBIUom;#m>jCFI+A@xR*}-$Z5bdD-h?3N!6%(1oPHymtc!#`> zp&tF2$x3$egzpa9$LPy0uJV=$N5q)?)MqGbxyB2=^2<@RMOMl)h9x{C)-kz3HHNT| z_3Y<7clrLfGZ7_e!x+|Zm$$?^A;+jjBSy1<<2)kLNv|&`O$!DP!g?+e`ILQ|Leyje zOF6_XJ`nx1o9cA8vU*<>|s@irluggs_w2+$G8#J(Jv&r5`KV!$Uq3{jQoP2leT~ zK#uU;J@aA|NBBni`__m-Y~l)UDE>g)7{Davv5`YuC+b7Jn_M&`go9in-Xre?(U}ky zvy0O_Bj#hzB`-Z$$5o;~v5wSbJS%z1&rjtX?Fr>8eV*y@M13xfOyLwC`1OT7g~2T2 zFu%U^T8Gsf=QHtMnIm&J&Tp^1cSJpUGKEKc<<~djLKlW`j~H*Au_;VtT62Y1@6-oV zxydt9zBe~Qct^<(dL#WA$2`^&N*Iwp8V{wZ#~`M&g4aa)B;ROGf5x+neZ>E4ZD~db z|8b2MwEJQ`xIy@@`ZRwtiVz<1k+k33o6byNDF?VmRiE^p!!O~20$KQr)(l|=>o`mL zprAkjnlq5GY~~P;`6GOg&rt^jCa{EEoZvP6A_N5vbD5xsL4lOyp$?r`!EJv2E-28D zA!a;#@)MX(%Ima#H{16mq#t^o0h^xFNLgb)8 zJPJ~gzZuC?wsMK^QCy$G)MX+Y*vA{4+$SFC=i=; zl%^^D2w?+9xa5DbF*ABl;1zjdm>Ywc%Q-%gG^X|XpPz#Q?ODrSUX$sUpg<8?(vKNz z{@QiD~T<0I)31O@UloY@@X zG2bOLCd%^0B#fOkD$OX7ITnWe4|84ab++I z$dXF#(v2ys;W%GNl{zSpn<3obDdEzn2l}y`AJWQU+A@BN}&^k*V-*h+--YMm;~ z=OB+soFOPMjn(Ys7B4B9F(}ZH(VXWou`&e(dNGn)#LR3>smXfw5+{pTQJ+cd=P7Zs z1_iQHo+W%HVYZ+^UYfI%3q;Qz6i7rX=ChqgM9-m?DMUG@vxO)*-Je$UCyb|jY{#P_TrYV;V_I1_dh9hz=~~7&my&Po;taX(+{C^k5(NNm<(b zY0g+ale&!iGnYfWr$Jd`WHVPOQqE&&MF>YoUEX{c!5R+mnfMjVi8}P;Jt->cSF~d$ z+qg^4N^+JCOk^pq313-HWfGsrS4Cf86}vc1P*t@-D|#@35O#Bhk0h<8&(MPH+~oxy z313}q5sO5mBonzQOc|xwh?(v)t1l5rD{6Yd!kb#^O zq7;>>LsQz)m41w10y9|1N;a{ZL!9OccX-M>0yXs-ViJ#Jq$3A~C`D!J(1bR0p)bQ3 zPY4TG!A5p*kW*adHcxoVH@>f>mlKcVWFQxRQiiJ3r5Ww$Mt?>yff+1hC7amIAx?9J zyFBAPLAAw?*d!)3S;eGUb^kyjI2w@?s z*uq|paet2@|=%^uV?Qj z4!@IzY!sjb6{$rdTG5H#3}GzOS-?s*vxg&`<2ny{%~!s!FUN^b3Nn(LB9x;B4QWMZ z`ZAme%w#cZ*v39iaEaSI6a zJmoz>4c&*>BqlXk$xjI?QHQ3qqdNl`%@pRaly&Uj04KS`ZJzR;phoUPY!Z`-Eaam& z6{$@V+R}{yjA9bAS;{(gaDY=>;V#elNQA~gfoQ}f32DhrK}u1Dx-_RfJsHdxrZJxt zY+?^bILCD!@|v%F-$V`&pA=*yH$^B%4I0vl&h%wC6PU?j*07CzoZu3-dCGf&np!hr zlbF-#aj_wR(G*g(%GB&V_L!99n_j$=@zH6or@EgfUPfq@%4ArPl3p&!9 zp^PJhg{)!=dpX7hZt|G7cwrfc%r7J)C7H=fF)C1t#WxWZkY z^N|R_;!j+Xke2Keq!d-COLN-OlfjH(8uMAfCiZZIb6n>kuldUNEySPrBqu#NC`4(h zQjcId(2F6AWjYI3$!0=1%6V?^h&O!Whn8M9lYl?SL>`J#o|-hGHC^b(2qrR%C9GvT z`#H&F?(mEcgm0yH5{KVOLpBOflFIx=GybLrgZPK3%wstl+09|j62=2w@r6jO?bXC1 zIT^@BVaigS2DGFTeHg}gX0V9WY~??WbCFv-;T_@HIP(yTM5H1M`6y0BYSVhcuXi8hU(vRVcCxiv8U?aOY$SJOHho`(J=x_7m7ZQ+y z4CJH`rKn6Dn$U(W^ko>C+Ur&1CLaYUMj84sgwaf38Z(&35>|4Ki-d89M?B><@A$|U z!go+3l%onG7|jGWv6UU{BvGZ>d=tp zw4o#2>C0e7vW89U;1Mr)#}~qPG6#Ml7G} zvYY)Jg%K|Tso zlJZogHVtS-YdX-4J`7?6W0}kh=COp8tY<5`+0RiBK8m$Vi1P}BqbFY$VMItQG`-dpc-{(NORiIk?!lE{j>o2DY=8Lxk_=+(vZbkdWl0B@4MJLHJ4rU6Z8MSEs2n?)>VFP8}8HV=8j zC%%$!fORE1g(*f!+B1aFOk_IyIP$+g50q!jVgbuoL+(MwNl0giKytK8-hFZn=V zh?o$KSi~nOsmVl63h@6ZyAwE_s>X5PPnq#9^`=FOqEbq-jAcZYlr6IFk!?0(GMiZ} zrDO{wQAi;aN|wr!wUAx5WZx@FmdF-m`G21=#=QON&HwXxzW3hex#!+bQ=H@4 zLFzr%lZ(fwMr|6>gr{ju4DIPa3SAh;V1_fA2~6Z;K4U&#vWoR=W*d9?ks}=AS1u4b zSXputcW@66QiM{J;|Xd|k47}7B~irkEN?T0517Iy?BNHFaDvmEC&wG=H8*hwVU(sU zRe6d!G~!K$@iwEGz+|Q|hXpKS4IA0cUJmgKXShJVxK<1p!<3e~AYV_FbFEQzGkjb6OM zAm*}=<*a2BJNS+R9OZYeeakbGi`&RYA&O9nay&sD8nKp*Y-cau^ApE7$F;+aNoYW0 zTJSYn+0A~AaFXB1`L;fbJlsoFYSD~Vlzm5gWHBoV9bwIb>$sUac$I++Wds}9!gjvp zM~aR#Po)fxQI%RWq&aPgC6P3qrw9Fbonee(9Fv&FY!>h(D_PGLcC(+uoZvSCqdY6u zb2E2vHwAc@;ygkHDpP~HG^Pb@X-5KSJWo&hGl;i%m+?$yI&)dX3f8fiUF_o!$2rA0 zu6z1Y-BsT_@2Ta$xq5so!YdZExmY!LCj?#X9-MF zclZ~%xS2fM!-Ethobo(IHEK|grnDlO4y4ePm*~qthA@Knn8=U(%t?ObJb}sH=iEST z8qu7VL=s0bop^!XyviHA%@{slDl?hSVpj1rTiDG$4so1QoZ})nr)WFe!foW^UJCLs zB?zZHm8nU6n$e1AVo4;OZuF!-gLsQ~8P5Wiv4)N8;9CxGl+&CiWUBZnMro4hL|0y- zF9R9MNZ#ioK4mrwSjHMQvV-sViDUfA1wude?A*egb@DvUBiVbXI58tt$ z!<^tZuK7e;Cl|Moj{+2?1ZAm2b?VTVXNV+@WIFKzy?K>4c$?8oURJzLn# zehzSy)0`*psd`39N>hO<)TACwX+<<0c$+bNz!YXMk1tulIySS5ebkz!&*y2LA(A+f z>CB7dnl4Ys!@U%w7*ElFr)fhw5=i5De&lCPagH1_jH$SZ$EZdFn$emV;(3P&OkoD| z*w10g%ycc)XhS>3F^Q?nU>;wxlJ#t67yCHGan2I>Ox|(>x009pd6*KEr4rStLt~yH zk~rSv9meu27YLoDZjy`J$VUMRQ<6t{oF}Qvz}eaZBYB@SY-9&}_<*4v$REOZgo;$977b}mTVhEh|3cvj;}I%S zm0C2UIcT1u056<%uDlBs#H;J^a8= z9OX3U30W$g+)N(s8i%r5qEh~wm0 zArB}>F-o(J&Fo?yhd9nz0xR`n+`z5m<$fNf1ZAm2byDccOT5BhhBKN8OkoD|_>z^Z zXA8U8&tXpR8`rGTUdhF6D1dqP}A#;;r; zbdCO=Tc|{J>d=^Hh$N0=I`blZ7{Hsn!&pA#V?N_^mhcrD*v4Ld^gZgA}C{kMcNAQkMoiO&el}Cxxzbrw_0425&Qlhz;f)B+-d8-xwqF z&yDI2w~>zm6s9DP@;FaYhsHcZYhs8emFMU|Z(ijM-eD{s@-d(BIZOD84QyjCKk_rD zILAeDZt@Q2MsDYB9-s)ND901jpcV}o!vv-kCNhO-{J;^8@hcYy-L4$Cj@;ZqUhd_7 zicp+z%J4WO4f7D4snr-x-_9BQH)|7lbFh<%w_@0Si?rP zu$%oH<_s5kc&9ugY?pUC6{$)s8q%D$#F9ul-RQ+D3}!f^d3?8eM-y5SNemrG;W=KS zFRw6|A-u)AjAt^_nad(pu#U~_VlO{(kY6~-?_3~sk2c9I+(~{Oq8O#AKoy>%0nKSi z6wlI;&b&w;2Jj}s7{wSSFohY+V-YJ@#|E~shy5Jp1ix|3US&uwZX+KBC`?Hn<#C>* zE=_1j6wlI;E_CN*USkL&c#nyE!YsaEDXaO0?R?7tj&hpwgnX<1ax;0jmx2_dG!>}A zQ#9ad+R%;!(s-Vp^k)!n@h;<;%yj0mh!w13GrQQwA&zsFz<1g_H*hO?xu1tAL0KwM zojNq;86t@zna;dO9|rIy?=Y4R`Iyi6oFy!0Et}ZMJ`Qo5vjo1ECT`$X@^U{9Q-ab| zpb9mqPcvE*Lp-TGPfz+YnBk0O0#lg5d=~Q+8`#EPe&lCPagH4Olp8mbhx|N57>`hq zs??$(&1p+4iKNqwUcAC!hBKN8OkoD|_>z^ZXA8U8&tXpR8`tbtx5>qAg(=CS zJkFEUr3o#G;#oS

q}YYbro?=g{2n8gQo7u%a4so2b1b&hxZr~>F;2s{N zDB+Z+GBv4BGg=cvJgGcK5Bl*s!x+UlCNYgUEMz%r*~Cu1=ODjuhKuApXwE}!?&3ZQ zQJgY7Mm1{Fh!#Z9p7;5PPnpLeRFrSW3CW#%I)^9!+UQG#yBxD=*QPfed9N@ADC#GMfb~ zV+~u_P0|tLE;g}~?>WdXoZ%ulf0ob8<4abuns3<7w;bRozjA>hN7W0;Q<=4FVkh76 z6UX@XFX|L`a1ReslyJ&ZnVQt68Lf#So>abIDXaO0?R?7tj&hpwgdEq-xtToNOF@cJ znhMmQ9v$gIcRpeYGw69j-Q{(LF^X~g#(AzeseW(+x009p=|)fbGl)%WWhdWrkY6~% zIj%ir%+9Uk<$fNd2*oKwc`8$#G@hp?#eUUKP?ky@;TXSifk)4HR;ut64S1S1v?HEW zo}&l-c%5O4VjPp0#vB&1oNw69w;bRor#Vl^S>?=4+`&CONKwKmPi3l6o2O|*I}%8y zGcVAaR~hx2F#~h>nynQ0U0bB;InPD|`td4nFq{#LVi3Q&+@ zl%@iWd4|rs&M-EzgYWpy1$`2CaUTy*gi@5_32IP}rnDlO4y4ePm*~qthBA`(`GKD} z#tF_6xTxMSl#wjt6u)s#AV=Uq!mh~?C`oC`QixR-(yqd9GfC6RQx(4C(2XAp1kF5{WZbmp>%6|CbRzi@_&vWGEwfpJl9JBRlwxpE$;^T%gePIReFLL<=HlPZFJYf!<8y6E?GpeH`LAX9@f# zN8lgaz^&xveriyUrnDlO4y4ePm*~qtHn5Go{K(Io;v6|{kPqC%9o)l%6eXPURHi2N zX+~>eh$ofj=s`bTXBeXx$9Mch&s^#SgBZr!jA1RCD0!oHOj#;Xo!T^_1tWNm5BZqS z_?#vD!Wk}-^QIhu|B#!zxQ{{e7UkMDZ*g=|Xp2<~4>eg7=unC(Pmtma>{}*iOQo zIRa@s&tXn*mcU)|fPZl#w{tfSP=r#H;|Xd|kEXODnhvDUh3>q}YYbro?=haqOlK~O zSiw3rvyHv{$U%PL3>SGTuRfgdOyyH%vw&r+VIw>Ej-NQjuUsHBpZ=U%xRd-mL>P}y zk*d_9AP}A#;;r;^ls_k7VacJ4-v*ARHQ1k zXh?Hf5lwrN=)`kOVj6Q;$Z}TkHCu_gN1Y*sE_CN*2Jj~DFqRMbm}$&pK8q=Qul|rn zsX!HKQlDlFWhC#jo-OQVKZiNNZ(Nh#*nx&Lp(RmFVk$G4&)EB zHnWR;9O5`<3Eb};#SPp_Uhd~%N>G+cRHr8OX+~>eh$ofKyg+YWWiZ1T%>)+|0tK`${>^{L&F$PxejcJQB`Hk>s_;BL>CYgBF^X|aVj6Q;$a2CB7tVE}LP4rBR{kNJ$xS;ALrU>kcmz)?>6w|JNFOlCTBS;Pv~v4L&uFHF{}8Rt?c0k zP88B#ae>f>^;g_NRi30SO_;&Lp-TGM^E}Qh_`r`@l0kq zb6La+*0Gsg?Bfu}IZL33GUY$q$SvGSejXx>N2o|uo}?~KXvs8YGM@!3V+|YG%RUZq zoEAmZ1)}Ld3S;V2+N_mo-ySR@+6sHW2QH|O(q6HDO zCy7qHKyO~<4c=x9A25}f%x5vH_?oTk;RlXzlHa*DTv>4=w{tfSP=r#H;|Xd|kEXOD znhvDUm6zztKtAJhmhcrD*v4LdgSCU2ftI?x7w{Nueu4 z8Oi(PFDH)(qcjz$!c#QhY1$CQvm}yEH+r#_P3+`9<<(*C;ywydoH9H{HEPp{7DUjV zBt|igNlYWYg0kQ_deD#88OA8aF^QZN#Y=AP;ywydoHG2v87@-yG5sJdiDC#Nc#j|X znNyUhB)wFlHfz|(4*vPLdc|!#Nh6xkni%3qhhUf6s9C~ zX+le)7|d`+Gl41W;5#l5`lP&|11WUn1Ew;Qf7CE`=2r4@KMzxaw#1T1I^7t~XeKa) zf7R4KayxhPEFI}WcV6aGX0w20tf9zL`cTU81U0C~3-sny=CX(ttm8Z(wTv$*#}m|` zG0zZ59LY>#8gp34a@MkmoqW$h?x?MA;6aKKPI)R*llnBHH3N8)cNoh>a@NuA$jx2c zM!&TvLEfhlZd4?l2(ll;!L zO|>Czd}-|MALy3#_}N_^BLDQGyftF_fn8zv?7`gPp{s6joN(u!!_;BCfmin9b-sQ=u+ zt>oo?9;O6cd5OMEV-5>h&RRCHlLH*(p=XpUZHZ+8OIg7>zF`Zy*vA8{q@5bnq9M&` z%QR*(p937FL~HLd%2J6Q^y77IXd_>_gR0b`A&I23k3&>!E03r_G#%*6KvJSSGkf`w zpSdSm8Bvr?>|`%La){%cB@iPoX-5KSJkLUwvzGs~Q+C|Ko!rd>^yXFGU<qbBuvpO5&IoE)Ar7H0_tq_?&I*S`$Guu_TbjhsHfCr&0Xg&E9d0oU}`4{<$pX+le)c!|FJ z%x~m;MSbHoO7bY}Num=kaEf!}c-5TbHRB)#(RrY`DGOP`SKRoz^l~>3Fnh2xv5Yl* z%~tmCJqOA8hQ5c~+(io_XwOD=@GBPxebaMs3stE_LwfNtuQ6_j_QYO(OvYl^fGt8KoIFfmnu}onO3)#u{9OX1=Z^;i{qz{7`%2>uTnFAape7HW1 z%G6{TYxs#{lziK`i;8sTWnSY)e&!VC$nlOkK~MVgJ`?$bS$x4#*0Y7(TsK19BMOVJf8+o{wf)t}PWvN7U>d=^Gv?hjll1L$)ZoJP&e9A0#v5!N9zpLNjNgC0G z?!3$fwz7vG2#nT0asv-ilyK_Om}iJ2j$}IXB7G?Ip8kb0v?HEWM({4T&6Z8e-<}U7|5XC9OV^pIyjc7qz zVo4;OZuH_6W-yQAoTc=K+CP=4Nqw5pnh4sH#19QL_T2_U$B(be8YCWBtD) zV>REfnO%I(L4M&37s)wA9UwP%aUX>!P8lAfDz#`xbJ`Ncvvi~j-FcbU7{UnNVj$}!+qs)?%2SzVh$N0=Ix~hzOk)lUSb!=ug`#H=BE|PPaGA5Qp(& zl-VrcD>ks3{j{8}?5Qkcm%n5$un$P43xwwsd6reCA zd6dU_k~Xv>fxZl65i3~7W_Iz9S=tbJxR-(yqcjz$LS35Bk|>^~BVFju%e=-AM(`dJ zS->*Zu#J5j;yBmM7B7VP z9mb$cV>%02!**`lsjr{_C75u?vmI4e`GA=$=4;9wb6=Vg&9%q9tEj^P>F@?$vf zozhPEj{K*E6Z9=}O;wLIQ{G4GEkfG`}>{^S+QkuKT5p z!aT}B$`%L-bmlV_vz~Jggaqn77!r7f_H?2rsf9e}!=97#{JU^S;C2d7f?UNy0#B53 zEzi)NW1OdFnUKKi1jQdd6}gfrYGLJKt6a3H;1C{#nsA z-2Is6qAWdF#VwWOH$~}0F9y--@sPm7PlN=1CA6}#WOS8~K&h(kOGNdMz%ssJFGsks zhP>lpma>689N~BVSu-TifYx-N>{Fh(w)l9L=5^E`zG5rW>v|?0Xdpfkd7gd@hPCwwFd0 zb4}k6b3|p>PyOK{U-u6Q?B+1PG5Hnc#4^62{%f9>4!rbXNMInNn9NfXLjv!xgSMZ9 z1jbDd2~?WlS!ad>ewY;!Xf!({5J@sG5;Z3zkU|d@%vJuMYXe_|1k&lv8(hC2B=C>L zA%S7EUZTD;g*TRl1jdkinKaRw1fJ&=9$qdFS9)H0a_}o{gPf~fLo})MWDuj7%6)63 zk&e8?>%7Zkj!hXl&d@oR0DfzD zz*+veQ@h{g9{aU{AJk_$|ENrVQdduh1d9I}5}0vDzMplDeVky-Zy|w?dE$aRy%-Xx z76=VACW?-9XCR-2ga(#UF*MZwdn`2Y{!O8QPdULgH-`pVa*DKDLIXWnN%>nt15Z)p zw$MNi0(n9MH;|XYl%pn3(~dOuaD?Ca_no1EJ19tLs?v}MlIhMsMlqR(?g|Z*p*l^7 zq9fgTjS);_7EAetZ#l|&uFD%5$U{L&Q-ub!A%W-V&s&UVI*VAxE)H>)f8+}d+{*ow zpb~Xh%PtP{JO930d=#WKRcJsP5_q2eyv2B?vxs%<;t*%~$35cXeo8Qlhw_I89-%4? zX-g8Huz)q};3s}1mHQ1jAuG0 zxwfFRaSuf)PfeN;Ln=KO#Av26pH*z-M+z4T4LnK>ni5S4FENl&OlBUd*v0{VCFjGT zf%^0*D$T5C4?lB`e-~5Vd63dnr6Ca{)185gVls1C!DjYxoIqG;AQyL2gmToR88M{N zgF%dD3iDXW7JlFqIf{n{ZsHz_Ql6SLqaA7VWH6(d!aP>8h5a07Rw-?bHsQ*T=lJ50 z(7;!Olo1C{(T`fsvVcpj+xFv@|O?wZ#6sv%lMt9733=)vxA%!)gQti z(@(L0-A{P_%ATKTRXis}tIAVWvW4c=v^l#X zsK5V)23j$U581-C^+N-X)0IAa%1l6V>KJt z%5L^?kYil`toJn0JWDd0*ul4a$ITt&BZVnJ6`BxB0;%-jRR*(&U&tTteMK|+GJ#Fx zN$~EaB2}nKe_m%OpR<^itYZ^9IKl}|QXo-YFr0V!nj@UxEQOP#m3R4+nap7>U+^W% z*vfHEQz=p#mXk`UCD{OBdFp0%1XAR$QT@US! zTWCW_PyICyP?!=t$xmG0OT3h$7TtJ>;f!Y@A2XdfZ0GUb>OHmjk`=6FBl|eO&m89r z=g8B?*n=XJq%4n7l?JpXlJ+F>IUCu|Jugc;g?W}6`f9_}=N;yLXRCNj=hep4$f+57CSMyv|TYFqU4g`<)NzHOPBuu>SB3?`QH- zoMt>v4+e9D6BKyU7=dN1W&>N<%{~rtjMLmSL|Vwl{S+dM(v;^3o}>KJt%5L^?kYk+Y9M=vD4g8ZE$W0MC(T$$;V<1DA zz+|Q|n=e?x3f8ib?d;_T4s)C{Tp;8v?VTIBjlA5)Llh&Nay(9TYSWOWv?Pg9jAc9% z`Iwo^V-d?)!#8YW5BoX9FZ{}Ratsd*{EJ-N%3b8AAVn!f9U9Pv7&_3A&b&Y``tv$N z8NpaSU<%Wj!vdCa{oCpQcW^fac$nfmLIo;QgSs@P1#M|ZXRdokTFFmAic*S4sYEqu z(ST;OB8oVYNauNa(3jVEleZbocqZ{Fv-q6FEN2bhu#G+J=McZ}E9c2ELcWrVTe*w; z6r?C6C__b_;7RJxh~~5*hB)@{J=cuXU+^z_(3_!*U^4Sq%`Pr*?I>-I64a+L5ybL5 zFEfade8^`kVl`X&o}=9Ju5zIq@3VvzTsvA{!@ZQFCUtn0G{J?!TMztecEu?K1NrVoP|$pk)S2J>0MYBsWyeH`W_=LmUE9V9n-DL@gz zsX$d~)0mb-6Hgl5=*<9zFp_ahW(M_zZLqXQCiCygH2&Xtt==jjUf4G%=JU~%O zQ;}-ap$V;sA%S#WpbxJxlu?Xl3N!hfrL18SyV%bWPH~>l3F7Bg^6>ygDNRMHQHLh9 zB8CLgd4WE>#!yBvo+-@abC$A(P3&SnM>xfKLO&2cw~~(sC`xH6QjIz^p%pPCkj@MA z;WdUbit$WgCZDsEHEd!R`#HiX&J+5f__>vQJU~%OQ;}-ap$V;sA%S#WpbxJxlu?Xl z3N!hfrL18SyV%bWPH~>liQ?y0^6>ygDNRMHQHLh9B8CLgx&9+Q7 zEPis6mjVHjQaXH1VX-jou7k2qPKCWM(j*C9Gy6JK4u!PI8WrPsC4d@=|~z zgj0d4)TS{li6)*jy3v~f3}GbWn9L03vxL=bWGDML%t_7>@~QaAO zCDFu_MmKshfFX=z9Fv*Be3r19jqGF}hdIePLZ*qI+~lPIMF^(?RjEy5S`tk>X>_AE z0~o?c#xa>0%x4L!*~m`zahQ{wBV@Yx$xU7gP=s(QP?g#=rX|tDlSVgsGk_tCWE_*3 z!F-mmnvLvaABQ=~IYMTLpWNi707VF=0#&I^V_FhTJZW^JHv<^LNX9Xl8O&!1tJ%m- z_Hme#oFinW_{mLP3Q&Y_Do~Z$G^Qod#FIuhdNY6_jAR^>nZbOPu$qnRWFLn)$vHwk z6F<4hO96@yP6et`o5r*xnt0OaMsEf%gprJ6GBcRZ5>~U3o$TW5KaZEQk%xK zB${~A=tge_FocneV=^1=r$-ixN=gVzO^8TIi%LpNONod|>kyX~7Cax8)-^dMHDeQ#7?l(q zmlzxNY-&r;JV3xyY_*F%j{xnY*l?FQ+6SB3W@IXG>y4lzT;8dDMv1 zh{T|*OA~wv%K9NTDLN)HJ=UXM+Gm|ePDyGP7q2j)l2W4o>q}OU)U*^eAvIWL*$%T# zUruIB7u72%sl(-cR)FAhxp_=V)(sP+*)Wm6&&qq7~xC8c&vj0y_-L;eSU3+8)R zWL#QmP-Z0xRwrpwp*y7~#;Lk7Vd-h@%4WFqJuAw%w4{h2&l44s8kLaTE+H-Jq~p}2 zl(fuUwptO)qht{WGa>tNTvAxO)OM-=Rq-mVa#DPJP}UEbw+!?AU4s74iI^@iQ89^~GIyCJnJu?UJR-YF zJQ6IV|JhS0sJO(UsWHKJtbu2IZIksiCLuB=T6%rLE+^sgJ~k=2Lu|3Q#IUXr3Gu}` zl?v`sVq&$NOIvL-F)gA?=2kgm>#!11il(I`C1!LxrOO7pozi79YeH;fTx`Z+uo?wr zyDTQHy}F&A5Eh$MH0xLgn2@A{3vRQ8ZJ!h$mk^N{7VI-hmVP927afrn5sWS@wPUq>m5{JbC9}H4_Ay<2vPG4Zl>eKoFd@^^;^H%Rms?jxv(4B9 zYe(4SI(T^>n-m|B7+WkUB{r-}SX4^aXpZAKLqV zImKDYi%bgkMVGdjL8Ic5m2u|w(vxQezx*^2F>asw7tfj*=r7Jj$0Vn!JsDa5zk&o` zH-CsdE+JWsN{;{I@0k&1+&QaH{EI+gQSza~rOh91fBE6OiK2r3>JI9F>U?SYKf+|z zldM*Ir7Euvwy`lQ78u9?XR9{xor?Ikic=#S^UG*gn2yJqhGcvh_nw(88? zAI}C)1>4Kz{U6U?&L!m^78{k|^T!aEYExKhT&&L@PhP(K&nn~PbBS@OX)#fkwtsc~ zrL*!hA}#2zg2hC4j!214Em^vBiAM#FiI2|MWCoAX-zTSeZ)NWPc$ds4iPRwm{qgkW z^k#2p|EH-0JJY1-OWVJ=L9i>yyjS*KC9A6m_B`rJrJeZ zOH!jd_+$$f;q{hUG(I9SHSE%%*QgK~$A2Fz^Zj@g0VAVQeXb&4R_+J0FetNFW1=%! za^^1c$E?6v?eS8mzdn7XPsrXsWJ_23=$K9s@mf$!*yXsA5>sOmQ`1xb_}z#hE;%`= zn2~GtoBhSlm-?V=F-2>!G0|bsQ7IXln5eL<8XMLr+?dK(E;Tjmx%jxqpsXL-1uIF$ zCfH?!MMRr(lq#9IyW9veUQ|~dSy)CtmM!>SREsOkGh=ESta$Cy(vpKRBTkDq#=bl} zNJ&*+BmSx|uAFkkl{;q^rQfa`W!|Do>Ee$DW%X~#noP{)w~%pd@ArpI)SiRkcWJ!3FzbYf~yf)X&*ymFLP;{*!M_+u{b|LR65N$F-(!A;hs zrk}C#N-!?AeOmV8%%oo#UPZ^G`ego`5MA0Q`{QNZ(1;~TUlvubQRZoHjS@kbU$YHq zQli3r{w%SXVJ}S{OBOdH>RO^y@zQ_%eifHqzT|%d%}RR4$oFajUQW;DeQ=Us_7sy6 z7H`ZDl=%Qzw{D-@AtvaLzhCYv+INU<7xY)>6XH9>BxG#efPK*fp zv-25mFP&Yw_iJQawDqR=n9KXW3@?p|sqKST z8P+~IBC12i=JIb@h55fO%qVtc*rjVQ&oU0KqNj~Wj`PVDQ2C{&LG@hnH3%gRj-#N@Q?alarF-Gd9^mTej3Ahoz^-MF#~} zTvBaklA)SD{vXx|8q90W<*)Pi;H>IBJAaZZ1F|L%d?`L;!@+R!=$Fi6}>d- z3Lg4gMZildE*UjTN0=C_Si${OTxmuU6Q6o%do{tknvf+Lx+PpbxQdG;B{eM~F}Nz8 zvA>E-E+r_K0c|pd7Fh?`u2ls)Tj~po4VL(&&6Q>N%O_1of>U^#Ke^I~D$VUPw%Jbq zRdHlXR4~dmDalb+Qup7#{MpnjGCrb1Ov%X1ol#<(VSq7X#`eE12rhbtr5M%)T}8rz zw@J;|Tt(o_y3#o{SVJytvt1Qy87MwJ;z~pQuX9DsNV>)vz9dG685YM`vojCvRHAs+ zmtciYh=_|1`tN57PEmsM)pP@>%lrQuBI|X16+zM>VtuaS9$~?^pFhWB?y^5pL}ZG! zfTEouQmsRW1z)7W`gVE$_aU$J1BN+fV=7w4?*HdXQ?m}~$(OeOKi665P7M10xh5eZ zHqJu7O~$&LvWjY-l(EUm`QY?4#a{|8?JfliE}pc@*!=%QmeDY;w8_{%&+KejnA#~S zwNthj;$!@+EIKLpmP=1b^!dwkVFphA_+~jTAvlIgxO9{)xLahayoLnUmo2nf`<98O zP)RB2*;mE?JGlPYBvAjKvHQ!rW}Xi-l1VWs>3Vse?SemDpSHrNNu`-{N5&ZeC0Zo< z`?dDV7hT@}O(d5i{+nQ$icwfbpZgaf<(n0dOWSNgqJn)@(aeFb+%t9!!{=`TMOtQ5 z6p6t;I;>qvyOh5Pf2sfan?RRt+BqUNDKXpORb6x`CD~Jz{jy7wf2;Aa{vO-m^7F<- zMTJEMhxJ8El`Y{fDOaB8s;+hURfWqI$A4v0@b7g+MOxIGE6HD*gWqHPK`gla`x|Gh zgN6m?16Lb1IA#jE+VByn31R-K75o!!oAA!QWxw!G>P_|x3~QI%F8fm9pVhO>SDM+9 z@jy)c<^6xX88ZIpX^Wn0Y~e1qqhOzubsUT_A@$Ps>cWPZ zx^xK6Upi!81mkP z9C-xCc~;2&XCujIEgDPqh_2!?wc+otxKyFDSGq?!|NT|}-G;N?hV86~c8>Xfw7rLa zV@Z4eLCIA zd+)vX-rJMc|E2FQA~Rn;;DKZn(e)|frHyovk&%&+k<;+G9gKCx!dcy2I>aX6(QJIg zqH$4ZHYU&Qg{Imj)UQ_ERp?QTpW!)Y#qpb!*NBi1e@JgucKM#@!;PEaRcN6#6N{o+N=&VL*;G%H5-gGc-nQl#)9 zfF4DKz<=>}=YwINMUtJ&6nT^HY0Rax626ewKLqs0J@K9*eBtAg`cC(9D$NQcHSV~r zU2H6GOHymP7zobE@0#+wQdUig@VPAq?DurQ?$SS5>hg2| z;fCl=Y@@R~noycnM^?`4Y}i4xufw&6P%sAiIDF!AsspLM3i1gP5ApyM%PbfkJzTc8`!pQBTWHH|Mr1Z1pP{ANWo z=1n+pRVkyx9KdY(Q~$KJ`Q4e6w~+${OgUskpM<-|CK2>o$@TvpW8BQo_v3X1ew2E3PH|% zV+uR7x;aUj$8dGIAf%y=-F>5QTFpRD_Q}a{YZk$k zM7Eb4cgixoRQl=Vof3-xD!INlWw^4I`mczmR|$Q%Tl&VbjZp?+jaQ!F%zB=szv!HE zYIh6+v1v;)CwN++M@XZpDgJ$D!vBSkO@dUN@X2GH|C&zYH;*GZyoV&si=ksj9r9^Bx z7@>1}_Rw?Z^}9IV2UEJeQrwGDdDQwap^ZpH#vtAqVWR8_6Nr(L3B66 zH+-_RqPw-y9hxaUr-L>zL8@K+rij#D#iHiVeDZHz!lIT`g%k`w%cz~1iqscV|6Qbi zkSf6qpT*czhwm+seioC2oSWk=J%yAte&4&6pvdvy#5b(AYrP2q{f@@4?Nxnc1;f*uhG4Z2pu_4K9%u>s|u-iB)Puni@u39))eO*=Vm$doE1#e1na#qVA6AmADF z{pZeOa>5#h-nS2sd+t(H>h7Qm#ty!6-35S{pwfQslG=LWd=@@;%>mD9s$%-yB~NNp zzc^-9^WXQ%Xw1p#zE7h|pO^Z(0k{o`{oIhKj$>lU9LeOmAzP}4U7NC>yQD7qY=p*~ z>Ku1a%R=+B=DiC9VYA3w{N5#xrp^uN(x6$(H2}$RL$1^VAg-iOcNjARJM4V#lSPiZ zhD>iI`bK~N!egUN3|>Ha!qjbvrW#u&dSa2=IG*pj`5oT%WJ!;sY;^~;ui*HJkf!G z4)~y`(tk!1aj3slajCyH**AB&q3ORXAfa?Gsj&a91nJS6c1^C&3Zmae)QK6#ny>Sl>MeC%X&N?^``c-vI_JzC+TeY#-q%+GI^Jc zHY{2AtW1`O!EFhBBd}_GB=Uh_V>ROvK|6Q&N#r8 zhHa? zJG%LAp81qRPMsm2Y$8eL;xzoYeX=wYB$HfU@pDRAGK90y=awX#c7lTl1>^U&^a;oM z3mm!m_~r|kw?SACC43dbJ?6JZ$gqXci$l^Y7?e8q1xu|o3b{q zWwsP?Ws*sI9X|I10vBJ`WHVR@;;$OT_B!<+KTvWot0D@=$d-PrVPhFeuG96~p8_^I^C zpm%mWVAGo%E9$YFBk{E>a-^E5#t@I&l7;I%OU+75cU{t=gFK6pV;OeJm8y}lH)l{S znZiCRH&b_1u3^zRPQmgl7iut4fm}!{^mkjjyQ14&_B*NYo2Elb1kW}q#q}gdZC4zR z2C^P_I-hsLu+PNcV#Gwo;@; ziFW>N$r8p$ar6@Pc?H2INPTXJo7A{lxmJ{(>Ra`#)GoCneqcV*DS9^`I4h7l1u zup2&E5#uw4aFdM$|Jfx-F&oC$ephq?*Bge|l(VsOcO1#ew^S*m##Wtj`tJ(hL9GB0 zR^_@iY3k4AlnH%m$_tY0TZ|kxWJ=={4o49;U<_x9NeVkFjoup|IM%9|DYm%SLw0lb ztr<_o#~kIr1(cGQ=I%yTwdyk;p2{DGs2e>cTdt(H=m{_d9AwKVdP5-MedR)BSSCo&tqcPjv0i@EGe&2v@r zyLG>Hp6TIXkpY`xS%G&0&@C{_DVrV9AuzeS>EKI;x;p9HTy-)Q6Wo~j*0b4gmTQGn z-T!{=icNX%j_I8aCcfe!woc9r47<)bX2B4Aun6?ebR~q9+Kf8;?Xqev*JO+h`7X8) z-~nh;Vg%EiPmY@lT+V3sU*0>D>Frcqe5WdIUY!s5pXd?pTg$C?(5=ZAZx=S#%LwJo zu@^4$M2mp z__n;N#@%LQHjC)=m6QRwocM()CycY<#C}9+2&Cd+zpjQ z%#pw{Mpr{_FBespLfBgTKG>QG$(nV#wA_K*DpYrxZDYCM zU0D%j)jVD`trQ^+7`61ispS)(A8^C0c!NBJzALMm z+2UgMJI&Ah{^ zcXPs3)X;Moo8eB)imI+3G}BC!WgyKJ=UMVJwS86nER*J}=Wam7tk*2f3jW~60%{HB zeq&}`GxM#ixA0|U{j6Z6NQkG`GPq^f(3X_eTat3zfU0%PQhL1@LNG4kcV#IJc8(On8q2p5S z5%0U2H-by`d!K>38Imt^YlQbfsBlXiS5j^p+q(`%>OIj6x8nOg?OvFrad<8GeMh$e zR;t}S>y+SRGk$F#KWK1oYV7KHzA&^XOL23Z13i7T(Tt8ew5^ucQO$$g{k{;aJr2N} zEAyx2$rmX}IxT};zm=a5CqORci!(NpuEC2HB z3!PEe?Z%@2kP9f(HTdvkDS5b#R;egAa8|jpL^9=zos6PWUMqg{H*PX0d~QgHkVp1P zs#bP8r$a79pwGc><)Ms7AUn_Ec~_5z?#k1Lv*K(%9b~<+dGVQgm%jHqBy0u^8?6_>$erZ?+w5YXO&%gDk!FXuS++J{`Ur3@3Uaeg-hI(>%Bn+ ztp8B;|B8A{y5NS{m(i{A51Pw~ItM`Eb5CG({7vk^b>&)X0m;JRTDoAuHAE7Lq7*C z>_+%@(+KwIy=!|r zI@Ax**Gx83lkUrp-K8D(B}{iI z_XCjJ`RNGYp1o6N$V?Q17%_g=3Vedp1}>q9-?aj-On%&t)vNah8y`KZgeqy}x@Wb+ zM1wDfU5Ay_b@0ehE(O#S@DW?^@|le6-Mb3)ZR48O-bJ8`3oflhs(GUwKy8%Ib!rg5 zSxZ-DPdk+?aZuwv>GNKZ;Asz-Mc*5it^~mI`|n)%cV|`%ui|&Lu)R8veT=D}4Bp-7Ab2VPL&-~?7~uu|^!ve3BDD7gpsfz;gqd2^ zHv_O_ePe0TkQpT@JrJS%(V2m`V^@4PW>(? z;^l7cuIOhuE)tC881y8I(teiXE(iVDsr@vxN>>17O^}8MS3{y8xASzFry;32IMIjA z-t6j9FLK52sto1qoF~h%l${(6DaAfaPW0Olse!M`o0vovMz zn%4{aU7dft51|rHuGB^e^el~GHMj0If9fo0eYvkVP+gH6^|>ONH|I{L8aKfY8oBXv zzpBGb20%gnk0u7C4JWjG7+jKn5HO^8#?^7w$j}|EZpXO z+z{L8LDrvl&bWA>xs*}H^G%2Q7L!3$I+bVfO^BV>V{zbzbWjb`$7?YT@OYYW=9as8KzI0m;D<4tR{@ zpG{Wrusg@}x4rF)&plazE1(!#7v6%aio5}VBs_gZAliTok4LJ{XKqVm&~yX_roQ9>pUA9}LcGVxhahbbD!}z^6X%a^|j3fJCF-8)e2T+e!mJVqdlaM1|J!6=%yMR&_cjXt*t0P z?XCM8D#dH?X@xOI27cA!?d--!C76p~Epy%>qrboBzjsI;&LfeP^7!#IeD0o458eA( z8y$JxS&#TxvDuxO0U)k!_fF9|vfnHnm-5arP{AIkJD5EAx&36(zZs0aKbK5U^!dntP#p)C=x>x{%q2rwY|!63Y(oS1!)9zKDVh5K6#SW`<~j^+g!MNK0{DZ zue)bS6yCJfpb`D*MWXkE0)Wj1>i~B}^M>+|?!pz=>~gAyDAdf=)qOX$B2CSC*}c@; z%9uM2jw~BbTVmg=TWp>V`uxvgmKtXO-yw)#>wrqk*gF%_$y}L?5sJ70e$4RT zFf7C|p#6>H^zURyKh!n(o4~aXWG2R}ldP(%8In;7>bYM_1gESO56)^c>)WOWKYtJN z>W@Er^fU2BdacNM0eE`<2bpU3dRFY5Pfo{(#HY{jl+Okyf9S=V{Wot8H_K@c{Z_2i zVC+?soNT-%(CLSnruBmd`s% z`ur)&<2B}K_43_zzyIyGdU@ys(LLaSoUY}B6) z*`sn#4vK=B7X1Ue1YLgq)a&ft&!0+y2r}sNcD&qK29a|V06xE(e5I$qK7ZO=u1w6? zBzTP@q*Pf?wy4LG$NX4*M&=t06ejm5B(=|zt+(tP4)nz3uqZD(li%!9F_cevq>G1s z=tCLR`SN4?+0d{4KH4xTJJo#sng?tz&G9M?!gF-GE$CZj3$cBchF1$|Q1(@~3#k~c z8Ke1X+~0b=)KXy=$O9?9SU@1&jTnpxdxt%vPG68zb$z4Tk@mo!Xof}Wy+M8p56D$> zb~V_~5UM$5eTO{`CQI4v+7i?4b}?eiqc~WX=iNW*{_VG`szw@WF)hyL7dXG);s=E6 zf7{3LlE*!YIVimc{EKIul3SO9i+x!iEU`Y9yANi?1Om-NWZ0A9Zs;;TZ z>Ov5&-^%}rs{{pO#o~kLN3X>9imh6TmvaQobfXWRjpIijedOPb_}y^-$2Qm>ZG`Y2 zZHN{f6oyPs`37{hIaA`-blUEguZt7r;sN70AMzi}IVqkEM&onz8Gkh&?-%F(yF0jG zr2QA-LQY}n)4lj{@Qs~)tl6-D1&IW~Lt?tDcYVaJl8H{T?GQp8os^Wt>?;IN0U=a% zq2E{Zo;hd;l;UuKQanc$`)YFFSpH&XmuveF8XVJ6pN0f-#eg4x#!m=&YGV=tJ|p0Z zJm3&2IUEiSFsyr45~*A-%hUbxl;XWNw?}>cLwVjze?6Y^Rhq^QVNQpMambO=HYO29 z{jWq7YRP#%MtEZ+`YT?O>bW%RO+1%sFK8_jGPkFI|!-2(! zuGLK2*GUAT_k**+BbVr%AXjtqPAgU(E$8k1%^iiOB zOp~vRt3#-yUJP|a;uL&7d!c&?bXE>KoFQz&fXp>bSx}Gic-m_3rb`fIt1W2`=)}nITSyrJs+P}r{e%W!l0rWH zsYyGhyn9~sfqr>Z@_ z7E)RCN&aqv;zn_<;W~XaI60lYg)eU%Gp3R4USyg#E$Rv$dIz|gQlNbZ;C z{Sqz~I&&%1f0!mBMi@y8fz}I~u#U8R<8WW7F{GwlJ ztn}yNVhZ@Jd0|eQnBFE$k)|r?9d}L3;=4Rnp_?J<8=hIY*32Z$)-P!t165qHcgM-F zX;IuGInGn%sDX(D00Ju^om~;zG@gSpLA!H$EC;eM|M_M9`rYSUF%j-O zI2|0%q zL!5c3wYSvbh`8!lNc_?QEMo=2TyLhkbfPdwP`{cFhbroYYHk(SFSugHEv&+PW%9xo z>Rtptqz%n~NB6$qasrzVb|{QyaE<4hoNqOQ#xrJ}Q?20l;*qIw*vwL2?x@?R#VK>V zoN(EaaxX{4mG@Y z!PtzO`#^QTjvvRQuu0IIs&xl!CWf?vrOk+zysGWt*kasiK>F6j7V21~q_?*uAjy%Q zGJdj^sB2!{R~Getpgw=P64d8U7lAWZ-VZv6n84S@-UJhkHOppPkffm!-R}`FA-2^Ryh4pdLZ5i4>_( z5kG>X|JW$qzVKLNDa3sA@y9;`E9A9!qKrK!OsO=t&Ej-1g@d0y$51J{alO))5HBa6AF4p(3xxzQ*hf$7Mlk*ow)pxC$RzLG0(5lc3xUjSgN> z=MjIIS1TOgY~N}>R&zpFy8PD{u(XmThnS1K^7UY-MtIDZ!?SA@ z&e~^XzhRHa#^W+nKYFbK(L+JesqIT(y!MOU1uOZ*sLQHz0E<=HpI8f|1MEI@u35~) zA#2G91>iE+d;!ZZgk7$j$Wp_OdAIN4^{TEn{JN?y5RWWTBLfD#wXs5-MfNA44*#Udh+zM&wuvC&pX{7ugD%8j%|m^z>aB`Edu5I{OjUMU5NxGhiCJ3 z(|!Tv<6L8O7z^KoC=HKkZZep9^z;Y;0o_I>?f6al=(0-VvP>A6%PQH~OHMJn{sb{b z@kx}lwlx!`+&*KMc`*QW_Qzwp@cU(3bzh8Wv)veI!(gK3+7OuVS7^oAtr7*cd@SzF zaviV^N!RDbTxt$jBo^q+#8~3csCr=g)y}KXnI2E+!QbW!Ip*oNp;3fdZ>P~yE_AYx zMV(XRe&_NPSja}M)#YOm#)!H6AC{G=G{1bMjzx%ko%cPJcY%1zy zMswH%0M9!(v@Q6uTFlGhV1U$=9ZCP0ZnZ~=_rtdD!4pm-Y^aSK&#KRA0aooeLP);A z2bbF0S|#(1qkivvhv~39eD?mlap8whyKh{^FPDh73DKdb!NuUDs*xnQeQ#h`OK=lX zMsx&1t>(V_8^bKuTZBLB}z1B8DMtm_~APSY_*IF``k^zjHKryaH>(GO+6?qIbZ zg2TG?YS5cjZWjI!eh{Nas8W<)Bk(Q{;qrPQ(Y|WB8y*wb^@p&l;oF_Vhbozdi{Z5< z^<&@zp;$3}fE`v_E5Cg3JLPjx$wJbwst;`Lk#01eJ)l9-G3#d?5XZ5xCsc%1KN?Em zd%Qnmq@<((hQ~k={(6i!FrEXKd!uLCRS+Jg3WJoTZx~0@p9#gpE`Nh`-7ajD%Nd;7 z@jkMrpmIK8Ym=#o2DGz!rUD}3uxQQ@jhd__z{^6~tn+5X;mh_6SNkxOIU6??6le>p z?G4e3V5(gs`5$=wK;+x%bn;XzG+m zc}ckmMHiB26?@r1&8mC>|1}+tkK-4VFAR^FhZ5xorEv!GpN)$xKBP|Vg=a(W0XPA< z8xTU4hyt2Z36m6snJ#zg8(41%eF7X8o$?B(X3PqpAr_#_aKnzhC;+-KNB<~|0C~5k zCnY-)dey{5u+5?DR5SNa=`o`>GqwR#v}7a8if#-%Taek6cZCTYEbts=dH9-ra?Typ zCx6gQTT$DnrbZ>7TgoC;2_5yE=BfQKpKw9;CBrU)MO_2yhp!!FUr8L2=QCRQJ$w8C z)<(%C=h&oi?J3&E-Wgp}f;Yy*T+dkyr567Oq+%x}O(1A2 z`}Qft%4aeW#hRQ%4ptow))c4h%1dN5TKbo2$bx_@g!;XJ57JHnqYFqd^1}jOjF%4% ztc9NcXnNdx^5n_Sfs?1+|7u5}BP|skt}=SF7)~4Xj1cPt6oKE8?aY{F!KZLs$dWSC z2PyM-`xvJ5SwU%R9oPhI(9r$ z=Nbq=o}E&}?35JtJttH#_nI+L^Lc`)MB)82XI);ILU)2Ccg+yfFP!i+RUZwBM zZMqlGO%HQcq-?WAl|bLP6^}t2lS10t$U!{Pj%Y;Gt03EQd!s-HHbLGd${3UecUwDL zqyy!=#6iW#9yTku)EnUwSMRNe~S)-$GF|~-p@uhv;_Y8rIc_kB6Dg~5?+Xv_3M^vy0$Q0#^ zxfdS9VIM;}q2laHVx!)numxZD?u&PiKY#aR>mABSkGH;fxAocQ?}kMeryn3Eb{K#@49Ihd$R%MEI@e+jOt!HUg`C~iy#j&a zc~}B>4%UPlZ1H2|gdP5>1#B$3EHJMOXqG@d4N(v|5Id$3s(REf5SF8khz*iMR>qCPs1cIH8^x}M0}k_^aB8OmYVaH zfkW}cr^v7a9%dmrdvmU3AA4cM1yBLTu;4bwG>C}SFz$hp?>SG8ynN2ms>1-3oT*}9 z3PSMF$imx8J;<oV7wEpNg5XrI)R&rQVa=vBadrwC5T$-=$rmj30;}M+8xHojW>SV<@ z7!z=N%42Cblv$hy(^eH{;f|LHa3)Sx#UoY)B#xv24#`NuAtf(Ft&z=(rG<&?b!4~K zX)lzS&AXVVe72S)q~kO%Le=5TRBPWFW|>9}VI9DH2-KI3QSjpO*k9+wlzT=Vg6b59 zc(dr?(77{R=nJo62sB}Z-+)=mxIl2SZKL?Ptb|a}J+6sQ53fcNZt*#o+r=PUfxu@u z)R+*DBxIV!Q2)7|WT3yy)=97sw3r|eom6?HplsVJd0uo%iBi5nA&p(8wlt(#SBo!A zr?Swl!&ogiG%p}DxE`oB)kCbN>#B^~+NLTm=7atYjEA@^U)o;0+uOCWbZCq&vD8OU zF6N4|v0^5kd)2w3ueLc39?jHg=qR9n(qq3l8MwS!A_Zht=Nwh{%D0_sz2UnCY}d0} z6Nk2dHld7&=9N?;M5seE%vf)gBpNWe1U;(FzqvzIlHY2Oy2a5DEl1P0FziE%6frU=?PAY-^ZO zNZ+y=uLtI=s$`gGzzr^~N3*L@GpUeF)g(!KChMzpF;X$;5jzHbG8DEHPJ<`$hYk^M$yJbH8)z(OHG<=*shFopv+;g|FJp#3HnDIn!}y{EB>V zm28hnr=HKQzb>TAX~fT+m*7cOvvu{Mm7qoVnW(lFFn3t-=1e?*omd6F?IohKWfsnt zCCl~fIz*eAgs@&SXpypJ4f5$Rajt;p2bezPTWAH6k37{Pgw$=)#>f&{v6-J6OtZl@ z8@E|~ZfW}I3?m?TbEME4M(?Wvo}3e7EGXFba9lxMn%AAAAmlA8563b8QrZZxHgAF; zOccsxWo%-S=%^OjTxr`I$GxUe8RSqdAqb+DxaE`tVkSaJf;EsAFJn(TBb>gU*-P7d z3Q^^;T~-}rC?FfFDk6+ZttrpB)5!s70f%AS>KbYcj~hXT?IlX`)4^DZ_Gs)->Jl_olttCLkvLx-&vS+;$7@ zG*N(tT_-(uaBm#r8oF`>fen4=ebqBfzd^rk%q~I+4=%*|wqKgCFHx8j>q5XIMuo0p z`w!i9LNq^Y+QK!2J zLf4q)QzML_sEkymWTBv1>K6msw0bGrNfX>C56X&F1JvF6Zol38 z8uicF>5eWi^n+{}9}sRtlD06z*{x z4s@vj4xSb0B?hbRTdrxAY4OA&(v=K=0hirzDFKnscNl>wf$azS#}pC^+N%s%u#d%J z;7P$ABWfsA0qv#?YpgQWiFKZ#tSP-X@0vsTIzuQ;H}#%8K6^EAugVjnaV~BWpUsW4 zFqm;rm9CijjNOX2QRLGO2j@WJn0-`M%@q{Cn3;X?8g3kt*4 zm}iG;xYGLdVo)S1ra|`3S|vr<@hq0uG<=6wRe7L(RJ$oXUju?5#4S(*uX0U2Ammtq zR*cs8e7)T~K9{=KA?xT2(?LCNKN2Xh{p0hS+PphBJ|6U7!NUhITu?cqxuG zG4YBfgQ+IA@+>F8S7mA_BPEr@xJubHZl1JaNmL2_Yk>Ovih=d?CPS$wj3 zsI|DMTKhVs#pqkr4&9iDA&UjwANS3Kj%1BseW22kOCHEX@wG8oc188sxPNVqFj4Ql z9A|3^$Z~XQT+)#`ii+I7Sr~Bj1uFy2_ygP3jrU)^<;ef&(&={CgFAr_9z)0N+4E}K z1hxbpHyP$9!exTu>TBOD+!x`PVEXv8&wj3Bio=Q;uCbLFjireL9Z2~yt>xc#CwsfD zJe}mzv1Van`I>#wDf#b=1P*HxUvCQ&OuPDUV!-9}677%0kb$X_&&IPW+wfkAEad7* z<@KnyiQM{p(2KStUUJ|f)GH1!<)drHezQxm6ar-5XHxWELLuIbL?=dE51U-Cg2@x2 z^nmygfsJ<#1wFcf7o7EiLLhf^PDYQ;4J47k^h+%Xk z62&Zjzfh9%&Q+J=4I!HTp3A_@)Qw<_6yVBSUX;5zrs*p?3SD<-#p#%$JEKjNMGom) zK6$hiy;T0gVL+Y3CK)i?Ry4IUeIy5SWhIS1Dj^}jqf9^K3xdq?`19!6dKz6%wxa8C zbTIit`kzJD)@R8T9gjavu2jHQD&R?qOkf`;xLXNss>b6~jjaTCE5S{rKTdGB65Oo> zHrfY;I(A(LPVeK-z)n4p(5f0$YvQ=$xqqbyjgb-G56s}zEiO4tybr~<<} zBolw2VT1X)6}XGU&?a4f-YcG-&kc>9Y}se)Q#(q>e1X(3-_GpPsIbh0iEsI_Yfr{1fbE66A>l9p7br`F{(|@yB>zvI;KX-5S=BadrV3=jU55u;?&5IGMeiJ^v1yTV72ZOv0DeEuTMq5x!JydpLYE;^x9kzxzn|DOzer zQpSQ+1?5CsyM)4WzZ{=D{?zqPv6N(nk&LNEu-KQ$B7Ie!zB0$5uK-?hqhTNS(1;xe zr~@N$;2;-h`=*U%RJzoqOYMPmr0v%McgE=9E-j!h;$lm?lA9UfUSD=|w@0N@XtI!I z!OO`oc4Oi(v?l?^LWn~OEUi9=R|i~0>~-#PMtP$^B;)Lm7IXm(va5u<%$S=YyZ-pu z_a{%kc=~iRd;@ep>bBedm6PrtAH&AzmwP!jBqA~4^jrr~-72*xO~Lk9zlupCLig4D z-g%k>2=Ek>I!|G>fRaw#kqsMeOCUbr+!NvW_ol>h|Nda14Qwtw4brK7bcb&@ob6-7 z*RUD$6p#Uz+N@0B8?n_8uG#6ZPq?9s=?!u0;~Gl716{otOR8QG^WVw4oX!bDFuQIV zl6sgF5DAgIR^ytuvo+Q*W89C7pkcVJzPT8rs|I*L*zP`z zYM<5KNmI2Edt5T`uziS88V<0%@T`|DbOElF=nzdt5X+;1_2e$m5Ap(-<}ubV6Rb7% ztnik?f1vHKAp2hU<@khkUltg;*sO`jgq4#R7-CJ%LSj!-*p)j8v={xs21CS9&Z~mB zU}nOeHTF;t4_5fc<|xzTeamWVx>G*>(Epj~Qq7b2Sz43r9ap(Tp9@kCI~PVaXku2u zjhN=3>C6SuU=vNF??TB+pTuMLplq|5<2iS?V4kp1T4iZ&E+*>mF8W*tT^`)CcWV% zg^(u1vju0t72S20N21K=co$Q%lO~VJoFMCAHgNFH<0oOV!~v`Y##1jp13R#%I7~)x z7oMT{?FPH7_=L-fdOavzSj6*g|0TcS;Ej#Gsr*Et;~hHp4#jD_Rc!dCS&K>r1{(uT zX~%V5X5+oL>v+Psx@@EFzuj?vfYK%)NJ}dhhpxJg>j_x`ac2<4f_aoUrBJR`rYsGx zOmoW9Aq*K$vsiQq-q=+kE7G-@W@9n^+cI=XGzP+U2Yu$NLCKPpIw|5P6y_1Lt!lUe z#8~L76GL`V_RVEmBOWx>OPiZvMCdyPY%#@rI^5)s$TyP?;$m%0=ltn@ieApUM2SCs z;b;`CsJ9_Xex1~R4f@J%DjOAj-mt?_5S8u~#yt>W->*2$6RV9sI++d1^PDX@aw<7( zet5bN8q@A`eO>m%_GE(@7LwwNV@7T~yeN`&Ln{c&gmk5CX&72sR?gn-@2OH&f3A4_ z0&%BG(@sma?DRuY79<@H#j|iy@YVb>P>5}j) z+^IT>!e5NdtDr>y6h-=%+8&EGzbzH~)9Hm!s`{`6Ck87}vm@9HYXYZ@$8Ty`ZU>b>w7 zE3J67_v*Pz%6DHMKI{ST zaQyUe{P^===|=`XX-B#DRxbUSJx;aDZ2=6*Z&AQwi`*Yi6uR7;(AXo^fq`tI9h*@B zwZF5FzQj-j(|t31kI)fUh8$!}^8HLl??*hFc!@o+&h-5Ar=&bO04jGh^%3xy<5~_t z0}#tjRoZ*2s_%@ka>|yt9|lk3Cg-Nu)!Le~(a;XQnLAiXNK$7iy)J)PwNN|2Wv zl$2*Yfz~sldsH~(X2Z?F`>cRWf`{|-VrMYH`tX5XeZe667$cI<2AjaWG4@mzLxc`9 zOiCXVQ{-LJ@OoRolVTNLLP7G@urO5R>a$OOzNsH-0@XTvc93Nt08Ur8MAPk4bx0MA zYp*QXKczk3Ht)bfH%_r-wSTbv_TT`UbRs60ZynVvu7vXaW8L6suoIK_n6hr_ha~V( zy)%=9&Z|rDsX&^|m09PGyiz%wytx=KzCtW%h-DURu;j^OmZKnl$lW$2Wafn9kD2b! zTnxBDD!~?_HSmSaq&T4tx-7^uY)IAd`m6P}$yg+i#d7~+`=LGKfv=f+eHYwfvU7&m zwu`9|TRBI1TLPJtj*$%_`--8lR$yniwL0yOSOBo}23Nj|_>D5=0|YggDLF3=o*(X4 zNp)T{>Jz~3Hw#9#8wMGZJZ`iFhna9eFXf%|sZCHQHM??0YLRq?nvoqervz5lx7bTkFxUO!1P z%=c#J;H}RHAqCx&;Wr!u-D6$*oRc0~kW4(_#K4>^tLP$QGe*}%j4J3%D0M_b6sO|D zIWo>FaZ0rJcHb_fY1I*wy|=7?F@20osq1x$$?BmgG48^--9)M_P)wJPhX^@t4uz9?l|7LGjcH*DQkp1?->&N(K z9m-npYv4i}PXMPlVT78(lva!m=G3`&Le06aW({ZzRO%W?Zq$lQc@KF^K>9qWmSt5p zXww`P9lC?X2*a7^3t}Pzy^EEd2Sp|Y83MxDa?K@t(e#y>deCkbsIeH>t{Ji&cD}zB z0+-W7nonT82#GPL9qe|@&sjgVww`+J-U30OjuGL%h0TKF=?q~nalj7M{Jnsf&^7^O z0o6ye+X@s+Kd4f$iPzpfe>Ex2%^P~O44I9EPjgr)R1sF!FR`Qi(U10ZZnZO?sv6?l zA~j&YfL*aT^|dG>OLgJ{h_IB|NP(*ZN2%JtX-BYxCLv+MMIW&@e%FArWJGHa%&Ody z^V`Z7YeBU}BolR}R&bxnG>O!q2orzc^r}a7m6E4S)JEH<`Nvo@fKLr~!s+_`s#Vs|mE;It%SONwyNcnoxVOa5XB+Y70lZ6j;^8N`{ zYdh>1zx=eFR$I`Aro(b#6rJ4?w3(W5nbgjObS6{+&6cl}r6M(Y-@+eEkj-m%?H3n3 zIb!G**%bx3F&yE?assa zOTj_sd3JL8H5*l3g)RCTM&;%Tp>Q}#`>4kVKBX>bFCw?T#o!3 zHsWygjtHt&t>J1dJO$4NY4M7C68K8kbGCZVcfOXQCJzhsi?ee*zJ`R-R{l4m;k7o| z`}%lCHCy1Jc~i6 zFg>PGPQ8OY9_SH!ZQI7WQ`%Z)$ecUToxZyynozJKzGDPMj(96|8s$@L^v}iS>1#VH z=Ae1j>z31idF4Qq0e6TXeFWU!D4XcKuW6qB| zeQ?rRvpwSlvNIVUgzLn`m0+^@p3|l7+o;(x4!=#EiJ5{WSSafioX7fBH?N{LK0#>W zkyK72DNAL2OlWHe#L}YABK8stXBZYZf&`;yaX`T8nph)aK77t-?gtmdoSRo%MBwh< z*N6>-q6bip12#3#5X|F)O$By<=`_kUM$b#Njm|c6lFk=B5;u%dJR~Yzr9id z0oiTh2{>)d*%uvL4$$m^NdyZ3TC)L_>Q1<#sXSbfgcfCCavL6r8S-8UV;BNtChEZB z7`bC8%Z$zL>~!*YvZdZ))WnaLC}q7e*%fk7G2<*0rvqLgw-g~JPai5^8)=YRZ}K^2 zhecDu21%dn)>;?^(e}R9R_l0|2TcmCCRj}wu^x2 zyRVm@I3NaT?bIJ39-GTExJqsN`~E?9!pvt0eKO-#2q0{HWUP<@l9}%)@G6hdBJfNl z+zB?hg8&Uhxz3QuXp@%&GEUCJ31KM};+*qN3P@ZU0%cC(5SLnhO;>fAri?ArLa{K> zsd>yi8Bfeqw$Cap{FPisZLS4KEH`7=XY9H<{n2nV++}lW1|Bio*w5Sw&;3fT8VMZI zuIcqO1ZWKuRDGE^a*jgK)V%{vD(Re93Th`>X(5Ktld zGdzye(mWQ!7-*(g0ML?~nP7*BteGH&mKZDfQZJ&2U_AcxmqjsQalR-l%&0cP1v6@) zsgJ6GR69?cbO+|I{QB_l?c*RG_jRNpkuSdeK+kz;M zKp&Y>E+oa~EA!Z785keE%O#XMoFteij3NvyOX%tStM4Xt-y-7#t& zK0pmhdXGO34qhj9wY|@uYE>~ntmax9Qt^4o;7(Sqb~05hVC(9>3_`3qX{u%n%G4rn zH?PcLKLEZ82ezxBJ1o_`8KxDXClhWVx``h%<;af6)*+`bMnW^^J1#0iPb@fddNnLG z6m4$36JrkP(YeJ&GP^@Tk6opau;5Z)&}<|yxD<$LBg_vsK%>jDZ+&q;)R?1a$l$#k ze?35DnRlrW{OgggG-S*IseFcAlGz+&^pi+PB$o%SEKNNS`-Dk-RrAEB6X?{tUyT7E zp%j&7S+U7SeY6C=yFhTD-jPSQ$?NVXTUjFac%sLjXA$mE>yxogAA6;Ft#D%mL?QNe z@7EAjmsO93@M1xz{F5z*tkPgv&`5y`mI7|%zEXfvR7fnJW1xjsPT`+|ge+gk0sh$6 zu*X_XNazC6c*hVFx{Dz1P=eeM&@R9NeTd;#etY}KGn&&gn3ELotH&X&N{3&4;bfpMR(*LxJw;Xyd2 z7vssyebgJXdJ4NIp-!cXRyCEc@K6JHvS)A;xau(;>Uut!2Myd%DJ5G^m-L)uKAb=P zyrF8f;9UKQ=@ru!F%HDGY3 z)WXn57~{$y#w)-Nv)@sKm@b>nZ>I7(pUAExUXZmXkCNs|JKcUfE(-CX!N6+Z?%+UU zKwJBe=n33s7Sc8oh1g%W`KnF3r_rpwBC-l+qs0E{TxS|Y1xO(b5~}3L$ z`RumlXV5ja7j9I-Gb7)N0c{N*+autl0%JW=K)F=cn1nlRSw@VJPW|!b*z8cRtm2_= zUhOx$VENu$DjF%BQRm^wIB8EIhZ8Fq3@~A*oPfX-KVwAG$}dkAZrj0?^Je^r_Y|PI z-ACi;2^MZ~KlIn&tlXc$A$Rpsmwv?XCkHj@RxeAdOe+Yznh}pSs;-Be53!cfcjcRr z2|dj)vUjRp^~|-K;^+rG$VnXdOaTg&nskGAG;6;b*aO;bU(tUZbjK_%^1hdGNC8=x zB;u(`vgK*#!Iy#$Y&~>9G19|=&el9HmdAfEwh++3Gch&tK#+ymPzwp^7K7VpYQBOK zAKuHr3kn|C-nF!R_I!P;C=l6pIRb@`T|by<0F=yb&uD6zCNb)<{n!ss}^H7Gv@kL4*(v{v1~}A}i-V zeAc}Ch*8|E?U9$MkCZ60lM&OH%4-O9crbcu#gNcaXHE}I6nCyRREu7 zYKqP?qQqwBTPw3JCTKr5$;lx@R}|-0&)@=j@6EAFL5GdJ~1g{BBke%Zb|jdD(M+yG!G<^DSu`QeC)^G;Qm+?kb`ciPEvU6MB_F6 zc7N~ixhCqt-iz1I_c>%Lq3fY^O=YN(2<4%O462EGUX3$dUD3QHtCD!pPQk z30ivcNTfm<8t=#z{GMo94}>$cRcX04fDP5cLWyceKqQJGg2`{y-`nNUvlU=6+6rPU zwz!>#arR@Q#p75}In2P9=Xw;H9&}osV8|cl?Lv;&pZ&NTWxc!rBqYVI05~2vtCz(| zrx)3;Z$9-^i04A0-i{Wf&!2X=C|a+m!-^QT@2v?1)P33l$KgsN!jkFj7uexYH0K0C z9XxX!6BD$0$LJDQK z0n`!c$J}Y%;DrFE{5qtv+D7KiS^K#1xi7?3MH(t1T?p_Yo8G)wBUE9-O1n1-9al{) zPio|Fs@g&_q=};@&`+=gL9drMX%uj3fQzz;2{e%*zW=PZ2l7M_nfJTnUe^dLsx)R( z2#y3A=wUCB{i)kFgj!w$&Kt!rIs(y?=rpPNzOGT#)R}R%@c`T~z6_wSFkZOg?2cW> z$Z(D<_`u0lf^XiW2u*UhAs0g(nKZ zDxIt7YBwL_fepwK06WRH3*LEDHJ%)l1+uzjsl1o%#4+nm5A7Dm+%L_7-*JvN^f-3K zgJBlsp;g7Qs9P(dM(g<0VVvU%BV9%`jDFgl0S+T>NAsG8^Ysm4>M(~}Xdk>>T(x0= z$O-wfs$})dFd@OcwNsW6I0KXC&VnO$uML+o*mQu8kI95!rm_a25OOe|XxCTcxdTGo0Xq0)*TzmP;--1BYJ0c|1_FW=={;Z=6^tp!sHvwCb7|i8 z0cT2K2Uf}%vR+87TU(F33PyxnrRt;Ks^YZiV!w#6g42n5u*v!qR|Tteab%S<<6itZ z)2vA@81*U-O%pDQM4l0PL`0-sfQIFyR{2=u4>4GRz0XBFAD^Y6t4FV`0zul~#RU(& z5L{`(83Fe$OiN7|Wb?bo&-X(Tg4mL8>Or0f2Es)VRfO=uz}5?iT^wTr^(P;jS4$sL zIAqa7b{QTYxm)L(JVD@evN89x9J`vBsl%0`Bz_cLdA0$rTr?`WwvcdbgWwg)2m-^g zP}Xxy6%BdCIJC)nBWscecLKkdML6gTShgL5ze9mc{TljhsU9&mJ)D79N+#B1DNw_t z2nN#QvcXrju#EX>E z9Ud-qIt$j1WuzDFR-(tlj`M1sjGnB_Lb8O6YTouWkE-!_6+fB0T;3iJ z^ za=9Q?AP=O9x%U|dWpuE_^xo^;Dxl5gcJ=U}_}vuQW~TacLWq?6bM#pbUnkOpg^lt{aaWw~4@}w>Cqfov?3X35 z>6R;Dh%Z`{!fX+EgQqzLc& z%;ao;Wp`7=kAy);{wzws7NZqrjbE(J57i4IQDG!vkqWXMaA>7A!)+rGTCzRxLc~Vi zT4j~<2dk*5xGYxH0>k;Eoh_zubdi#FV#$74Md6d}vdHl)WLtA1UTPtN-~|zkH)0`> zTV>$WLLj%c2$XnfA;K%jENKj18_9XefTBDY&*x*sYk>=CvYOSBt-DKW+;ON_ElizL z3#e*V3yxxfrSxmv#lsb$V5EHts;t5~ukupx+J+9uwnaoX$Bpe;i3{QDD{?U6U8?gS zABJJIGl46vEmlG%7`+?PKvFuo)G~A~etk8wE6LR%Z0P)jP%yx6@>K~F&MZb`ShE-< zyqRG!`2=`Nl21i8g|B&fAd8Z&Zk^&R1Ue-Ta^W_|>}bO|g;E9U08&3JgvV}hST=l8 z56pN9Ct*6T?45^AtDnNeBLZC?k-a`on5W}plROzLJIw(-veNKn2@)7j;WRb38@SxE zwa)TPfL?8B7XlMCO?|qMV9luD(AnS|OFp1G^h_=kaeNM}ibXjgJ9DU%-SR*k>4>mY zvF2-g0hBlxqXyIq(WMnzg^F`nRr(Lp1@ZAoWB;_Psdd3pESf0(SY=G_NQGKTJs53s zg}C8vz@~9cJIHt_UKX8cFMq}MYb$U_(Q@}Mw(@-Q!_onXXr zSJ!CG9i2)pq5eT{!aKPs1_Wpdjx=RO^jaruwJyrFw)IB9ocRc?PyQdEh=9gbnd{RR zSl(;qA?s_4j@q`7-=go8j-%|ntqLrpTTpq0+Gc~uCuJ!w*H3gy$U{2jX6Ne;4`lD= z!NRS2q3fOr=ywcd>q;e=dq<`lw8tEscx8H3fSx*AipRiy7PgQiuIvt~o;1d_z2Iv0 zTRj%Makd4EY4wUkNK!xal7iKl)ycBeI5mB(Q`Rq)IHOY2P-uvt1`VNW9_qY=@|o;W zpn4j2)hi-JwHGSq1Yb;JEsy#x4_J)2g{^0f%Z8Cerh{pJI+iJLUCpWjf`DjEoNkGpxa;=kSKui0pfSQUdePkF z>A$9Yk)x7*23>^0rs8Qp%`y+l&@Lsb)XE&cbQQt!R}opZAU(u7ou@u`AtU}k`WP^_ zk<#haXrb4Jb=gA0o5C37=KeIdW zJON6`W@j>B9PWTpcYxL9w%Cya#1_3QsO{Fi7hQHOCLVnGf%nh=z z#ep8)zoc{4Zf@?R!Zbw}3kq~rkG$vCHQd)$up4a8)UQJy;w;LbSfT)t8DWU8d{zI&(5k(P7n6foRfotL zk2_FKyW!J*5Y9P^FWVf%{qAR!w3t1L|{Y)@DA1Wq?B$+$KOpqr${(X84q z1xjFs7_$Lg8x>e85Ng2rNmf+o1$L`g6Mcn#nCMk%yzPGm!iM**=LV`z8Sv2VB5}N ztRR7{aBQ)Uj=FZ{Y7sf3Tr2PJ%E-2sjyO%;cCJAu@A$Z6Gk7t8r2@CbHeUn%`qahN**bN_SJ6+mb3KfsujGQP5eEUMG7_yMi)v7|rqmXzR z0v3~9RHWTfnSUXX_aDqZ*M2gHwcv#;f%RC*QxDHGEmOJB>)s(_9|EYg;Y-E*POAVr zT3tPsA*;hXcWW9!+!)rYv%#p(nG_VQWCm!NVS)4XM%BtDf~{xAS>!YonNM0OJ;%g7 zI)9FwBou-hw)t|{wWU#D0|?K{Dk*qP#VK5mR!5Ttp20L)qVXP}WebAgaY$A1FIm@n z9MdSvltl-`Ny|0!Ob=t)>Rt3RPS{uP5CoN$ttC4#)C=lfh=@cM$jh!{%&9~3V*(wx zhkzKlUvyz`J%5PyAf37G7ss+Qjs=GRiW7cM%As3Rr1%jP#{)E4P&_T&jlG0E97mtW zGf=dNV(5tN!ZG#(XjEv=TNHoe@C?OCcB#-*SCvoZq_qLxK8OW=M4Iy~I zP&*K;MqdhhY&I90td0G!-LMtTl6iQQR|#o_@7AogJU8a8u*CSh5qn%{HikDYiGlxx z@ypPifoIL~{Mlf5aJZrT3rzTViisT%$=`k!^=G=hvaNf6tT^YBS7GpHRe+|l)iZ8Y z9F$cy@3#)et)3stMN7gV$*7eS@%FauQ!wXFwcGaC^`UR=-!v7^I>K5v(IgM$qVQq~Fe6^VA&0<4h^ zpzC6QWe6Ufjdcdy9!HwMpGE?xcbv?hCvwH1qK_bjD`Ih9E!p}DAsC6kqjZsHivH(%S1rV1L&a-cdMy4bqa}>F znF+pnWHZoKDb11Qn2^;nqf)D9o=ju%YxMA@aiF(3_;h zi(Rv*#JY#sR_h$MTxq85d}@Y{S`H7@UXJj5d%HAqDbhP+Xf`ABLfW|}HrU(vz+C5j5qjRM(jctNXiBXNPEnFzc5Exu(SWXurNwT4 zu4H|$9FM`A?VZEu@xJBZDO}YEqgA+#?Xf4I^`xsFzx4F>sDzGuGb;oERNEM0mPD_2 zU+l3KNXpmF*jv1|70TNuoj$~}zJrfc$je7KTMv#E32X=r;xW479F8?IV_Aq2yZVV* zJ9?Zm5_q#D4yLLP@awS^ zQjyd>aij<^{d-8DM+AOzuOF5f?@zqeP15+Uk_LPP#^F>(=6LfwKxqgHiGyu2Z%rS; zHnz~<-(tqBUcii1tK$8+>RMT-1I654Y(uW9raBhdy&my+bkA^>EQ>)Q@f}cdHt1in z2i>$SsGXhZ#TD~`fNVzWQhrfxPp2JT8uK2;g0y?}jskkV&pX%;<(iVNgLM@1X3F?p z^f)`27wG3#VRQ}y@cath6yD4#v2cK4RHGbiQ1}Efc=ZR!?AT2(N z5!pa2_K!Cs&)^|dY5lB&t=NWM_B{205d{vLrhtAOx0jipB$=VdzzTCEUpKtGjecE0 zcp70lHL@i))F3Y*l%2Z3b0s2X3$TZ+`>?`R;90fTuU6vS;({ATdd4bSdolq58(|Yy zWE0#QZ)bm5DD7PhtLpXL={4`NEtaLsjS*EwrjZ@*EM^UC!(uQHm7{91wW$IZ=j>vN zu%Qju(6{YmjT9|qxC6`_w+%U#fKc7Vu$XBvgJU2WoV8ob20DEw#haTFIGP&1W!Zla zr1RH&D|};6*e~&Vk=f-zv?2!G0^>I54rH)99c^J|3Jjg@vI(YfUP-W`QwgstEwloLZGY7A{uBdDozawJHIl>s73kHmL_vUbL>x4*N@(lh2-g_V$1}%aF3O!;MDZQsTu zO$gi6OouAWwlFb*Mh1WT?bampy0>YP{AzYBisnXEgmqa0>smDD30YX^iCPNpg$P4x zBR25V&Sv6LuSxG@RSIfXMb>*O4$i9hD(mWj4SAOnRGC){b*l7Ie3f;%XRGp-yC;pv zV#88I1-WTpQjO}7RVJ@#ZKzV7T3j2QXO@w-vSbv*P+PVhyzZKi zgA`WPz>Z57nrC5E64ow*yO1gdR|%WSP0guCa;nqen2iRFhjB(BGp~a31VM3~`DZxk z^~h2$#OGOei=g4YGV@Z3JUf&z$bpv%t)e)L^k-veizk~_0Xz{i9@_nu8lcHSX#1_p z^{ne1hz`l=Aq$Do30OSBt|eWHjoE^V)SxlfVk8=j}(SAPazd5!X zT5ENKA&2Gpbdw!w+c$mq-XGK|Hl=s*FPG1++fNM&4&^brX=#1 zX=}4NsRzsWUJCgIXK-<8aOmuW8e^-C;Y%G7Fr5!irv=9W!!R8$qK&Af_$n({e7zLy z<)-Y7X(|vg`->^Y<=wo*0)U1TwfQE10!p1}*jMP6w8aqo;~(O7kO+s-{I1TETC~Vx?@)_6OxzDl3ld zLTCk>`$9-gP;2J6EhJ8$YjI-Hvb8KQX8711dj8wWF!n+A8umwBMpv77(hq zHo07h8ow%igpu>0&p#Y=lbmi)J|E4d5mQib<1~-86VqSz?xtn^vh9y-9_cc5bGKy7 z^HLgEPL$ME1c&Bw+97Mp%(@z5&Cy#u*iMTXX@?o9L~%74qsAG#oVzEB_4M?&*ODn# zVNkuP4x&m>%|qcwp7w_3=Gj*x8?T)30)+oo_~S30G-Hpa4OP)QFJ`FRLX z)V9`n815@Kg$n$lqN?*Xxs*`qtd;LAi@U*C!+-@Ws@c8IR2%j|zxy~WbhGLl z_=d!v^igf_yGTjQe}H-DHy0>0Vd~gBpd=(e_r}W=7;?TYP}Leka8L`iPTI9#7(2Q_ zhNQ-$81G#(7=aLPknxOP{+OSQ9e1hI$Z;__B&0t% zSW+gx6vini2$33Bc6Es&jIsAIz(Tj$5O9vkL*E>ZaJEE4BSHkA#k8xtX-lDHD#3PK zWlRuT*3&)=c0(M$UR8bkdF6hxRk?ZZb8vznZO|D#iw-b8C@kG*fspXz9gs})|xDTd17DGLH0}-c<}WtO9D)@SXre219z_ zq5;?Kh8(zU^Uf!h6p~;}CT`ax*gdFaZGQ8zpt{py&THM{htX|{Ri8cj*(RNCn3^1v zxi*;d=`fKy+z?0+k+p$8?E~FlrVe5YEmAx=otiG!@Ysu#tpvyBAV1lLmxE?)!)TZ^ zdfQbt*lNgJxV>`12uT0$9O5CSLbxWsP8HCOi$xH6$O)lh^=*i?YfFb$^_Xu_ag#A< z?g*Q*LNSfgLS>2dlm1zpLp&yktyE-5(gBWvAmHMZggm>=7+x8gnZb9%It81CxxIE= z47Yhe`x$|&$OTognH?vjB{h_dWv5BaB&ud<@MwxwS=2M8IgroMS~f^;LvpJ*=@#Zy zm2zQf5s`N%-i8jEoHgB2?e)vfW}#p33E|d7(Uc0!7FLqpCJUW8NPG48`tjA)_15l~ z3!^t?vdx7wXy3km_TuWr^)oDPv%Tu6u*rCMJsO{Lx1)1>JQx)s`M>D&#$DEgt2gu6 zHGfd081(()z7-e!2V9@%@Br{|_Kd5>?vo)9g;-;Z9Txt7`O%Mlq|c8&{`K!a-`V}T zsg=F{sk*|Si{O$j^MSjd4JldEc$}p(-0Wg#c671{rF54XX}5gIr&16#gd4*09Sek;$WmY!(G>Ct5OI9i|Ku-PPo$SA8#WX z9f#wvJk{#tC5q$Lysp>_CYJF|K@UC7CifZyj|XOAFL-h*xy$hcLjtfPF=x0ppJfdp zznYJy^K+;G#7xYp&8F`x(AG5Srr?SRVDSe^V>UPhDNn*4m2T_@SFJY_cb4MmpJrPthO0w|k^ zj$0lhB&0ndmkYYzOq_AEq|9DgADzpMiyY)pk?1H*TuxVGQ9Z3aUvx{#)WZO!UCtxJ z1FMbBTD!-oINeVKCnUDt!0FgP64aq%Cyyt4yP0>FjZ5YY!s#qTi{5o)V$-@317g7x z_6EQJ?_ce~qLF8>G#)f}C+HTVqSX-bk_R9X_eXns+>yUxt`4dC)wOq25oSgBs9Dv_ zsaHhn*vW9*?Z9RU&=P0{b2&#A80XLOxEQxzOpj*O77<+Z-60O^a=sCInEgcwfu5H5 z79!Yvl)~j~V-d@)=5EZh5JOL^b!kYM&FV{=%4sr*cMp7OpU6CM7>1SUwKaiq=UHqN zS7w-My#MeYZEF+V{<7Vb$%ZFe?LYQO3YxPjDCCc5D!nRCwx8{Z@6qJ8kv1kM8&2zD#g%;#|IiIT{;51adBkX0k}$H5cFv>X+9NXj_@`Q0W95GGDAJ_B z<19uS(#H){xfol9SrHTb_@}k>H6HFKk8D`t@#~}4oe^R`_Huo|?#{V=*b8(II$%jd zjvxQDi6u;tRa4k+N7{-C1(vKv{U86diq5pCop7#*G`^ZT38{bbh$==W7UZx_*i-l; z49wA$i+KN&M-7E6C(>j}o90Jv=QHiEpKSg3r>pqc)Yw&9)5Qd~5a_+jdPg?z=~CuJ zj^ihfAbSCgs?G}29@NPe`G#olFwIQ5GY&+`ZjK-Sv~k5wRf;Q`p>?&OR$cFeU6bP{ zj{-q&j%=jhRnn#EQGF+xH>WXrdUKM90HG&~fLjupEtN`|h2%HDt`9)Ww*+%xAZ|)0 z%)FsM8?rR0IXU;qok!)wdpWkE(;oLHfBQ!twLWTXv_5YAsP$W|-)^;9e@g35ZT)Gj zKfU#5wEoQ2pVj)aTYpaL&u#sAtv|o@7qtGu)?d{6i(7w5>o0BnWv#!w^;fk1%GO`i z`m0-iP3uAHuWhwke_iVjwSK4d*SG$L){k31Y5lbIH?}@$J#0N{ZMHsbJ#KBap0u8} zK5Kp6`dRCX*3VmCw*IEp-`x7$*5A_lTU)=^+HO5-?X-4V&s$%$UbMb$?X`Z<`eo~7 z>s9M@>rLxz>sPJ)))Y0^Tfg7>gVrBz{cWv3()!z5N3Fl3)oFEGy;i?f zw2oURt<%<^^_$jNYuGw(jauW@r1f2E+A3SK*1UDmx@=vwu3O)?{%Gs(Z2hs;-_`o# ztv|8R`nxw;f6qqi@7-wqeH*R6f1~veY_$Htjn+T3(fWrsTK~vK>mS`{{bL)ge|)3$ zPi(aQ$&J=OwbA;gH(LM9M(dy5X#H~=t$%)_^)GC+{>6>fzqHZ%mp5Af%0}y7-Dv%5 z8?AqRqxElWwEoSF*1xsU`nNY)|ISA1-`!~admF8Pf1~vuY_$Hvjn;p((fW@!TK~yL z>p$IS{bw7k|9qqMUu?Ag%Z=85wbA;oH(LMAM(e-bX#IB^t^aP2h|FqHi zpEp|n%SP*e-Dv%98?8UN(fZ#vTK~sJ>;K$n{a+ic|9hkL|7^7W-;LJ)x6%6lIr|cD ztBNE4I;Z;dz31M?BCBx;mw*C33Gtb25<)aFgqVbEW}R%4%p{XcX5TVfhEiQb#--hRdrQ$pLLO6 zANeOEzajD)Bflx~nC#1MgCaiUyuCp$iET! zHzR){@+TvID)Mhd{&eKuj{G~3e>d`HBL80G&qn_J$e)Y+2a!J?`987l8~c8-?;raC zu^$-wTVp>c_Jd=8TkMC#erW86#eR6~N5ua2*xwQRk+B~Y`#WQQSL{c}{_fb{6Z?B( zKPL9~#eQt;$Hjhp>?g#2V(cfyesb)m#C~e*r^SAH>}SM&X6)~e{jAu}j{Th2&yD>9 zv7Zm&X3#*e{FyBe8!p_RC|xBK9j|zbf{R#eQ|{ zACLW-*sqQK6R}?x`}MJZGWHu{zcKckV!t`|PsM&q?6<~#TkM~X{WGzDHulfOetYb9 z#Qyo%?~MJf*zb=03$cGO_AkYLPwe-`eqZeO$NoU<561rG*dL1h;n*LE{VTD5HTFki z|61&i#s2l!ACLVTv41o6Ct`mx_NQY1R_ss5{_WVm6Z>~#eier7pnjnGTh$LzKUn>3>W8Qws(zUI;p#`Izg_(u>PM;{rT$L!cc~w( z{%-a6sJ~bJ81?t5AFFLK*ewzB}>Sw5*ss4WTv((R4KS%vs z^$)0@r+&Wr1?m^7U!;Dq`X%ZgRR56rrRpD6zfAoj>K|3VT>T35E7h-3|CsvK>K|9X zM*Uj#PpDs~e!co9)o)P0QT-bI$XTKzNXpH=^y`t9m>sDEDlPW8Lg z?^geU`WMx|q<)Y3z3TU=->?3F`h)6UR)0wSVf9DUzoPzC^+(merv8}v*VP|a|AzWE z)t^v*QvE6QZ>c}6{%!T|sDD@e8TId}Kdb(I_2<-op#Hr2KF;@bzMu2`ogd)*K<96D zevtEnoxjcbAx2^Yfiw;QT`8 z7dgM!`6bRj==?*@FLnN5=a)JEi1Uv+zufs1&aZTSmGh4|zuNi7onPbpTIZi|ex38{ zoqy8#4bE?Lev|W?oqx*tEzWOsew*`8JO7OH&pQ8{^V^-@;r#Q??{t2b^ShmY!TA@R zf64hh&hK@8pY!{jKj8d9=U;aIkn@L~KjQo=&cEvXQRiQC{+RQxJAd5yH=KXd`4i5c zbpDj{Z#jS3`L~^a$N6`iKjZv+&YyMuedo_P|AF)8o$r(QzKQRb`2L9>kobX#zculL z5z ziC>ubMTuXW_$7&dF!2v1ere(#PW-aOKa%)I6Iq@_5{rtH1PVMOSxF@)d8v{n(o~vB zbGbxXNK0uYt)-2$l}qJAa+zE%SICv}VQD7?X)hm<4$@JslB=bYbe1l1ja19E(p5ex z-Q;6(oz%$n@^Sfud{RCopO!z9&&X$`yL?W1$mit-xlz6#UzD5VOVU%mEWP9_aekebZKbIfNPvocaGx@pvh5SN(DSs({CBKqi z%U{cHsL>mQk_X8OvRyGBK7(u}qF-N-R@jnHJ0RSZ2gBGnV^fnH9_ISmwksHWHWkoD2V_6l;W3jA`uMd;aHBu@=7eP#&R^4*J3#q%j>Zm zkL8V6-i+l$EGJ_*70X+(oQ~z~Sl)@{-B`}V@?I=wV|hQ8bFq97%lTOPsPt9or_x_# zfXYCXTU7?B3|6^KWr)g9m0>EwRYs`Xu5yRUNR?44cdFc_GFs(sm3vg~RT-mlpUPO3 zaVq0gCa6qQnWQpVWs1sFm1!!|Rc5HnRJmVemdb3EIVy8i9#EO5GGAqZ%0iVzDvMQ? zs643hkjhe(hgFuTJfiZb%5s$zDl1i1sXV5#TIF$-H7aXWo={n*vR>s$l?^HzRW_+? zR(VQgi^^7&Z7NTzJfrfg%5y5)Rd%R6ud-8Rm&$IH7gSzUc}ZoD%3hUyD*IIqs2o&z zS>=$*VU;5)uc*ALa#ZCtm18Qes~lH(L*-4C6DlWFPN}@5a$4nWm3LI$RXL;bp2}I3 z_f^iRe4uh(rH_-oPWn0N?__|Jflh99GRVnbC$~8n;$*0kVNQlS8R6u1CwDj*>133X zJDuF+WVDmJo!sN(UMFLm+~;JhlW|VQJDK2QqLWEZCOetpWU7;CPNqAV;bf+h`<={k zGTX@?Lr#`DdDzJ^CyzLJ)X8!uE1ax!vdYP0 zPF6d4+{qdzYn?pdWSx`sPM&nK!O2D^o1AQR@|2S;PPRJP=HzK7&p3J3$#YJ&JK5pn zc_%xa>~gZ($qP@xlLJl;I(ga2At#5O9C7lBlUJP_b@G~%V@_Uo za@@%qPTq8K!pTV|r<}ay_SGZVQ#ky(k%PGn9Za}#+Wk$H*C zPh>$N3lmwC$l^qnB=TS)4<)iRk%tpmmdGQCn9imqx#S6f3Yg zbx?6*t5e`noqB4t@y*i=^jn&h@zrT66ROjkOsr1xP?)our&ThkI&C7m@-n$PZ7Nf$ z(`GWYI&Ch~s?*D$d#6{Ym&=Um^a`0-on9&TSEnDAS=DJfnO&V0WWgnAdzn+6enjS0 zryb;h>a?TGt4_Pf{Oa@?*b)n>(`s2*on9-8s?)BrxH|o)EU8Yr$(b(c$K+g>^g8Kt zOgx2% z@_2RHOV(7UUy-%d>CG~zI{m6VQJsEG)>Wrpm-W?YZy8ygenUo8r{9Whk_g5TY$KRP zu#9r~swVlS&6;1*qU9y6@~zwC+g_Ug&}Eljab^C)?F#KbQs~gJaMjg?PMy14Q(d^W zYvH5a3Lm?!P;-6Z5+t{byZ1^Vu%lKUe7S`N9o1e&LHZ6~5H7@a0~GuiRYt z>emWi?_K!DHw)kTcHuj>6u$et!uNkr_~DNVfBxgbPkvhX+0P4q@r%MQ|FZB`zbgFt zuM5BVZQ*ZzSNPk%EByUG6#ns_3jh2sg@66G!oUB%@E`wK_^|Jx@j^o{yO zh5pfis4y_PH7X2>21kY4q9IXXXf!M;439=c(Dr#jxyQN^G+)lSh>W?)mCn_@>wfiv~rJ?W16zneO4~Fa+Q^#&Sv|) z#mZgbxs|V3IieZcPO@@}mD8;p)11%4h(bBeo`iCW{jMxSomuuglymHNC>PrA#a1q} z@+m9#TN%a}%0u?#a7B6AexI@OeJe*?Lfpn!ImyZ?RxYygK`R4rQtXyT~F)QD+ z@`RP=tQ^*gtwvfo&dNzvF1K=pl`E|bIIOqdJFI-c%A-~eX-znHSvk$hl~!)Ea;KHM ztbD=B16Cfk@}!mLt(?$?aHd*0&B{equC;PY#qXW=dykcGT6x0C32g~sx|Jube9OuK zm-6{gD@R&+pOrJLoN47kE1$ITIV*QrdD_Z%tQ_|t!kK90G%J@_`G}Rvt=wwmGgdxp z#W>h|UJ z$}?7;wQ^89z8!Dn5i8GIIl92-%r+eqd#v_JlLa z%JEjtwsMh`4_f(zl}}l@)yk)>eAdd{R_?L#H7ieAdB)1~R`&l0dl_uy5G#jSd54wv zS~=Uwc~&m9a;=q5TDj56%~o!)a+{UAt$fAG*Q`8g?~XlItktbC`UyrT=BkFs*2l~b);Y-QlaQ0}rPFIxGMmHVs= z@?_{WgfraAJFT2+F2e->K3m%y&my;#_P8<)^_?0?WWzeMt`iQB7MedC;h437VCRn6BuiS=)^4WunAttGS?>#Sw6YBT6%JiAGVJ&?ANV8ENSN zL*bo5yC!(j6cC#0CE7w;YAbD~t@T5CnO?3}=#~0mY28vG+3(X$0uZ3x=a#RWjk zw254rM4+Hk^LSkbBog|)&`(CLuznqVV4BK@*;36JRxn)Q5<{hr1YF@8vo;;AO`d)- zU>k6~MB8Xvy;QEQn3#lKG}OpQ=VCALsNt_`2+q;9hCi+iUDC()QFN*1Y5SPr2!9*K zo{<`BozV9Nnq=hT_P3fJ?vtqL>5T(jNXJiyp*r~trmcXIlarCpYI_j$BS5lBKIfdK%daaao|WGKLMu!bC%Z;|Q|7vy{1)xn=@-z-sEW70 zt$?lOoc}sg0d5+&;xz-ge>lC11ZSgwuqY7(j!RUy!^d>2}7jNrPS_> zR-NSUE9X0<=Nqp&6@gXDKa?eKBLAdWuzt1tQ<$KH4su}KOa9qJL^C?e(G<%UPdlKW z?ilTr=;bSr4gcCSs;a~&OSd{|T@Q@NTK`^RtxM@^*IxQnXf&_i1}Ku`I{i2Y~JfV4dW@nng|OG;B@pzQJbI zKv<&584P6Y1@=;nIP?HeEKrbIN+LK+#^w(kW+!obYX-z_;L%*lr2d+N= zoju6)=OAJ`ys1+a?yv~8+JW-JqrgFM4@amt0`8Is^niN`hRqKl)~oQlq*@R-!P6fh zfWmbPFD9cXzkP<#BMO^p8@jE^*{7K^}qFR^&j;QpaJXm(*IS= z_cu|oAv>r^2>SrQ&-Gu5O?m*pzw1BZO&zjjLTm_C|3d#+zmLC);;br!i-6!S^hap> z1N|p-eI@8QzRqkm3jrnlC2DojztX?dU+J&W>aS7zhmdy@qk1bd4Y4Ow^cZ&rv~7nc zWgdi6ID%5R9{&ZojQ~|!T2Y8pnH+$>nDHtw=k(%~A#(L8y%GT|Hpqo27V!Cv{uY@0 zCCHV*vsyk)Lxc-B{t`93{*C?)Ps#}7Lg>q0djRN&LH!EPY60XK78}O7`z4zH8t*BS zeu$?P!Z;TKXXQ!(%=`*4xe!#-zXKM)0i1I^NU^Y@M)MGGGZ>`jFF;Wu^!H$ef55m3 zcwb-2z&+0Joc;s;Cq2>-r~^k*5Y_-u_$zBi3lAh`C|_R7`6`4xEbO-;g7#>_=-+*TGDNt5CjW|tFuL%j4&zmcMG4WvzhP9Y z%8}8AdaMqAWkMVg^;oMT{wgwPHiQ=K#jowv+Va}WhJYjb?FGR93L{`$`JE48NGy$B z==#e`g5&mto&de}i{*2c3opCi=FXjYBro5;YS-o0!%A!L0JHBF-5` zJHa{M!z;c(zEaqmWEcZoz!yI!C*ZH*i(H6|YM;pD?p2sU3VJ-P<;P|rZVH^K7kfc4 z(@x|zjXS3vcw27?BE(b-wA!2@*h(?;OAMD>l`&D{p?G)How5vLvh56yju5j*stU-r z2!UEi!X74}sRxNgchG)d1Wo%5Q^7lwySXUjh2?CcwBNx~w4r1y4aUhU!6HLIrTZ7)>xYD%K~h z(6NzDVmQAZSLZ@_A1p`Ap4HaKhr9qRL@4LKrCJXf zw-cUMP^*fG1Mil^MG$oNL|D3=@S@V#$%XU+NQ!?4IuvmQXo~kLdd!5>1C9~B{Xxet z7oo_{DH9UTk`fTAi8cNK9+h=fhS>^F5Jy@@9r0IrN%ld!o-@?Z%#&U^E`ra1mPP@D znMhL!y>&&Z!-b17FMXN)fb~3{y?WH0zzOJz=XGe%pXm{J9}M4)n4F)0qy?l+RFVMU zJ|<8YoGbA=tUg$U$Z!Y}@3)Y6gW@9U2y-HHg5qv0{ExAzq&)L36cE67bVP9h8E4>m z1xD9}+zc=rj0aal>_%N{97(Cj(NhV6Wb0t$>6{4oUWawOJ}RzW4xxu`u(?RgLjHE1!`~I@QxVo%7cBZ`BV8HkbI8VtKNfwoabCXSN{hmE=y=uD7J|FB>qonNG9-_n z>mJ~-I{snBXWsxq8IDv5ZC=@ra=p7j6 zdJczUtN}l)ieMtHj`Z;eHrr!dH$T${BV7~e{TM0`_(XL5{|)PpT~~Ac$6JMr7t>SI zBeP1$9_?U|`~Y_9e;HGOo>*L{*^n@5#%!6}xySk?s+Wv}c10WLhj?3WStGX1+!|DG zk6*?P9}9^#fsrwu0@b58-3P@43e1Wy+*-oUCN~**ATxtjH2b+kToC447(+&3H+>Jg zrEln5>Vhhc2E^{7e?W)bqOSiZf~6r32uP9>ZC8vZ<)xbq2}1U&7d0;aF736lA#I4G z3frw3JSe@q4B14)uNqzo?gd)`PdatxQy@VI4)kda})_q60D z#$h9dj1Oi!L5WX-QbE09?$eYQ_D43PK-nlfkk8=n(pZrg!o(|i&P~`6?>GFZxS-b zFd|zBKck!g$8(q05uyce>sah*NG-FK``5N}`VF3x5y*#}v*K%RtGHqKA)Z!9=v+ui ztAK$%e~pK=bk2o*wTddg!3OP#iW*7CWy3n}f?p;PT8G3oH1b#lbi+WtcLM|e1S=oH z{mBTH8F!l)-#6f6+7LJBVrd#OO0j5>g~_TBKZ zsWhpx-ZCNK&Y(kS;;-WT=R*!2UKCaCMk-u*QSiKid}&D117>7k>ar$yQl5fb$leS3 z49$CpjDS5+ZD(Pk5)h2(@1pgYILeW;FX%Z4mQSQxNwVQX}y z0ePeh>e7(ji2i${N{KzD(1@VceV(-LsXLAEoSa>ez8ER?DzCS zwaRJtA(axHz}(00u$Dg@QY#G`XsHqx-bhOvbBj@a3N3cigu}RN$XVoTMl{-U9nk%U z#M(FFE2GOVqS=tU#@tP?;)$a0MiwXXXHQXt(TRPheWW zFI%v!Lh`3gbvIfj7{T{}A26l&H3q)zh$Nk~-BGt8Q{u9aI*O{jF;neyAL-A{4NY8< zvopru9&Gjn-A{W;K|V&n-itpJwQXd?NW^0zDiD3YI9jBn{tkJm7;LkUn`$buD>0oC z6>ZC4S=L~3&eu0zT8C6tec7s0VZX}VVppJuP2C}K`J0iRh=Ar**h&@G5;5jX%Jz4 z@OMcfz`SBsuyIWXP#o4(`CV1W6$S#%XiP5#==^08X>1(|=R-bmaV~BI7oy%t5*aTl zhIl12j^Cu7ux&|@8ko1hKbvf!QhF4ZXM)HBgM2Ymj^hfz!srGN7u_+p3n|U$<688B z%>g$_?CCmo^Hx#hnPkCuKY`vlVzgz>V@s8G*<&xIUoVAE6Irq02>nbz5~3P#E?1ADrn27@|W9Gw&i`ZFr3 zAVZiL+S(KUlL36l)wU)ON3%2`m%Cg@-X>n}MS70ws~ZMbz~frJ&4k=;bkkX}y+-c; z10_a7!YdQL@d{7ps|hQlzcT$B&-lw8H4VAoe54;xQM^wrP{Tg^#)R1q+4@@7Txb$9 z$89a04~X^PzPwM2QFp@2I_4HKY?)yW{4@AvomPc(b97YeXrqkpiRYDz9|^fC2`Uxv zqc{S~PsbySYI%5;3EAqv9h-QdfIo|iO^X@qk8vee$>WMdcAFOL;$x8W79a(chZmK- z`jG2xWWe5jZE-?M$?xk3tX0T?2b2C30O=;=mK+%*^J1MJ>m#u~8taA_?z^Eel1!H2 z%z`!~`Y#Dt^uWEB4k=cj6N9Hc5bOY;RKx{TY92MM%g@=6c@GTW;k176pd=XzOvvXv z2PXsHf17a}tSDxaP`k9pBoBym7}4|aZBl@I7i)EVtl0Pb6xQVg9IMcF(Uo=kWqxi& zDol%z_s==f;W4o33I)|u?}!zv_?u-||q>Wi@RpAf@ zYCDjyWVO*DzNgM|NO(*Go?%Q4+|s3GXy-OK6xkmhY4H%pK`xIZoaG={df{hr>DtK- z5(sBJ?2!-0JdA4!_#Gr)RXFxx^U7(fDoz~OXgH4K)Ilx{heN>MoH@Ee!L_f~s?XA~ zkvD<_u+t;RJ)o++3QOSIn2K1jsXtK%YV&Zw1g|EOF2*=PZer3nyz7UJPH09vR^M3jVc| zH*InJ1}%Izf`iduDDZ!rFV1hmLpiUgF+yKwjDYAp59tKRpcW|7&lNd87mn`W9fK>> z&AoLl9Ja1<)!4ZnyvpbUw0UtfH|*7lXMLbq20K!?6;J)N0s%_=PSN;d!0k@)n80}G z#Jvf~JEXzPyyoG^kWp{}ZH?{>nslMqU&c&=YRJADP^Ug$z>MS}BWt%X)+Mn%6zd`i zxbApUVP!Q7=aBfWJ8EBxL31Y%5~UW$$fdd6)w4_T;m}gKE_ZC)UyZDUTNTbU0i5;P z6R>XyW5tU~?bj?Ed%}CKz|?Bf^rYLNtHQOj7zYFEqW~+Fr=-xN7!bnWC0*1aoSh=D zr5qGMR4aTtfK1OEsm)amZyzdN$kO?6=*lR^?P;~O=!vHlRP*6XmI3OF-$9VHdPe5Rb*W#=0p+U1{*nat&+^+wzp&e*zQI z=_>QP(1gLZ#^|~_wooWt4cyvffH@j8!X+)jaX(OkHre&aMhu=~vODkqNjuoT9|A z*bzxjFo7f17grbE6P>}1KzI|N@uValk!!+}o<_*PF67{+jD5S~U7gKTDyyCR4s!$! z;1I!;cv3;n$9WPJ6Wor1U~8<;#qg;BHr7>*?qH(>*w)4RbgV~XeGTghbf%T|cwRaDBL6@@z|vm1yGeTjE2vH3ak;a;jxU}ehQYYYOsOlvY2qRXxL{-U zSkRYZ-5UcW&6Wg&qD1Sd`(jds>8an+d6Djq^+vS6Jo->$lKrx(a89`hAJD_zY7a2Q zo65mt!&zn%Z%pgyh`&p#%ZC%r_O2s-2g{&%;u#|Dpp7LH&OR3*AcG3mmjuz-E}Vx3 zR1mi4aSYST&0aT*Yz)0>2V*@_yP~kZ-jDShbz46LFBZ5~YOu(TxIf~TY90<=>&szk z*z{1WhuO9D&`w_gBvh(zV73TnwNWeB6f|VJljQU)Qrgix=z&TXT3D^a0dL@megK}P z3J(iS>A_Z&4gEYy2mQ3m)Ea7Y{OA77oG#cny2;XjjlT z2=$bK>H*=?4ZWCnZm*|l5Wfk}2g7=}X5!366z-+rbUpAOdarYyfF2qHJOR>@n{%vRfAub2n-$7#P_@CW24HpU&rv?`J)*}D9s)bLTQ&5ADu55@x8XP+-c`(Svv7?B zNY1k=A^w8>0QbRwJxI|6HR|oftHP}lAZk|~tf=}q44V_4!HY_rl?fM9pqlMk@K=#8 z#k(rd=`Fam!dR$dxVXZ^Q;_Z<0s=IEIn7y4bx$3t;P@Zw2nA7LnIXzFRv96q)q{Z| z4&2u%{7na(ZpMj7ga?uiQTqnuZ^cPRZ27LhT^v|Fy(tR2>M(lpsrka9q<*LY7q`GD zZ{awBPaACAzN5n#4ZAD3TrP_m?ZSu4IAG5W1{J!Gkhm*>xVkgZ`qLVg>FAg2v{KpLPfx4^Ybp+Kp5lg%HI>n98mOf#eMW zp*yY$DKQj`{R9V%zKH)Qf!fH5L{=tN)xu;Zez>7SWT_LA?`9&71>=VXIRb#pajHR^ zhV>vWfl1`C1Z#ekL2n|f6M4K8!o+k3T{c?v9#sSh5e{6P)H7z+B(jzvlu)%s?^an; z#=eO>k;uBlv{a3$CWd6VSYfBvhqOMCClhKl%8MH4E?Hj&F6$3Jc?ML4Fxe%6pkBWeZ>TMjjh@cDL#a6a?J3z6cgp zJ%S)AD4=>w^)1!Ys&A{lr+QZPebsZS9}pzg!Fkm_xFILGXymcAY)xbvC0JK@Z@z;O z+G-lFx`sHkBcQda+Z5}DD+_-7_Gr?eux>9;C-O`JDC9VH0XA^lY(TS?ltS?xOcvRxjD%qaM zjzlLBiS9aC(G$%C%BAgft9{GX(*R(mM08guWm#8jPU50C*${1cM`x4oo5VaY~VIVk4 zwlSMTXRFRpovVttDaJ65Ml~qd0R)|*x=7KuF^%BlKq3c88T{Z9MY=q~6I?_z{t5&M z7_-8CMLn?s>O1&JfT?CiNo4okQNWoZTXCgw`^*Iuu1JUkC^1peZme0wF zL{28blT2Y}L&Suis1T$rqEZn`7G~h=| zr5i=CGeA|X)?!;X?Ro{a~DKG%)0q3w!2j;}KCy~bxfG%KR%s{^*hXRi4VN=dv7j~-X3{hze z6Px9Bq~W>b>ZoI*stOkol`^1P$_I&@=d^WZPhsBBQ=r;I)@48r-F6~L5qAHeA+q6$ zEH8bT@!kjK4|%hnm;T=9-Hr`=7RQI@6`YBXh-V5xFaxkGFj5Q?lpo-0l_W0Q@^UMu zt~-92C6US?FM|=$GBLs3C7hagRu;M$xecdGXgktR#lMPL^%5E4WoW>x27?N*50bkF zWHRI%mm}(2U~D#*VP1ZRsVQksu8*6r$%4p(9PEjtLc%vEX4zT(_3{yo~i2e0%5~R9H_ffx4TNzI)Cans{oX?W#|zJ`Hmj zsX)F#b>w9n;v*iA00vk0jVq#xTLisK^e7?2n#m+DlVMyNi7Ak-1^q)ntCMa}ysl^J z;^I4NaTWe2?`CDHmuc*#E6>bS!LFHF9#KZ7dzrxz**I`%;Pet_HJ6!SX7(Iz)Swkv za=2s2y#Wk0>N5xurM=8%Z(A@qA-}vksW_`*ijYI&Wo}?v7>V3;Z3RR;t(`_(&u4Xd z<9`mLwaoLl84iGH?REgZC3J$R+qp>ZXGn6zEr;_Org}!^ds#px<_heDzltl#%R-pF zo?sx&@JC=AT*_#(v6!>bT$TU{URJ`!+<$W;OMl0;*ah&qiX|6Nq^&&U<&B86=cX=T zPuznFrAH%h3NQ!b>`;B4w0Ouj;!MrTQZEma!l4=3fX9}Wr?j~&`y)6my8uUAa_FU# zegprJ)^L`4S?;l2sKGB=EM8W4S?MuSn0sCEM@eU_^70snA*-yVm(@nyPWlq7tu9u} z$>S6@z0rJ+>V8-aky%uDTsh-wkmBQYugV$&mdX=2SV>BE(|z3Da6vy&D-^S`o={0q zp5E$)KT9hWcVWWx#ZgSoS}Gg8Y$C-7>!8w5#hsQLD+y`0ZoFtbRr@vsI-ArIkh3mA_oslLO@ z^Im@@JB;W}Wv7>2;XWP)LFuibojs0f8YZZ(>#0HV3=B?U%v7HmTN$_)bazD$E#yTn zFOeh+%OBTb`Yn|tmW6Vg$eqm_xP#PR=mpKo9xr>TBff4@pSdJ(qT*=<-CN5(FZ`#jFptvwAsA`t-uDqTqNN_GTC|?vH)DNVBZG z>jl?75kxNz9|WLr6uaOzds%W$g1AIE73d zP4N1LqaR_SS15Am!4zF1+7gj1J3l42!Wv~U6u)mt4_vP`u}2ww)pDh1EXP z=^jTq+~y#;=tu)1pNu~K|1+e^WH8L;3_Yg3O%Tz>rrKx^RJi)Ws%AGK`2~L4ZWtSy zH6Cn7+EPY_1~xGoV60p>AO(hht7Gae5}XWu`VeYRzoB$fT(_H%;dW6Ae%ZQdE+aB> zI}V8fy^zBjoFM1n2_`9SPo5@IAJd&vgF~9;` z-aj%jQ_q~t%bmEDge!-!-_KwWX1U;Lh5XISXxuhJk07XkS)*700bnlRMMb@qa!*F? zB{0;Z^P(Fjfg6zC61?HCe;sNXX^ucFfj$>>kvn(E9K zqZ|K!*tX6}#6{O|{$u?3pLW_MGCm^{$TnnOpxm8EgBVz3pa(DlNq{7XfxOW1nF}_7 zxGft=`5Dj*KM1jjOtuGIK`+1w!E^utD1aa7@Vbs4v$;&k$W&s$<%24toZjhZCbQX;Ppq!eptudK{WhXR1eK%9(D{FMJyB4 zEe{jp!bk&|K^{*%9b@eCh!pTzy#rH{NrpkaFxwop^((J8y% zctaLEM=LKJRx4SB8(>Ow0WTm=j+&rMpRjJ~k_c@YlG<5WjoV|$zl`m{pNzjtL(j?@ z;~U0!AP#I1;!){!6IqL-816z#lra<_$}sKVrnPmKSw@~Ha&K2IY%ul{rMa(>bs1UD zgcv5q%rfDH-XQ!!_!vW^(Z9gv90IBX_@@~BKyTn+NHB;tOu#La7LcA;zYw61Tn{oV6x-Tsf#t)n~%3S^3l3Rq6zL~tw3(>c@) zH|lIhyy;`=gt7gEGNmVTC)QbP=_*}la`-yvI=e&xxB5Ss`BNfiS=orYW@5rAo=`>8 zjpfP7$tEPzaBAq8nCo;N=mW~(ajgi-$YvZ0;PUFM53maUF3JpS3X$N?Fg0y~&iJeN zB9$!}eBS~u;4LbhP~B3y!c*Cr!Iv)pk^U_}g(ZncWeJd#Z5cVp4NaKa0{$*>R5N)R zyGPO!qbd|7)g~hpEgB;ws?^i&sXUvJ=Q1YfG5gHYX^%(c95m8vgD#~bqkS1A4%diM`m8gOE1t^#yBSFyZ4gv+XOGds=Ax(yc zpn0)W9p6XD$es-AzGS)zpGwHcK5E0g_BY}b896{iAlvr`aBbuu_Gz?S1I5fh0jHr) zZfu`5ULv*Zpc%-uHbO8EjT&}9rg8|;2d;R?ixm!{lPdt(%!g`8mX{;g08)~F6Ju!4 znq`@Pq|z8dpduqjSrJ2eHQi#Z;gZg)wLx%;CQCN%`d(rk&!ozzHb;kvvR_$4JtjT0oYu4P+~W1 z0jVDN4xM5PSemAcoWiw`;H2&}hwx2}Q>8aqc`L)1Mps%{FtH$Vpe^1igT&4;BX4v5 z01-@dx;V%W$vYW&mqa&H0#Lz%;76)s)MOlQgGpG(Jiy!t38k2DiVy@hGM7ee8Wv4C zIfH#>rs(hq&A2Vj;Cbyj&&gSAIZL%Vz|6exMSwOlGQ`0XS_Ow+pAj@6c#Bz|KH+Qwr0wCNrq#b4}4U()3%*w6VirUx^XKSZ_ zP*w(KfeB{?Up5((Ey}p8+?JIge8W@(90tYTrB+okG%LgEz(lBc)~Hk0@zqvFW#!H+xNs-702b<*R5!webWDVRx-eW6OdXP{fT*bAi!Yb%>5zTJXV?Mk|l2QyF`YtV}Fb-iE&MpvVT7$Ru36LQ7$9*b-Z21vt78_?ufY zoHV%#)h?L1mNGdjQ?km%#yuRiro2^|33ikoydylEq?w#;V3XKVrlRL8=W;)n3hiI) z$GK|zmAD;loN<#~*1 z$nqQ+lMdk?vdafLF@ND8*pT~QIFw+_)A{hS(^nmm7to?1OS75G%*y>-&=?72AM6J^ zCp+t5?o2y@#&q(}YKQ=c<6zg6 zWd+p6AEkiE+$=-vbF*-*L$_yTUKU;0fgSu+oc~njXJr9j&}~2?w zFYJfA=`y(f5>UH4E^@%KSexh*iLOg(2{G9;>!%c9g=N|Q^W9-Bar>*my<# zxk_baR#t^c#t7jWb&71^m9?CM-CGtrzhLoPg+Gc6m&ocYGcwR8e%XfA%j4LF5!l<< zf#Q!aIn8CQJ*G`a@xm=6*|fW@C9Dm+uRrTqdBR2%w$r#`06Va<3~nv!pe=(-lST=* zyPY^{IvA^&pw5jyMvU-xPwMS;*#<4JDp{XJi03NE10u|oz-u%R7Ql;2)tJhYS=mq$ zyn(D(5_no(U^&^Cr3d|e_#mC0H=6fJ6luWtBG|?X?bk#$;mA6P)K1S)RQJ#@L)`zM z?xt)VhYwC+WMvB_5ds4?jotC2q>Wn2R_sv-ERdDL2?=gMq7nmRrYZ26p>_j;H_ zh{o646;Q5YD4(j%OA0eIY9^mT(@F$O|R_#!GloT1|O5l$FETVz0(*bV726awuEj zRmZJTS$U;$z7cOeQU;TeSF>_7OANUxyW`K|a>>eTSvi))P}(v1l^1=yR&LfrUeC($ zECdja+n3lq?0;~lJYLq33we11%)!$%m^QEgW)8Xz`t2^`**7Zj#Rm(qx6Gmfe$d2i zBPXeeDK*03cif;!vk7Y=K!7erTnoA$F)sRKuqx1`;myy7

(AB^kt%dr)1#<(@>5 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≶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%0DeJL>#S_7dopz;$Fkm&z}vpRsxWvmF}ZP=-DqFN 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 z zCJ%}7o4p;zg;MK*P5QUZ_g)GDsA7ekVukWvw!x24 zjmfE6|)G@Kp+1zMXPVuI$^fUE3{F$>a@w_Y9SK`jKr5(^%BCVc0 z;&E`u*z)FYUuf?!_ue)vtryRSWt zhE2!mbd7!XXvxQs8;GCs4AKgxT`U;I1+gw=he;Zq>~i<>piwnWZRF?-$M)qp0b-Ni;Dqc|F|RAN!2v<^r~X|}1lC+pwA%VhFfKQ@1yfpIX$x0k;ky)zn3`0F8bf?qQko$7w&h#!+?l8XlyhANeLI=?x zql3sH2aMqkl(}}O3vrh6v#aI6e4GT*?0f8q?1zEVu}@+GF5j&9BcO#kR8qWo1u{iYt07#0jPz5{U_do_`rpttQ!TZfGSo6e+=>b zx3Ack8+{Vf)CNB*<$)6?-^~UENpLSZo~n9 zdHs44t#lV?rOxKL@V?8?A(B8+_L|OOvDLfVcnTTQ_O1?3@`R1ZskBO}rqjE}gqJS! zi;KPcEH@BG-!e`StrXHZvp#Sfqk?AEqeDp!iH8PKF>!JzhK3lPt6!m{%_KmV&em;(c0~DISQ2`2vVAtBA6Yd zV#ztD$b8a4tMI5@mG!I1@>!F^S_2nwi(9y%lzvu214oz~W0XtcdqM;B@{h_j`BzY| z9r|DR3-P4tR6B=I561yjmeHK0uBio;xTY& zTqK^CR*C1OSzz&tbvy#1XKVwsGjkwh8QMg$cy1)*;la*ONvtOV?ZqDlP`U^mmz!Ox zBt*;ghl8}ilEQh@8ZWwD`rht zWmPyRt$F%+IcCHv;{gnrt1uq0XSs^!3jHNqx`-Qo#38*5mn^t^r~#OorV)NWvUdHB zw7PSnXj|$Ri&ayi?n}gwA?%8$uCZ&81Z82B<3;+)1q8Ow+f-PsE^fYO=v#~&MI40O zi0^sgNI!?butQmv6-OY26IKVn>T6tOPw{QbJ;>9G(v^Y3f#5| z&EnXzN2Aea?c_K(l<;y?6ZuCzYbVQC}m#^>%EvXI?lCdJkQZlJr8FmmXd-<8O%=IIi4Jw_`M3}jO-|h z0~1C$)L#^;yY3a-wqJwOM(J~IMyhQQ9);n>**Wm4v3lK%U;N=})VzNi_90i2X`T0f z?LCW#^q%P-yax`{P6fe%ll;q})gCdj$G?VecHADA^IMRpk6VxmP@)BvcZ0tO*Ku<( zjS%7jaV()_x)51FvQT?P*4}F<6?uSTXQ_g$finwp7mF}{2J&v(+%N_)g|e;eINmr8 zKYEGu{D;N07b1<^%7&B4h==#>D7L7F|4aDGYKTPruXCr>mEy)_NRmy)V&Zl`REssa zz;6y}au{pOo5@8B9SAl+9*4_O^VU(Rb%RV-`?e#X|Gn5a|Ez^=9SaxOy^O;bT;_gN zuK2&oWv_VTia%_hS7^q*RNx|c0Lm_T0LoI+SZKwLCv|3dkC+r|ApdZ4V3T|Ty{>;C z@CerRq0n5{-xh@Fz>%g)i@4p7b>z{e;C79gLQ9KweJF@Q{b8XLB&VU-`#(VlZbk%F z8K8stZZu(PO}-PLwm$ICseLagr1pqSbZl$3|E>52`yGkF$b~S$j6rUT8*3mh!j#FN zFkS;-5f9~F$)YemGL2!%8=u57JRXjg9E=PNle#g;Y~-)n)=^nLg)f;WC|GQtaSPlu z)8rPI-|5G_ZgaL!xM)eM;N(SZvQIc&njO;%u=@2edM_R?wzjl`RJdHSqo*!ebSim* zQwcG7cK9A}LTQ@WaB@}F|Ejomh^X=ffnhm|_&(7$&%aa2PGzzf`Yf72k6jBpc=FMD zBu;!v;>4#2k>Zg!F|bPvsO%C0DvLx2lI8g`6JNUq$oS{RPwb2a))M27gTag^Ifmw` z0zQwg9zV*dPd|M;4(zhIlb_YYU|^5LqS{GS2?_xu-ru)Y}9!Q!s|j% zN{iEry|sPnlwYY3+gjVFJH=YlwS78p zkJ%^n7te@oqjI0sy>(hS@h}%#rwcneimhGhnyVz@;cbb>-Zp4Q;<3Ok@tCqp;z3!U zIzil^)#u62Si$dFC57v8z?u{Lgl42`v;Oyd`EQA-?>Rg5?UZAmYH;jkf;bD=F}MH_<%vEL4U71Ssds@#0&kDKwM}Wg}ByM$A@z$4Pi{!Sg3Fp zE@5vfo*8g$yi7^@D-zTnFf#|jwlf1Ywz{W4*z7{O1Q#5YnJ<*q*|2FSh**L?=Sj|g$dJ>2EUWhM0HuO;yE2m3lp zdJ4N`=YvlQ2xd=-M}nxd!VIvCn>C0|){z8=1~v_%#zlnFAUYMc2v9^p^haok-oR*3 z;c}2V9tF{mO1WUtyqfN10X5BgAXc#IEpX)2r8wP8yxXu7&N=X@Z)&>;{vR>DdAk83}!fiKJCxB4hrD zmyzb07D3w0TR1z=`6Q5$(Ez1zRj2o9ovFrN7i)(Y9MXep01kZ5tH!G_83mY$8s5(z z$5SDcie(?EJUc0@95K`?^Rd%#u;#FsB^Hi6F1JVkSRA`ph*oU}bGg}J97qq*X4%1P z``#VDp&96_S^oe|Kr4mV298I~a%K1y9WU&6aYXt9+EEUo4+^Us zMABT-RTO|NJj95p)ls~8FljCJBVqRO_Q!iOUIISnNY0HklQak1a)-Y;NZJEob1?rGeo5rBuNB2eN2QxLw2Qpb~*{G(d5Oeb23jz zr9u&N5)=*{eF@I-nqc`HZ>S{UbWKUPu0$y1mz17e9Kcrmu$~<#;}vWt+wKYy#n8uy zqu?jy@;uO5n58J4?C`g8jignGr)hw~K_9Ao$5!Q6R(&-~!lx<^xi=nkZK%2>h-UHQ!YD?oF+f_pvnPi4L~1(k?D8t#+QHDk;;@k-X8!iCuPza zQi@^3@&AZ=EMLxSpK^-bCXh_yL@+W_2R+P0%Hol;LSSucpVG7_>^~bPXG6iUWm0VH zYU>EO$q7OxAtwlFrhwWQoey`GAz=pP*xpBs8+S+oTbG*4ge+JnA_e8N)<*9n9eIE@ zuu_~u3_nuxWsN_v0Ou0p4>M=M2E2SIzs>0-i6CQ`N*?#T5yM4xk|pL1#ly2>*me*> z^K3WAT#_=Fol?TWr9zY)UT$F6{FEzo!KA=IXrPLC2y!+wtj5Q`d}C@}n`;zI={&nw zXj*JnLydxS#VBCci${(EW0epst#PHCb6eVG7h0yYHWe3n=j#;YMj-+E0_}uvHQvd} zJ{#Y^2{?1Z6subD$$014{w}iJ5zLNOAuL6VS4UojO^^$3W<_-PYs^u8qcR`TG4*fq}OPsAY3lT($~)LkzB z46Hc)aMH>6-bKNd3qfuz+L&88rk8Wgne9b+qQ2DFZWm*lqe?t-YzNk65?;nCN3^uo zG^@$%aviru6HDS!4dE)5;Fp>JZMsCD1dVHCLRyKi?@ma%!Nhl8nvkxfbg7_?_WFc0 z4XUYdd2^&GXpt+1l@Ptcl3^ubMLZI4!}jQ`6!=IWR`$~K(zPb}U}9Qr+>mcIUOh8? z31<2w(d>>X2VEP(nT}vcH1Z_PCdue=Rf9=Y^Q%J}@(t9^_w= zgZxWo#K}P(vWw{{u*;#X?3kc*^0$~2f;s9dfg4vyyox|R5Y1HcCT6L?*{g=PUN_wZ zGb1F8b$C_uI0n57H`r+=4c_G8Zl~ZN8If_d9n7{n7DW5fG^b%N6k@p zN$|bPK$ZmGusu3Q1wImxmA&*Fb&p9tn4|79ZYWwcUOh*B4`%u$!EH)7bOb}9k*9Ld zOa|JdwBDVg*yMksbJTre~X#RL`D<+xUMOi&{2e>bBwn4SJ_ z;KteM;lLW6odRdEBU!6P;4kqlHOiA91|zWY?fK{y##6++LRPUNY1Z?byXH-TfZ()_ zwna(o(O;sm3t9&Fm!?5vlWIH3X-!f;U8WgQV6g-?o!C@!=yXZgJ+t@%KVusysc5Pi zuTHhE5^19PISX4GU4n`qK)XDRhH7i?f~54*rj?G;Ew@ED$tD_#208>UpZ~^7uL@=c zMhibFHd7r+E*wtbL}_+)R21x}@r^a?5C* zvi}hUDkavCK{zee@QNzDE!NNwO53jAzG8O(#6C?f4+x|n>?XtxbuGB35W^_XK6O+Z ze8~IaM}nSs(WyZe4I%tiYImm zqT*Y*w}2RC0aZ|M4Uq({cIG7;W99z(2=0bc0_qu@IUF+zS8#|O_9v*bhCA;5x2a@? zo9<67-N>NfUH3AKm3Iq6(U&qlB1x8ifX~{TeA%m9*yg zqr^RbG=o^KIYM@Yi$X4Pt_U0?a#D8N0?BFRQ$xY5Gda)v$>b*7xL3}DI^LDxgX=hm^5`6SlCMj$FOu^qqJ^zDU((|$?K(__}IB( zRCiwv#IzGXwqF97gKQbau|-rWu~L2sTTy8xcN`rh4rb~$vFJzx&3RKvzoI_D+zp|@|ZHNI$_TD+50E78nRMtY$y zo<3cKSOps3$wRXa88m&|!cO71$dF?(*x!-_qtkL0? z1T6^*G{lHJ4x#agKP;8z5b4nmQ*v+Rtg8Mw|2jn*2SF*PC`avS-W;Y}U~9H4lTaqhy51 z!sK};;@g*q!9D7n9 zIre1Mo92=Y%!UZvttZBbBxU5dt5r#yiZ90m#{-4W*?4*!gaypU!@akUqgCuAT|vT) zG|+$8J6N$RL?a!{)-oh--d|5S(=6_MOW97Wza0IcYY*AKmP90-?qK8KnU0q$TMcO3 zzNKBa+j%e_g!k)kuMWA-fSD`a1M#hbpAKJ8?(f0(M!5g2J&sOw(Vup;9ntI{345HC zqE9Q?6ucvlZgHJBRx-Hb+o^21!a~PWo#vt!dR=GNOc%+U)j`$~H&}9TCaczV4>KC` zxULnm(*3|~Rjd4*zdXx(U!ShZ`^%S(qO4K&L{PI-Z~AGd)4^gES0f!k`gXHWyeBar zt|z(g0fuR%CRZ$Y_ovoZKld!-AMqN`-ceLZY7mp>(#d~o@Y~bQaRCLaC%8b1Sgd-I zl9`^VTOcul2q2L!5d@@Zj{q8^& z=`hS$ELr$Lw4q_U%j_WFfDdkrD^Rc^r^73^#M24Sfc_sil6ZgeVQ)ao6i$!|x}8FM z90$jeo5a7Y7(WyeKO_}PzoXdRQfMp+#VtNMj7wR-?T8o#lNS<+l&r^6ct9d!hRd@+bgYfctND?!&>q+)1nBR++ z3vRH##lvu4=qKIBz`P1C!IJL(hL_<-dDnr;0s%$mg=CYD|fga8W`{ zPsmP`@ng#UD11*)!ve;?+s844F{r*+d1%+mQT0@S;KHsE#3`;rs~VZ}kAINV z!xYg!|U3CYy3Md9mS;u53va{W9q1elZC^0^3VN`3##MPD6c*5pHELD zwX$k3c=Fw>MH!zWKyFf@wXxXJB5unw{TL}CEE4u^ zl&}{paqAjokyMhkpp^C`P*KJ9r2nu~V_^4W+t%m4~ANO!lCUkPn+VOzS+V z+=b`6KYOJG9C!dz;`Ig)k}@qp8{J6S=oSZU1iC5F&(6n9H)%GR9XhbP>$7S}5W;OL zbEVmiMW_>h?AY>3vqbM9Bui9OXM8(7(lKQVi$E{OclWHM97{FDmBcw|R7ldv*4rYDD!9jn5vR)FkIcKyyP;$2_LFYVTCKkp(p#|_RG$Fq#r zrZ3olsL1jqsO0j+@f=I}^^z}GVOMY=;MnN2n*?BYeVPH3YLt~v$pNS=L0SBn39;XF z6(UQDZwR`;AMjw#zmyAtJhvmndV<_YYWq3~Ym02%>o8@-6-#8z%g(*b>G38k8sx1C$gudDxyM=T zB8g>=(9@Cgw=EURnDrU4j`^)6G?e#0%#u+`5&1&_lUVsIVH9~E7Bmg#-art)YqLLS zoZmGHzq!0z!L;sH1<6h$XG#_-dzN73;;M&vEcUshda=sERSwjVq5HyoC4IS35=g=I zN%1odTE_->QFoi}mz2^y(k>~bzydvJ$|6N0HKlrbq1_7!Mz@D$Bpx(L*UT<-77bl@ zU*Ha*q=i`91mf0`?L~#_51CL72Cih5{lEkXbg~C-idEd~Jz;{$)S++WKaEpJ;Yi3) zADbmf={*|{+;nDpr}vw{or}4URTNJ*k+(Sr7iu5xSAla_fILXXTDFl4H48Gi)`~6L zj6cGX)wW3G@dnH^Can(O_3pC|w}1n6zq6cuQy*9Q%CxC5RfM~vI$&w@+RB|0`WaYfu^=f5-XLFoemnI{0?r4 z%8}xk882qeyV&V&7lYBAhc_x>%cA0Uu!UWEFG~4UNE{{v1k%(G=B`2r{$)q|`(tN$H+ZrL<7e0SOJ+z9 zp~?K-2Fl-%1i}@bC+EiILC7>^kKZ-w;fHWvj z=#Chn!Xt8JjO5Qgt{UxqC@1+*ob4}xc|P72yxgSI8+b>;J`na#;=L{8el*-!?!)kg zrE`YEotui>6aQP>sO#|z8{5PJN_FU=L9>M)M|Oz!a%|oT$Dz4GshI>+)hEvJqE(3R zoWT?DU4ndjLTI~aK>pNX>ePD8B%Ja*aCA&brIIS;7e&}>vy@J~R){oWX_@yA+>`S= zMp24EtNR5;%@3{m9Rz*eTrz{3XDhNzTn*!|>JPj;dDoIr&=d^eq1D-OylCqL>52Wd zs^15(uFGQO$9!-dO@yE zzYGz1?7V%M40iEIWUTBG87oV$H0$(kG~p#ul?%YHSgvyl3%suyH-RQYR^VBsTJmNS zro_e;F=Vnd5AkHOFR`Uufz=Y};u!@OIua-ItMTw?Sh%^+47X$P{-qxWVoI~pNaC?4 zpL?+@>c|)v@w;XDWA1oymKhR@JKBZlD`^6!9Kc>IG z9(t5~&DHSm=cQHd?%I+*Q)|mn_Zh}oRmea*ATjX+1{X>`VPKb-S=l9KR+gH!g9nCzZq|d$Kmv-adI&F$O-%p6Cf@%*XliCe5pt{uvy$Q;#tET z8y2)kHHIp0O*&fRYSPfe)sx_M4$Rtp2F&}z4IghPB5U^xLhe&T z?&pTwSDE4?^55v=7>=${oYu{5CCC0NlB%|YrFFC8xzXazG&pxlirK3y4(#WF|Knn< zxE1*48GP;I*d((n0`jyQdxK6tJ1o#;`3)rmN^`YtY~vR3UM|~w{dhn>UI`Es52J1l zmI$gxpS4>Y`=568QgXB$!hG`9fE|uJkpEN6zc2lIP;SRyOOr}uCj1F!LS7IiZnWd# zfg5@JVsdKoA=dXTn7JC^>2@82S;O7b7IwioPPu+Ixb%>UZHF!)As36 zC+0?D!pk23UmvTPrvJ8uR$AgALiaMqDo@tGJ66SNIXWI z9r-qXxq<1+H15v4F1+My&DyT?ea_^#p&h@N+)=Dg%;?45-s#1Txk=2g&2q-xY^IF* zrMwzX+3VW6=0R<~wxZMJ1g^a01gGJ{YR5*jY!GtUj-iV`M0>Jxs&P!g1DUZ zUk$8X^O`$NN}*s2SkETo6U1`iA7~dA}Z-ASoTy94IQaTJ9-)Cn07~2aWBTtGT6|c6ykBQF+WZ*au zb(G<9gO6jS*H(@6|I~k6Otkrbu)hyv#zR&Ay+oa=x=rv+p5f45!lBLc--A;LiE{6F zD(+g+``zaiTAG`1YxcxKXLDnuiD;2rk@bG2p7D4`la7bp7BHAyo0kJwTD=+t$s7XS zKN~O&J5MTfb`_hvTLMpx%D@^U4OkL75`LVXBjHKm;zZAXV-gAej6{f%nvrg#0nZS; zbmVam*HhxE-$6!0kE7!;57%NE9_fM=JD)f%tn&UTec5tpUzNN0 zIH-H$rwscLQ=G`i!8J~Bj#tFV6HmS{${9S7SMCfQ2C{$7`UBn65gc$=xrRR!%2j%64zmL5`o^8QvZrRE{ch|nMX1TEvGgYTbi(eXFZwq z9|B|!6&eVwkOW=v)HRZUAT%)wyF{eYTM9CrT3FEBvREj<5FrH9_y8Fjznl~&D;oz! zsR41IC$|jH%vhda^>S`}vN}M*N2wqxH}i2Q_BDRWuw zV;cM?Q4g^pkL~7@un+w)3veJ5#6=-M+n$1XjmFg~Kw2X(Z>U!R^Ty^?BR3uU<1iEE zoAJ7y6jYvre`2TP!ttR6=_US&z)GC%-cF_a!&Jo>)VU*)#C-XT!@C!17AZC^i>Fr6 zr?b_d9Lr73r3$MRy7X~3L<%buuiTrPnLW0W!Unh%?a9-_m9}Z53?m^qEXeF~jU^E| z^TSh(_g#SP;ZTgU|GNN7cnTg@n?@R}X8@~l5Hr#k_CO9C$Kxu370iWUL#14o^-mHC zf-ttKDjC~ykgn=+@Fb1;2wb&NDv08|aCK$#f~=TS4kac8 zU9nN99Q&ac6)WEvb!svb3plB3x*WPQbAv27i-~74UXAzaV6L#_uKgA!8-8513H!r* zpl7IExg&wquoVR4wI+xYgIGOWBiA8dBMV{+7p%f`cXoUw@N2ain+Q*M@YTRxVXKKW zLO-q+iVnUbdolP}Ks@Ya-Ka;v+{-eTP{x?2o<{fSrD&}_$PQ9NkXr>;i}hWFfXuq! zxj?-%e-Lkl)x&<$Q;ZsUTzE5DgZIdBn4R+47-~)ub)c4*a&-{Iq~Xf3ym-P;MGa;Z zRzai@`Y8`pLwf;LEFhk0yc()BH?9|$uXiXN+${r7Jx1x0u_f*yp3EM=(}0)8BsL?% zypvCoq?BET0RdXIy};qD2DcGh&N!yE!#aimhD#bPP1Ee85HEhP!VXk1Pv6PB=L#Np z$WGk0^TY}GERLg=1K}gsz-S~p)*$j}k~~XA+>cUJ$x-cm&|W)Z0sxMk=d|JM^eb#? zJGuih>>w59kkD(`vR{s7bMz+wnLcTc^{k4Cu%YSVjt<=E3}@FCf$oUqU`T1ykvxpewRJ2clg+03X(nRyOsH{>Z>d9yZE6s!ZDDIyV267(-tQ{^L-5^~<~CKV z9)AXS*gFB9aPV}2Dux169MbbSZ~3xv<#J#|B90!$yFL~ViKTS3ONy8~VyMaK=th3= z$c`N162izK?&x6FI>XsHxG-lFEgmR0IJx%(=^Gy+vi@S8U=#aKVz+aIU-iZcAW5;g z1d$t{xuL>BNhIkkG>FxLj4#h?pIdC@wUWiN78Vy4n>3P`ZXuYo2=EY%06!vXo>d4? zuGRf8&eJ&o_i+S^N8&zdjpMiv=wJa_5(_2aEZw5`g@PNlr$I`GX-^3561^C^6B&I- zhZbL!P-9%KuPN!n1ry0@q9RI=(0nY++(uiC*HjYbo<2!rbFU5y}LtqbT_7_uW@z;1XsXsT&$Q0l>&5po59A?uv zD{k_^8Kjg7_vL}i39U_9j7AThw8L_Q9+r@l!-FdqiUph(4M}myp(mL|lI)P?nxotG z{S6=1Z70VXrD+J@@`;Zc`pfJXBDMgbBS|JEA+w^3VDdEJO93u^Ih>MKt;t80Q^8p| z1`sCTII#AYtf9C^m~|(q+m+b;sE){|K; z>MPV6n_Aa>Ce#G=9q3^hi%_d4hlMcH`NR0(mlFfcmrC=p_u*TOx3^Deni0!?wLkt0}myxo=c{{&UoD|68Ap7V#|u&3Wf@#V4N1ixDS4Iw@z zF1{z#K1r0p$&L&ira4yip+Q`M^q9a}wW=*<;mdw!pSzwO_M4s5UTxWD*s>%%xjyH? zE!m!w{t$ZhaTm$(iW$bUL=|F_MyMG_A_RvKCxY-WBCVx|5#3>4#xT0c?co(nQ3&)7 zJtd?zOR+6W`Pn5;n)^TsDz>N{!?yQ61vl88ZD*7+Si*qbob!h?VO`_53CX$;1o~n` z-;+IslWS*7GZb9Z3=*A`vuCJ@CJ{eu?;S_AowDswXsX#7g5vmD0!X zCGM$9KtPW5D7q^?;i}~H$FacHUizCLfSI&EqNC|A#=@#)n76LSk9O1F1VuspWt4b$ zj0vXYWEI=XF_;xl92#N=pW;^v!%I`do^%*Q-{=}&*fKqHwGbBCwpL2A}H7mmHhqF2f!h4qFOKael?4u$01C zbxoZ(=|ad7PhDq6W5{ZdP`v^_1JuS~VAvSmUDB!b^NjLKx_4|TSB>t~1QSJ@h*z5N zx*i8!u!E(T4jc^AFoJzox>bvl^>H@@E9I(7q{P@?rF82d0679IC&Vzo>IsppMt4q# zWczC1hOx&_D!`BNE9~r2jg8p+7*AzyWfTDrikNd@H%3lIor_x=k1KSwEog46uRUg3 zo0wZ>v~|`uHFr#Dozr&F2uxKAu;Ez*Z*ux&P=jkf;GC!#M(#-t(DRL)eg@VplKm#) z)wQ)Wg{|O+g{<|R$e8K z22A3qL|{OOKkoshE0~rkK%h*=k47V6^ILWN7-7pP+gM@iPbgrUi>FR>yRp_2C^FJI zK!;(M(jA9x@Kn!fjxu^qj%+kw z9ayR%YoxarDBfGaz5s_KVM9|Q;ZCAEJLzzI^LXti6{0Q!^&=0?4i$Wa@+fa=TLEaw zdICfzF`G?Tqn#w^Bc9xAkyclIJc2j9O@m3`oUHOBu(EwR_~Up=a24&)8Sfn1DNL6A zfA-!4z>eZN7w)cJZr^+7&aQpoYC#$n4T8}!S}z zpO1SMdk80O%H#be#IcWAU(U6+nZk-S~mepN%G3^(X|eZ@+SFYeI+eKkg!Qk&v*Ci-gloE6Eo>BstN z1{=_i_0(gcna(UlOi1^nDYJBB zrtvwY-%QM~h*G6#H(i_5+mJ4eOzCu~R!D*zZ+@A4e?}IUPL`4bfWci!uw>YP_=c!t zs*|>jCdM2MrZ2Q@3X?K|B^%R_%n*eaYUwe`zyKDP{az8yO3ZmU&a==3=e+97Sj&Zo z&h48Z3DTh$ms2};cOc%!)<2kX$6{>rt_hVFCV zGSoRlXt`+-4dL{?zn$9$VR}#c5))4dXZvg1Rmfet0+E<`37nhuIr$#$F@#l-a8=|7 z^i1?&f8}zY%g5!Hg!oj>xn`ep&RY6sQ(noirP500J^P#)J-*Y=!go3M>~k(-$*>;a z0pD4L4Bxp=YxGV^CW-7dHtRau?$Lt6HZ1B^xQtwKRA5xj)BW|?c7>fs|8E_uC2r6yUN#;GtN4$ z?;hH=rhM)Az^^aMwd&=2Ow$0vkgd!(4kPevufSw&p~Tso^%fwB#r zrZG1qwkLSPe<1Z@MB#4)#Q(28LUCR zxboG`Rg5F|L-0Q4@Qm-&(Mb^>s@3LT?&PrGad*F#%G~}Xcs())8z&d{=v+UR**^H; zx);9qoqJxp_g;Twh4iHn@kCAVCoEUoZ)>)=RCTmAS<8^UL~+Ia5w(#m#zNqWv5;a% z@fgV&D-c}tsetS-vfaRy^s~jcS|5&HytpqGsA36Eqo@Qs#S&Bx@@!C&D-YG3fz+WE z97%#9tCS#^gfWZZT@wULCz}Z8_-vYUta3aGY!jz@N$dMah0uWSxUN{@v=>9J5q>9H6|>6LJd(!)ql^PxC3R|0Yoss4ETo9O;p)SSeQw|lsT zz*9@Csr4+`qy{MkBYs;FEEzU)g>aZj0$0KY)`hoqRshU*2K_FJSOS=oMbu!yF@Yt^ z0T_dtn_`|Ouw+&So{MA#oz|3l7O;ev^+#$uU;A1Ad4876mE&D&C`N51zx=fQ3taGJ zGS2eTV&(t3XCGyyr-hUIB|ZeA@O5{`{hc8km#;c4Qp~#7hTiDh`dlY9RHu$C7_V5- zDfSAd?={3ejD)^3wFm3NoZUz$?zR8J8QkQQs1Gk!JMB`4!|V8d@gKG`_?k0y?M>>@ zDk|pudYaoDjR3G(EhTsE-hTPcA?%+E)$7_5Sx5b5CLaCGh>em*$3o!Iv5@4*m9UzJ z3&W76z7yr5l)qc8KTE~@D2fTU*1gsG`%0AhW=V_i7vKS(O{y3+s*aVWn3Rx^21zL{ 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 z Date: Wed, 14 Jan 2026 17:27:03 -0600 Subject: [PATCH 02/26] feat: add mocks Signed-off-by: Pablo --- .mockery.yaml | 1 + mocks/option.go | 65 ++++++++++ mocks/proposal_interface.go | 241 ++++++++++++++++++++++++++++++++++++ mocks/proposal_option.go | 65 ++++++++++ mocks/signer.go | 151 ++++++++++++++++++++++ 5 files changed, 523 insertions(+) create mode 100644 mocks/option.go create mode 100644 mocks/proposal_interface.go create mode 100644 mocks/proposal_option.go create mode 100644 mocks/signer.go diff --git a/.mockery.yaml b/.mockery.yaml index 5939bed9a..f68d21894 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -14,6 +14,7 @@ mockname: "{{.InterfaceName}}" inpackage: false outpkg: mocks packages: + github.com/smartcontractkit/mcms: github.com/smartcontractkit/mcms/sdk: github.com/smartcontractkit/mcms/sdk/evm: github.com/smartcontractkit/mcms/sdk/evm/bindings: diff --git a/mocks/option.go b/mocks/option.go new file mode 100644 index 000000000..0f67c9520 --- /dev/null +++ b/mocks/option.go @@ -0,0 +1,65 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// Option is an autogenerated mock type for the Option type +type Option struct { + mock.Mock +} + +type Option_Expecter struct { + mock *mock.Mock +} + +func (_m *Option) EXPECT() *Option_Expecter { + return &Option_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: _a0 +func (_m *Option) Execute(_a0 *mcms.executeOptions) { + _m.Called(_a0) +} + +// Option_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type Option_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - _a0 *mcms.executeOptions +func (_e *Option_Expecter) Execute(_a0 interface{}) *Option_Execute_Call { + return &Option_Execute_Call{Call: _e.mock.On("Execute", _a0)} +} + +func (_c *Option_Execute_Call) Run(run func(_a0 *mcms.executeOptions)) *Option_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*mcms.executeOptions)) + }) + return _c +} + +func (_c *Option_Execute_Call) Return() *Option_Execute_Call { + _c.Call.Return() + return _c +} + +func (_c *Option_Execute_Call) RunAndReturn(run func(*mcms.executeOptions)) *Option_Execute_Call { + _c.Run(run) + return _c +} + +// NewOption creates a new instance of Option. 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 NewOption(t interface { + mock.TestingT + Cleanup(func()) +}) *Option { + mock := &Option{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/proposal_interface.go b/mocks/proposal_interface.go new file mode 100644 index 000000000..90ef7aa56 --- /dev/null +++ b/mocks/proposal_interface.go @@ -0,0 +1,241 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mocks + +import ( + types "github.com/smartcontractkit/mcms/types" + mock "github.com/stretchr/testify/mock" +) + +// ProposalInterface is an autogenerated mock type for the ProposalInterface type +type ProposalInterface struct { + mock.Mock +} + +type ProposalInterface_Expecter struct { + mock *mock.Mock +} + +func (_m *ProposalInterface) EXPECT() *ProposalInterface_Expecter { + return &ProposalInterface_Expecter{mock: &_m.Mock} +} + +// AppendSignature provides a mock function with given fields: signature +func (_m *ProposalInterface) AppendSignature(signature types.Signature) { + _m.Called(signature) +} + +// ProposalInterface_AppendSignature_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AppendSignature' +type ProposalInterface_AppendSignature_Call struct { + *mock.Call +} + +// AppendSignature is a helper method to define mock.On call +// - signature types.Signature +func (_e *ProposalInterface_Expecter) AppendSignature(signature interface{}) *ProposalInterface_AppendSignature_Call { + return &ProposalInterface_AppendSignature_Call{Call: _e.mock.On("AppendSignature", signature)} +} + +func (_c *ProposalInterface_AppendSignature_Call) Run(run func(signature types.Signature)) *ProposalInterface_AppendSignature_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Signature)) + }) + return _c +} + +func (_c *ProposalInterface_AppendSignature_Call) Return() *ProposalInterface_AppendSignature_Call { + _c.Call.Return() + return _c +} + +func (_c *ProposalInterface_AppendSignature_Call) RunAndReturn(run func(types.Signature)) *ProposalInterface_AppendSignature_Call { + _c.Run(run) + return _c +} + +// ChainMetadatas provides a mock function with no fields +func (_m *ProposalInterface) ChainMetadatas() map[types.ChainSelector]types.ChainMetadata { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for ChainMetadatas") + } + + var r0 map[types.ChainSelector]types.ChainMetadata + if rf, ok := ret.Get(0).(func() map[types.ChainSelector]types.ChainMetadata); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[types.ChainSelector]types.ChainMetadata) + } + } + + return r0 +} + +// ProposalInterface_ChainMetadatas_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainMetadatas' +type ProposalInterface_ChainMetadatas_Call struct { + *mock.Call +} + +// ChainMetadatas is a helper method to define mock.On call +func (_e *ProposalInterface_Expecter) ChainMetadatas() *ProposalInterface_ChainMetadatas_Call { + return &ProposalInterface_ChainMetadatas_Call{Call: _e.mock.On("ChainMetadatas")} +} + +func (_c *ProposalInterface_ChainMetadatas_Call) Run(run func()) *ProposalInterface_ChainMetadatas_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ProposalInterface_ChainMetadatas_Call) Return(_a0 map[types.ChainSelector]types.ChainMetadata) *ProposalInterface_ChainMetadatas_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ProposalInterface_ChainMetadatas_Call) RunAndReturn(run func() map[types.ChainSelector]types.ChainMetadata) *ProposalInterface_ChainMetadatas_Call { + _c.Call.Return(run) + return _c +} + +// TransactionCounts provides a mock function with no fields +func (_m *ProposalInterface) TransactionCounts() map[types.ChainSelector]uint64 { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for TransactionCounts") + } + + var r0 map[types.ChainSelector]uint64 + if rf, ok := ret.Get(0).(func() map[types.ChainSelector]uint64); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[types.ChainSelector]uint64) + } + } + + return r0 +} + +// ProposalInterface_TransactionCounts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransactionCounts' +type ProposalInterface_TransactionCounts_Call struct { + *mock.Call +} + +// TransactionCounts is a helper method to define mock.On call +func (_e *ProposalInterface_Expecter) TransactionCounts() *ProposalInterface_TransactionCounts_Call { + return &ProposalInterface_TransactionCounts_Call{Call: _e.mock.On("TransactionCounts")} +} + +func (_c *ProposalInterface_TransactionCounts_Call) Run(run func()) *ProposalInterface_TransactionCounts_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ProposalInterface_TransactionCounts_Call) Return(_a0 map[types.ChainSelector]uint64) *ProposalInterface_TransactionCounts_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ProposalInterface_TransactionCounts_Call) RunAndReturn(run func() map[types.ChainSelector]uint64) *ProposalInterface_TransactionCounts_Call { + _c.Call.Return(run) + return _c +} + +// Validate provides a mock function with no fields +func (_m *ProposalInterface) Validate() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Validate") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ProposalInterface_Validate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Validate' +type ProposalInterface_Validate_Call struct { + *mock.Call +} + +// Validate is a helper method to define mock.On call +func (_e *ProposalInterface_Expecter) Validate() *ProposalInterface_Validate_Call { + return &ProposalInterface_Validate_Call{Call: _e.mock.On("Validate")} +} + +func (_c *ProposalInterface_Validate_Call) Run(run func()) *ProposalInterface_Validate_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ProposalInterface_Validate_Call) Return(_a0 error) *ProposalInterface_Validate_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ProposalInterface_Validate_Call) RunAndReturn(run func() error) *ProposalInterface_Validate_Call { + _c.Call.Return(run) + return _c +} + +// setChainMetadata provides a mock function with given fields: chainSelector, metadata +func (_m *ProposalInterface) setChainMetadata(chainSelector types.ChainSelector, metadata types.ChainMetadata) { + _m.Called(chainSelector, metadata) +} + +// ProposalInterface_setChainMetadata_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'setChainMetadata' +type ProposalInterface_setChainMetadata_Call struct { + *mock.Call +} + +// setChainMetadata is a helper method to define mock.On call +// - chainSelector types.ChainSelector +// - metadata types.ChainMetadata +func (_e *ProposalInterface_Expecter) setChainMetadata(chainSelector interface{}, metadata interface{}) *ProposalInterface_setChainMetadata_Call { + return &ProposalInterface_setChainMetadata_Call{Call: _e.mock.On("setChainMetadata", chainSelector, metadata)} +} + +func (_c *ProposalInterface_setChainMetadata_Call) Run(run func(chainSelector types.ChainSelector, metadata types.ChainMetadata)) *ProposalInterface_setChainMetadata_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.ChainSelector), args[1].(types.ChainMetadata)) + }) + return _c +} + +func (_c *ProposalInterface_setChainMetadata_Call) Return() *ProposalInterface_setChainMetadata_Call { + _c.Call.Return() + return _c +} + +func (_c *ProposalInterface_setChainMetadata_Call) RunAndReturn(run func(types.ChainSelector, types.ChainMetadata)) *ProposalInterface_setChainMetadata_Call { + _c.Run(run) + return _c +} + +// NewProposalInterface creates a new instance of ProposalInterface. 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 NewProposalInterface(t interface { + mock.TestingT + Cleanup(func()) +}) *ProposalInterface { + mock := &ProposalInterface{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/proposal_option.go b/mocks/proposal_option.go new file mode 100644 index 000000000..1b377e645 --- /dev/null +++ b/mocks/proposal_option.go @@ -0,0 +1,65 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// ProposalOption is an autogenerated mock type for the ProposalOption type +type ProposalOption struct { + mock.Mock +} + +type ProposalOption_Expecter struct { + mock *mock.Mock +} + +func (_m *ProposalOption) EXPECT() *ProposalOption_Expecter { + return &ProposalOption_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: _a0 +func (_m *ProposalOption) Execute(_a0 *mcms.proposalOptions) { + _m.Called(_a0) +} + +// ProposalOption_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type ProposalOption_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - _a0 *mcms.proposalOptions +func (_e *ProposalOption_Expecter) Execute(_a0 interface{}) *ProposalOption_Execute_Call { + return &ProposalOption_Execute_Call{Call: _e.mock.On("Execute", _a0)} +} + +func (_c *ProposalOption_Execute_Call) Run(run func(_a0 *mcms.proposalOptions)) *ProposalOption_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*mcms.proposalOptions)) + }) + return _c +} + +func (_c *ProposalOption_Execute_Call) Return() *ProposalOption_Execute_Call { + _c.Call.Return() + return _c +} + +func (_c *ProposalOption_Execute_Call) RunAndReturn(run func(*mcms.proposalOptions)) *ProposalOption_Execute_Call { + _c.Run(run) + return _c +} + +// NewProposalOption creates a new instance of ProposalOption. 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 NewProposalOption(t interface { + mock.TestingT + Cleanup(func()) +}) *ProposalOption { + mock := &ProposalOption{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/signer.go b/mocks/signer.go new file mode 100644 index 000000000..9e4fe1acd --- /dev/null +++ b/mocks/signer.go @@ -0,0 +1,151 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mocks + +import ( + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" +) + +// signer is an autogenerated mock type for the signer type +type signer struct { + mock.Mock +} + +type signer_Expecter struct { + mock *mock.Mock +} + +func (_m *signer) EXPECT() *signer_Expecter { + return &signer_Expecter{mock: &_m.Mock} +} + +// GetAddress provides a mock function with no fields +func (_m *signer) GetAddress() (common.Address, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetAddress") + } + + var r0 common.Address + var r1 error + if rf, ok := ret.Get(0).(func() (common.Address, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() common.Address); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(common.Address) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// signer_GetAddress_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAddress' +type signer_GetAddress_Call struct { + *mock.Call +} + +// GetAddress is a helper method to define mock.On call +func (_e *signer_Expecter) GetAddress() *signer_GetAddress_Call { + return &signer_GetAddress_Call{Call: _e.mock.On("GetAddress")} +} + +func (_c *signer_GetAddress_Call) Run(run func()) *signer_GetAddress_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *signer_GetAddress_Call) Return(_a0 common.Address, _a1 error) *signer_GetAddress_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *signer_GetAddress_Call) RunAndReturn(run func() (common.Address, error)) *signer_GetAddress_Call { + _c.Call.Return(run) + return _c +} + +// Sign provides a mock function with given fields: payload +func (_m *signer) Sign(payload []byte) ([]byte, error) { + ret := _m.Called(payload) + + if len(ret) == 0 { + panic("no return value specified for Sign") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func([]byte) ([]byte, error)); ok { + return rf(payload) + } + if rf, ok := ret.Get(0).(func([]byte) []byte); ok { + r0 = rf(payload) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func([]byte) error); ok { + r1 = rf(payload) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// signer_Sign_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Sign' +type signer_Sign_Call struct { + *mock.Call +} + +// Sign is a helper method to define mock.On call +// - payload []byte +func (_e *signer_Expecter) Sign(payload interface{}) *signer_Sign_Call { + return &signer_Sign_Call{Call: _e.mock.On("Sign", payload)} +} + +func (_c *signer_Sign_Call) Run(run func(payload []byte)) *signer_Sign_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]byte)) + }) + return _c +} + +func (_c *signer_Sign_Call) Return(_a0 []byte, _a1 error) *signer_Sign_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *signer_Sign_Call) RunAndReturn(run func([]byte) ([]byte, error)) *signer_Sign_Call { + _c.Call.Return(run) + return _c +} + +// newSigner creates a new instance of signer. 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 newSigner(t interface { + mock.TestingT + Cleanup(func()) +}) *signer { + mock := &signer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} From 5848e84187f7504b787f602769c25b280d940991 Mon Sep 17 00:00:00 2001 From: Pablo Date: Thu, 15 Jan 2026 11:57:12 -0600 Subject: [PATCH 03/26] feat: refactor to use chain access interface instead Signed-off-by: Pablo --- .mockery.yaml | 2 +- .../integrating-new-chain-guide.md | 36 +- inspectors/inspectors.go | 32 +- inspectors/inspectors_test.go | 113 ++++-- inspectors/mocks/inspector_fetcher.go | 98 ++++++ mocks/option.go | 65 ---- mocks/proposal_interface.go | 241 ------------- mocks/proposal_option.go | 65 ---- mocks/signer.go | 151 -------- sdk/chainclient.go | 28 +- sdk/mocks/block_chains.go | 223 ------------ sdk/mocks/chain_access.go | 329 ++++++++++++++++++ sdk/mocks/chain_client.go | 82 ----- sdk/mocks/evm_chain_client.go | 82 ----- sdk/mocks/solana_chain_client.go | 82 ----- sdk/mocks/sui_chain_client.go | 131 ------- 16 files changed, 567 insertions(+), 1193 deletions(-) create mode 100644 inspectors/mocks/inspector_fetcher.go delete mode 100644 mocks/option.go delete mode 100644 mocks/proposal_interface.go delete mode 100644 mocks/proposal_option.go delete mode 100644 mocks/signer.go delete mode 100644 sdk/mocks/block_chains.go create mode 100644 sdk/mocks/chain_access.go delete mode 100644 sdk/mocks/chain_client.go delete mode 100644 sdk/mocks/evm_chain_client.go delete mode 100644 sdk/mocks/solana_chain_client.go delete mode 100644 sdk/mocks/sui_chain_client.go diff --git a/.mockery.yaml b/.mockery.yaml index f68d21894..26ca3c0bb 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -14,7 +14,7 @@ mockname: "{{.InterfaceName}}" inpackage: false outpkg: mocks packages: - github.com/smartcontractkit/mcms: + 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/docs/docs/contributing/integrating-new-chain-guide.md b/docs/docs/contributing/integrating-new-chain-guide.md index 432faed82..fe8ac5da8 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 index 9db3930ce..9e4dd3ce7 100644 --- a/inspectors/inspectors.go +++ b/inspectors/inspectors.go @@ -22,10 +22,10 @@ type InspectorFetcher interface { var _ InspectorFetcher = (*MCMInspectorFetcher)(nil) type MCMInspectorFetcher struct { - chains sdk.BlockChains + chains sdk.ChainAccess } -func NewMCMInspectorFetcher(chains sdk.BlockChains) *MCMInspectorFetcher { +func NewMCMInspectorFetcher(chains sdk.ChainAccess) *MCMInspectorFetcher { return &MCMInspectorFetcher{chains: chains} } @@ -46,7 +46,7 @@ func (b *MCMInspectorFetcher) FetchInspectors( } // GetInspectorFromChainSelector returns an inspector for the given chain selector and chain clients -func GetInspectorFromChainSelector(chains sdk.BlockChains, selector uint64, proposal *mcms.TimelockProposal) (sdk.Inspector, error) { +func GetInspectorFromChainSelector(chains sdk.ChainAccess, selector uint64, proposal *mcms.TimelockProposal) (sdk.Inspector, error) { fam, err := types.GetChainSelectorFamily(types.ChainSelector(selector)) if err != nil { return nil, fmt.Errorf("error getting chainClient family: %w", err) @@ -56,23 +56,37 @@ func GetInspectorFromChainSelector(chains sdk.BlockChains, selector uint64, prop var inspector sdk.Inspector switch fam { case chainsel.FamilyEVM: - inspector = evm.NewInspector(chains.EVMChains()[selector].GetClient()) + client, ok := chains.EVMClient(selector) + if !ok { + return nil, fmt.Errorf("missing EVM chain client for selector %d", selector) + } + inspector = evm.NewInspector(client) case chainsel.FamilySolana: - inspector = solana.NewInspector(chains.SolanaChains()[selector].GetClient()) + client, ok := chains.SolanaClient(selector) + if !ok { + return nil, fmt.Errorf("missing Solana chain client for selector %d", selector) + } + inspector = solana.NewInspector(client) case chainsel.FamilyAptos: role, err := chainsmetadata.AptosRoleFromAction(action) if err != nil { return nil, fmt.Errorf("error getting aptos role from proposal: %w", err) } - chainClient := chains.AptosChains()[selector] - inspector = aptos.NewInspector(chainClient.GetClient(), role) + client, ok := chains.AptosClient(selector) + if !ok { + return nil, fmt.Errorf("missing Aptos chain client for selector %d", selector) + } + inspector = aptos.NewInspector(client, role) case chainsel.FamilySui: metadata, err := chainsmetadata.SuiMetadata(proposal.ChainMetadata[types.ChainSelector(selector)]) if err != nil { return nil, fmt.Errorf("error getting sui metadata from proposal: %w", err) } - chain := chains.SuiChains()[selector] - inspector, err = sui.NewInspector(chain.GetClient(), chain.GetSigner(), metadata.McmsPackageID, metadata.Role) + client, signer, ok := chains.Sui(selector) + if !ok { + return nil, fmt.Errorf("missing Sui chain client for selector %d", selector) + } + inspector, err = sui.NewInspector(client, signer, metadata.McmsPackageID, metadata.Role) if err != nil { return nil, fmt.Errorf("error creating sui inspector: %w", err) } diff --git a/inspectors/inspectors_test.go b/inspectors/inspectors_test.go index 8a402ece6..24054ce72 100644 --- a/inspectors/inspectors_test.go +++ b/inspectors/inspectors_test.go @@ -3,12 +3,14 @@ package inspectors import ( "testing" + aptoslib "github.com/aptos-labs/aptos-go-sdk" + "github.com/block-vision/sui-go-sdk/sui" + solrpc "github.com/gagliardetto/solana-go/rpc" chainsel "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms" "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/sdk/mocks" mcmsTypes "github.com/smartcontractkit/mcms/types" ) @@ -18,9 +20,7 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { tests := []struct { name string chainMetadata map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata - chainClientsEVM map[uint64]sdk.EVMChainClient - setup func(evmClients map[uint64]sdk.EVMChainClient, solanaClients map[uint64]sdk.SolanaChainClient) - chainClientsSolana map[uint64]sdk.SolanaChainClient + chainAccess sdk.ChainAccess expectErr bool errContains string expectedInspectorsCount int @@ -28,19 +28,17 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { { name: "empty input", chainMetadata: map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata{}, - chainClientsEVM: map[uint64]sdk.EVMChainClient{ - chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector: mocks.NewEVMChainClient(t), - }, - expectErr: false, + chainAccess: &fakeChainAccess{}, + expectErr: false, }, { name: "missing chain client", chainMetadata: map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata{ 1: {MCMAddress: "0xabc", StartingOpCount: 0}, }, - chainClientsEVM: map[uint64]sdk.EVMChainClient{}, - expectErr: true, - errContains: "error getting inspector for chain selector 1: error getting chainClient family: chain family not found for selector 1", + chainAccess: &fakeChainAccess{}, + expectErr: true, + errContains: "error getting inspector for chain selector 1: error getting chainClient family: chain family not found for selector 1", }, { name: "valid input", @@ -48,17 +46,19 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { mcmsTypes.ChainSelector(chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector): {MCMAddress: "0xabc", StartingOpCount: 0}, mcmsTypes.ChainSelector(chainsel.SOLANA_DEVNET.Selector): {MCMAddress: "0xabc", StartingOpCount: 0}, }, - chainClientsEVM: map[uint64]sdk.EVMChainClient{ - chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector: mocks.NewEVMChainClient(t), - }, - chainClientsSolana: map[uint64]sdk.SolanaChainClient{ - chainsel.SOLANA_DEVNET.Selector: mocks.NewSolanaChainClient(t), - }, - expectErr: false, - setup: func(evmClients map[uint64]sdk.EVMChainClient, solanaClients map[uint64]sdk.SolanaChainClient) { - evmClients[chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector].(*mocks.EVMChainClient).EXPECT().GetClient().Return(nil).Once() - solanaClients[chainsel.SOLANA_DEVNET.Selector].(*mocks.SolanaChainClient).EXPECT().GetClient().Return(nil).Once() + chainAccess: &fakeChainAccess{ + selectors: []uint64{ + chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector, + chainsel.SOLANA_DEVNET.Selector, + }, + evmClients: map[uint64]sdk.ContractDeployBackend{ + chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector: nil, + }, + solanaClients: map[uint64]*solrpc.Client{ + chainsel.SOLANA_DEVNET.Selector: nil, + }, }, + expectErr: false, expectedInspectorsCount: 2, }, } @@ -66,15 +66,11 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { t.Parallel() - allChains := mocks.NewBlockChains(t) - - if tc.expectedInspectorsCount > 0 { - tc.setup(tc.chainClientsEVM, tc.chainClientsSolana) - allChains.EXPECT().EVMChains().Return(tc.chainClientsEVM) - allChains.EXPECT().SolanaChains().Return(tc.chainClientsSolana) + if tc.chainAccess == nil { + tc.chainAccess = &fakeChainAccess{} } - builder := NewMCMInspectorFetcher(allChains) + builder := NewMCMInspectorFetcher(tc.chainAccess) inspectors, err := builder.FetchInspectors(tc.chainMetadata, &mcms.TimelockProposal{}) if tc.expectErr { require.Error(t, err) @@ -86,3 +82,64 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { }) } } + +type fakeChainAccess struct { + selectors []uint64 + evmClients map[uint64]sdk.ContractDeployBackend + solanaClients map[uint64]*solrpc.Client + aptosClients map[uint64]aptoslib.AptosRpcClient + suiClients map[uint64]struct { + client sui.ISuiAPI + signer sdk.SuiSigner + } +} + +var _ sdk.ChainAccess = (*fakeChainAccess)(nil) + +func (f *fakeChainAccess) Selectors() []uint64 { + if f == nil { + return nil + } + + return f.selectors +} + +func (f *fakeChainAccess) EVMClient(selector uint64) (sdk.ContractDeployBackend, bool) { + if f == nil || f.evmClients == nil { + return nil, false + } + client, ok := f.evmClients[selector] + + return client, ok +} + +func (f *fakeChainAccess) SolanaClient(selector uint64) (*solrpc.Client, bool) { + if f == nil || f.solanaClients == nil { + return nil, false + } + client, ok := f.solanaClients[selector] + + return client, ok +} + +func (f *fakeChainAccess) AptosClient(selector uint64) (aptoslib.AptosRpcClient, bool) { + if f == nil || f.aptosClients == nil { + var zero aptoslib.AptosRpcClient + return zero, false + } + client, ok := f.aptosClients[selector] + + return client, ok +} + +func (f *fakeChainAccess) Sui(selector uint64) (sui.ISuiAPI, sdk.SuiSigner, bool) { + if f == nil || f.suiClients == nil { + return nil, nil, false + } + client, ok := f.suiClients[selector] + if !ok { + return nil, nil, false + } + + return client.client, client.signer, true +} diff --git a/inspectors/mocks/inspector_fetcher.go b/inspectors/mocks/inspector_fetcher.go new file mode 100644 index 000000000..3d3dbf325 --- /dev/null +++ b/inspectors/mocks/inspector_fetcher.go @@ -0,0 +1,98 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mocks + +import ( + mcms "github.com/smartcontractkit/mcms" + mock "github.com/stretchr/testify/mock" + + sdk "github.com/smartcontractkit/mcms/sdk" + + 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, proposal +func (_m *InspectorFetcher) FetchInspectors(chainMetadata map[types.ChainSelector]types.ChainMetadata, proposal *mcms.TimelockProposal) (map[types.ChainSelector]sdk.Inspector, error) { + ret := _m.Called(chainMetadata, proposal) + + 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, *mcms.TimelockProposal) (map[types.ChainSelector]sdk.Inspector, error)); ok { + return rf(chainMetadata, proposal) + } + if rf, ok := ret.Get(0).(func(map[types.ChainSelector]types.ChainMetadata, *mcms.TimelockProposal) map[types.ChainSelector]sdk.Inspector); ok { + r0 = rf(chainMetadata, proposal) + } 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, *mcms.TimelockProposal) error); ok { + r1 = rf(chainMetadata, proposal) + } 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 +// - proposal *mcms.TimelockProposal +func (_e *InspectorFetcher_Expecter) FetchInspectors(chainMetadata interface{}, proposal interface{}) *InspectorFetcher_FetchInspectors_Call { + return &InspectorFetcher_FetchInspectors_Call{Call: _e.mock.On("FetchInspectors", chainMetadata, proposal)} +} + +func (_c *InspectorFetcher_FetchInspectors_Call) Run(run func(chainMetadata map[types.ChainSelector]types.ChainMetadata, proposal *mcms.TimelockProposal)) *InspectorFetcher_FetchInspectors_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(map[types.ChainSelector]types.ChainMetadata), args[1].(*mcms.TimelockProposal)) + }) + 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, *mcms.TimelockProposal) (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/mocks/option.go b/mocks/option.go deleted file mode 100644 index 0f67c9520..000000000 --- a/mocks/option.go +++ /dev/null @@ -1,65 +0,0 @@ -// Code generated by mockery v2.53.5. DO NOT EDIT. - -package mocks - -import mock "github.com/stretchr/testify/mock" - -// Option is an autogenerated mock type for the Option type -type Option struct { - mock.Mock -} - -type Option_Expecter struct { - mock *mock.Mock -} - -func (_m *Option) EXPECT() *Option_Expecter { - return &Option_Expecter{mock: &_m.Mock} -} - -// Execute provides a mock function with given fields: _a0 -func (_m *Option) Execute(_a0 *mcms.executeOptions) { - _m.Called(_a0) -} - -// Option_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' -type Option_Execute_Call struct { - *mock.Call -} - -// Execute is a helper method to define mock.On call -// - _a0 *mcms.executeOptions -func (_e *Option_Expecter) Execute(_a0 interface{}) *Option_Execute_Call { - return &Option_Execute_Call{Call: _e.mock.On("Execute", _a0)} -} - -func (_c *Option_Execute_Call) Run(run func(_a0 *mcms.executeOptions)) *Option_Execute_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*mcms.executeOptions)) - }) - return _c -} - -func (_c *Option_Execute_Call) Return() *Option_Execute_Call { - _c.Call.Return() - return _c -} - -func (_c *Option_Execute_Call) RunAndReturn(run func(*mcms.executeOptions)) *Option_Execute_Call { - _c.Run(run) - return _c -} - -// NewOption creates a new instance of Option. 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 NewOption(t interface { - mock.TestingT - Cleanup(func()) -}) *Option { - mock := &Option{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/mocks/proposal_interface.go b/mocks/proposal_interface.go deleted file mode 100644 index 90ef7aa56..000000000 --- a/mocks/proposal_interface.go +++ /dev/null @@ -1,241 +0,0 @@ -// Code generated by mockery v2.53.5. DO NOT EDIT. - -package mocks - -import ( - types "github.com/smartcontractkit/mcms/types" - mock "github.com/stretchr/testify/mock" -) - -// ProposalInterface is an autogenerated mock type for the ProposalInterface type -type ProposalInterface struct { - mock.Mock -} - -type ProposalInterface_Expecter struct { - mock *mock.Mock -} - -func (_m *ProposalInterface) EXPECT() *ProposalInterface_Expecter { - return &ProposalInterface_Expecter{mock: &_m.Mock} -} - -// AppendSignature provides a mock function with given fields: signature -func (_m *ProposalInterface) AppendSignature(signature types.Signature) { - _m.Called(signature) -} - -// ProposalInterface_AppendSignature_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AppendSignature' -type ProposalInterface_AppendSignature_Call struct { - *mock.Call -} - -// AppendSignature is a helper method to define mock.On call -// - signature types.Signature -func (_e *ProposalInterface_Expecter) AppendSignature(signature interface{}) *ProposalInterface_AppendSignature_Call { - return &ProposalInterface_AppendSignature_Call{Call: _e.mock.On("AppendSignature", signature)} -} - -func (_c *ProposalInterface_AppendSignature_Call) Run(run func(signature types.Signature)) *ProposalInterface_AppendSignature_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Signature)) - }) - return _c -} - -func (_c *ProposalInterface_AppendSignature_Call) Return() *ProposalInterface_AppendSignature_Call { - _c.Call.Return() - return _c -} - -func (_c *ProposalInterface_AppendSignature_Call) RunAndReturn(run func(types.Signature)) *ProposalInterface_AppendSignature_Call { - _c.Run(run) - return _c -} - -// ChainMetadatas provides a mock function with no fields -func (_m *ProposalInterface) ChainMetadatas() map[types.ChainSelector]types.ChainMetadata { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for ChainMetadatas") - } - - var r0 map[types.ChainSelector]types.ChainMetadata - if rf, ok := ret.Get(0).(func() map[types.ChainSelector]types.ChainMetadata); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[types.ChainSelector]types.ChainMetadata) - } - } - - return r0 -} - -// ProposalInterface_ChainMetadatas_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainMetadatas' -type ProposalInterface_ChainMetadatas_Call struct { - *mock.Call -} - -// ChainMetadatas is a helper method to define mock.On call -func (_e *ProposalInterface_Expecter) ChainMetadatas() *ProposalInterface_ChainMetadatas_Call { - return &ProposalInterface_ChainMetadatas_Call{Call: _e.mock.On("ChainMetadatas")} -} - -func (_c *ProposalInterface_ChainMetadatas_Call) Run(run func()) *ProposalInterface_ChainMetadatas_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ProposalInterface_ChainMetadatas_Call) Return(_a0 map[types.ChainSelector]types.ChainMetadata) *ProposalInterface_ChainMetadatas_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ProposalInterface_ChainMetadatas_Call) RunAndReturn(run func() map[types.ChainSelector]types.ChainMetadata) *ProposalInterface_ChainMetadatas_Call { - _c.Call.Return(run) - return _c -} - -// TransactionCounts provides a mock function with no fields -func (_m *ProposalInterface) TransactionCounts() map[types.ChainSelector]uint64 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for TransactionCounts") - } - - var r0 map[types.ChainSelector]uint64 - if rf, ok := ret.Get(0).(func() map[types.ChainSelector]uint64); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[types.ChainSelector]uint64) - } - } - - return r0 -} - -// ProposalInterface_TransactionCounts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransactionCounts' -type ProposalInterface_TransactionCounts_Call struct { - *mock.Call -} - -// TransactionCounts is a helper method to define mock.On call -func (_e *ProposalInterface_Expecter) TransactionCounts() *ProposalInterface_TransactionCounts_Call { - return &ProposalInterface_TransactionCounts_Call{Call: _e.mock.On("TransactionCounts")} -} - -func (_c *ProposalInterface_TransactionCounts_Call) Run(run func()) *ProposalInterface_TransactionCounts_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ProposalInterface_TransactionCounts_Call) Return(_a0 map[types.ChainSelector]uint64) *ProposalInterface_TransactionCounts_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ProposalInterface_TransactionCounts_Call) RunAndReturn(run func() map[types.ChainSelector]uint64) *ProposalInterface_TransactionCounts_Call { - _c.Call.Return(run) - return _c -} - -// Validate provides a mock function with no fields -func (_m *ProposalInterface) Validate() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Validate") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ProposalInterface_Validate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Validate' -type ProposalInterface_Validate_Call struct { - *mock.Call -} - -// Validate is a helper method to define mock.On call -func (_e *ProposalInterface_Expecter) Validate() *ProposalInterface_Validate_Call { - return &ProposalInterface_Validate_Call{Call: _e.mock.On("Validate")} -} - -func (_c *ProposalInterface_Validate_Call) Run(run func()) *ProposalInterface_Validate_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ProposalInterface_Validate_Call) Return(_a0 error) *ProposalInterface_Validate_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ProposalInterface_Validate_Call) RunAndReturn(run func() error) *ProposalInterface_Validate_Call { - _c.Call.Return(run) - return _c -} - -// setChainMetadata provides a mock function with given fields: chainSelector, metadata -func (_m *ProposalInterface) setChainMetadata(chainSelector types.ChainSelector, metadata types.ChainMetadata) { - _m.Called(chainSelector, metadata) -} - -// ProposalInterface_setChainMetadata_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'setChainMetadata' -type ProposalInterface_setChainMetadata_Call struct { - *mock.Call -} - -// setChainMetadata is a helper method to define mock.On call -// - chainSelector types.ChainSelector -// - metadata types.ChainMetadata -func (_e *ProposalInterface_Expecter) setChainMetadata(chainSelector interface{}, metadata interface{}) *ProposalInterface_setChainMetadata_Call { - return &ProposalInterface_setChainMetadata_Call{Call: _e.mock.On("setChainMetadata", chainSelector, metadata)} -} - -func (_c *ProposalInterface_setChainMetadata_Call) Run(run func(chainSelector types.ChainSelector, metadata types.ChainMetadata)) *ProposalInterface_setChainMetadata_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.ChainSelector), args[1].(types.ChainMetadata)) - }) - return _c -} - -func (_c *ProposalInterface_setChainMetadata_Call) Return() *ProposalInterface_setChainMetadata_Call { - _c.Call.Return() - return _c -} - -func (_c *ProposalInterface_setChainMetadata_Call) RunAndReturn(run func(types.ChainSelector, types.ChainMetadata)) *ProposalInterface_setChainMetadata_Call { - _c.Run(run) - return _c -} - -// NewProposalInterface creates a new instance of ProposalInterface. 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 NewProposalInterface(t interface { - mock.TestingT - Cleanup(func()) -}) *ProposalInterface { - mock := &ProposalInterface{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/mocks/proposal_option.go b/mocks/proposal_option.go deleted file mode 100644 index 1b377e645..000000000 --- a/mocks/proposal_option.go +++ /dev/null @@ -1,65 +0,0 @@ -// Code generated by mockery v2.53.5. DO NOT EDIT. - -package mocks - -import mock "github.com/stretchr/testify/mock" - -// ProposalOption is an autogenerated mock type for the ProposalOption type -type ProposalOption struct { - mock.Mock -} - -type ProposalOption_Expecter struct { - mock *mock.Mock -} - -func (_m *ProposalOption) EXPECT() *ProposalOption_Expecter { - return &ProposalOption_Expecter{mock: &_m.Mock} -} - -// Execute provides a mock function with given fields: _a0 -func (_m *ProposalOption) Execute(_a0 *mcms.proposalOptions) { - _m.Called(_a0) -} - -// ProposalOption_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' -type ProposalOption_Execute_Call struct { - *mock.Call -} - -// Execute is a helper method to define mock.On call -// - _a0 *mcms.proposalOptions -func (_e *ProposalOption_Expecter) Execute(_a0 interface{}) *ProposalOption_Execute_Call { - return &ProposalOption_Execute_Call{Call: _e.mock.On("Execute", _a0)} -} - -func (_c *ProposalOption_Execute_Call) Run(run func(_a0 *mcms.proposalOptions)) *ProposalOption_Execute_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*mcms.proposalOptions)) - }) - return _c -} - -func (_c *ProposalOption_Execute_Call) Return() *ProposalOption_Execute_Call { - _c.Call.Return() - return _c -} - -func (_c *ProposalOption_Execute_Call) RunAndReturn(run func(*mcms.proposalOptions)) *ProposalOption_Execute_Call { - _c.Run(run) - return _c -} - -// NewProposalOption creates a new instance of ProposalOption. 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 NewProposalOption(t interface { - mock.TestingT - Cleanup(func()) -}) *ProposalOption { - mock := &ProposalOption{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/mocks/signer.go b/mocks/signer.go deleted file mode 100644 index 9e4fe1acd..000000000 --- a/mocks/signer.go +++ /dev/null @@ -1,151 +0,0 @@ -// Code generated by mockery v2.53.5. DO NOT EDIT. - -package mocks - -import ( - common "github.com/ethereum/go-ethereum/common" - - mock "github.com/stretchr/testify/mock" -) - -// signer is an autogenerated mock type for the signer type -type signer struct { - mock.Mock -} - -type signer_Expecter struct { - mock *mock.Mock -} - -func (_m *signer) EXPECT() *signer_Expecter { - return &signer_Expecter{mock: &_m.Mock} -} - -// GetAddress provides a mock function with no fields -func (_m *signer) GetAddress() (common.Address, error) { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetAddress") - } - - var r0 common.Address - var r1 error - if rf, ok := ret.Get(0).(func() (common.Address, error)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() common.Address); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// signer_GetAddress_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAddress' -type signer_GetAddress_Call struct { - *mock.Call -} - -// GetAddress is a helper method to define mock.On call -func (_e *signer_Expecter) GetAddress() *signer_GetAddress_Call { - return &signer_GetAddress_Call{Call: _e.mock.On("GetAddress")} -} - -func (_c *signer_GetAddress_Call) Run(run func()) *signer_GetAddress_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *signer_GetAddress_Call) Return(_a0 common.Address, _a1 error) *signer_GetAddress_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *signer_GetAddress_Call) RunAndReturn(run func() (common.Address, error)) *signer_GetAddress_Call { - _c.Call.Return(run) - return _c -} - -// Sign provides a mock function with given fields: payload -func (_m *signer) Sign(payload []byte) ([]byte, error) { - ret := _m.Called(payload) - - if len(ret) == 0 { - panic("no return value specified for Sign") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func([]byte) ([]byte, error)); ok { - return rf(payload) - } - if rf, ok := ret.Get(0).(func([]byte) []byte); ok { - r0 = rf(payload) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func([]byte) error); ok { - r1 = rf(payload) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// signer_Sign_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Sign' -type signer_Sign_Call struct { - *mock.Call -} - -// Sign is a helper method to define mock.On call -// - payload []byte -func (_e *signer_Expecter) Sign(payload interface{}) *signer_Sign_Call { - return &signer_Sign_Call{Call: _e.mock.On("Sign", payload)} -} - -func (_c *signer_Sign_Call) Run(run func(payload []byte)) *signer_Sign_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]byte)) - }) - return _c -} - -func (_c *signer_Sign_Call) Return(_a0 []byte, _a1 error) *signer_Sign_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *signer_Sign_Call) RunAndReturn(run func([]byte) ([]byte, error)) *signer_Sign_Call { - _c.Call.Return(run) - return _c -} - -// newSigner creates a new instance of signer. 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 newSigner(t interface { - mock.TestingT - Cleanup(func()) -}) *signer { - mock := &signer{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/sdk/chainclient.go b/sdk/chainclient.go index 6f5177958..9bce514df 100644 --- a/sdk/chainclient.go +++ b/sdk/chainclient.go @@ -16,31 +16,15 @@ type SuiSigner interface { GetAddress() (string, error) } -type SuiChainClient interface { - GetClient() sui.ISuiAPI - GetSigner() SuiSigner -} - -type SolanaChainClient interface { - GetClient() *solrpc.Client -} - type ContractDeployBackend interface { bind.ContractBackend bind.DeployBackend } -type EVMChainClient interface { - GetClient() ContractDeployBackend -} - -type ChainClient interface { - GetClient() aptoslib.AptosRpcClient -} - -type BlockChains interface { - EVMChains() map[uint64]EVMChainClient - SolanaChains() map[uint64]SolanaChainClient - AptosChains() map[uint64]ChainClient - SuiChains() map[uint64]SuiChainClient +type ChainAccess interface { + Selectors() []uint64 + EVMClient(selector uint64) (ContractDeployBackend, bool) + SolanaClient(selector uint64) (*solrpc.Client, bool) + AptosClient(selector uint64) (aptoslib.AptosRpcClient, bool) + Sui(selector uint64) (sui.ISuiAPI, SuiSigner, bool) } diff --git a/sdk/mocks/block_chains.go b/sdk/mocks/block_chains.go deleted file mode 100644 index 7d7564bba..000000000 --- a/sdk/mocks/block_chains.go +++ /dev/null @@ -1,223 +0,0 @@ -// 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" -) - -// BlockChains is an autogenerated mock type for the BlockChains type -type BlockChains struct { - mock.Mock -} - -type BlockChains_Expecter struct { - mock *mock.Mock -} - -func (_m *BlockChains) EXPECT() *BlockChains_Expecter { - return &BlockChains_Expecter{mock: &_m.Mock} -} - -// AptosChains provides a mock function with no fields -func (_m *BlockChains) AptosChains() map[uint64]sdk.ChainClient { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for AptosChains") - } - - var r0 map[uint64]sdk.ChainClient - if rf, ok := ret.Get(0).(func() map[uint64]sdk.ChainClient); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[uint64]sdk.ChainClient) - } - } - - return r0 -} - -// BlockChains_AptosChains_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AptosChains' -type BlockChains_AptosChains_Call struct { - *mock.Call -} - -// AptosChains is a helper method to define mock.On call -func (_e *BlockChains_Expecter) AptosChains() *BlockChains_AptosChains_Call { - return &BlockChains_AptosChains_Call{Call: _e.mock.On("AptosChains")} -} - -func (_c *BlockChains_AptosChains_Call) Run(run func()) *BlockChains_AptosChains_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *BlockChains_AptosChains_Call) Return(_a0 map[uint64]sdk.ChainClient) *BlockChains_AptosChains_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *BlockChains_AptosChains_Call) RunAndReturn(run func() map[uint64]sdk.ChainClient) *BlockChains_AptosChains_Call { - _c.Call.Return(run) - return _c -} - -// EVMChains provides a mock function with no fields -func (_m *BlockChains) EVMChains() map[uint64]sdk.EVMChainClient { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for EVMChains") - } - - var r0 map[uint64]sdk.EVMChainClient - if rf, ok := ret.Get(0).(func() map[uint64]sdk.EVMChainClient); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[uint64]sdk.EVMChainClient) - } - } - - return r0 -} - -// BlockChains_EVMChains_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EVMChains' -type BlockChains_EVMChains_Call struct { - *mock.Call -} - -// EVMChains is a helper method to define mock.On call -func (_e *BlockChains_Expecter) EVMChains() *BlockChains_EVMChains_Call { - return &BlockChains_EVMChains_Call{Call: _e.mock.On("EVMChains")} -} - -func (_c *BlockChains_EVMChains_Call) Run(run func()) *BlockChains_EVMChains_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *BlockChains_EVMChains_Call) Return(_a0 map[uint64]sdk.EVMChainClient) *BlockChains_EVMChains_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *BlockChains_EVMChains_Call) RunAndReturn(run func() map[uint64]sdk.EVMChainClient) *BlockChains_EVMChains_Call { - _c.Call.Return(run) - return _c -} - -// SolanaChains provides a mock function with no fields -func (_m *BlockChains) SolanaChains() map[uint64]sdk.SolanaChainClient { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for SolanaChains") - } - - var r0 map[uint64]sdk.SolanaChainClient - if rf, ok := ret.Get(0).(func() map[uint64]sdk.SolanaChainClient); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[uint64]sdk.SolanaChainClient) - } - } - - return r0 -} - -// BlockChains_SolanaChains_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SolanaChains' -type BlockChains_SolanaChains_Call struct { - *mock.Call -} - -// SolanaChains is a helper method to define mock.On call -func (_e *BlockChains_Expecter) SolanaChains() *BlockChains_SolanaChains_Call { - return &BlockChains_SolanaChains_Call{Call: _e.mock.On("SolanaChains")} -} - -func (_c *BlockChains_SolanaChains_Call) Run(run func()) *BlockChains_SolanaChains_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *BlockChains_SolanaChains_Call) Return(_a0 map[uint64]sdk.SolanaChainClient) *BlockChains_SolanaChains_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *BlockChains_SolanaChains_Call) RunAndReturn(run func() map[uint64]sdk.SolanaChainClient) *BlockChains_SolanaChains_Call { - _c.Call.Return(run) - return _c -} - -// SuiChains provides a mock function with no fields -func (_m *BlockChains) SuiChains() map[uint64]sdk.SuiChainClient { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for SuiChains") - } - - var r0 map[uint64]sdk.SuiChainClient - if rf, ok := ret.Get(0).(func() map[uint64]sdk.SuiChainClient); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[uint64]sdk.SuiChainClient) - } - } - - return r0 -} - -// BlockChains_SuiChains_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SuiChains' -type BlockChains_SuiChains_Call struct { - *mock.Call -} - -// SuiChains is a helper method to define mock.On call -func (_e *BlockChains_Expecter) SuiChains() *BlockChains_SuiChains_Call { - return &BlockChains_SuiChains_Call{Call: _e.mock.On("SuiChains")} -} - -func (_c *BlockChains_SuiChains_Call) Run(run func()) *BlockChains_SuiChains_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *BlockChains_SuiChains_Call) Return(_a0 map[uint64]sdk.SuiChainClient) *BlockChains_SuiChains_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *BlockChains_SuiChains_Call) RunAndReturn(run func() map[uint64]sdk.SuiChainClient) *BlockChains_SuiChains_Call { - _c.Call.Return(run) - return _c -} - -// NewBlockChains creates a new instance of BlockChains. 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 NewBlockChains(t interface { - mock.TestingT - Cleanup(func()) -}) *BlockChains { - mock := &BlockChains{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/sdk/mocks/chain_access.go b/sdk/mocks/chain_access.go new file mode 100644 index 000000000..c3906142d --- /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 +} + +// Sui provides a mock function with given fields: selector +func (_m *ChainAccess) Sui(selector uint64) (sui.ISuiAPI, sdk.SuiSigner, bool) { + ret := _m.Called(selector) + + if len(ret) == 0 { + panic("no return value specified for Sui") + } + + 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_Sui_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Sui' +type ChainAccess_Sui_Call struct { + *mock.Call +} + +// Sui is a helper method to define mock.On call +// - selector uint64 +func (_e *ChainAccess_Expecter) Sui(selector interface{}) *ChainAccess_Sui_Call { + return &ChainAccess_Sui_Call{Call: _e.mock.On("Sui", selector)} +} + +func (_c *ChainAccess_Sui_Call) Run(run func(selector uint64)) *ChainAccess_Sui_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(uint64)) + }) + return _c +} + +func (_c *ChainAccess_Sui_Call) Return(_a0 sui.ISuiAPI, _a1 sdk.SuiSigner, _a2 bool) *ChainAccess_Sui_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *ChainAccess_Sui_Call) RunAndReturn(run func(uint64) (sui.ISuiAPI, sdk.SuiSigner, bool)) *ChainAccess_Sui_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/chain_client.go b/sdk/mocks/chain_client.go deleted file mode 100644 index bf1324bc9..000000000 --- a/sdk/mocks/chain_client.go +++ /dev/null @@ -1,82 +0,0 @@ -// 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" -) - -// ChainClient is an autogenerated mock type for the ChainClient type -type ChainClient struct { - mock.Mock -} - -type ChainClient_Expecter struct { - mock *mock.Mock -} - -func (_m *ChainClient) EXPECT() *ChainClient_Expecter { - return &ChainClient_Expecter{mock: &_m.Mock} -} - -// GetClient provides a mock function with no fields -func (_m *ChainClient) GetClient() aptos.AptosRpcClient { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetClient") - } - - var r0 aptos.AptosRpcClient - if rf, ok := ret.Get(0).(func() aptos.AptosRpcClient); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(aptos.AptosRpcClient) - } - } - - return r0 -} - -// ChainClient_GetClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetClient' -type ChainClient_GetClient_Call struct { - *mock.Call -} - -// GetClient is a helper method to define mock.On call -func (_e *ChainClient_Expecter) GetClient() *ChainClient_GetClient_Call { - return &ChainClient_GetClient_Call{Call: _e.mock.On("GetClient")} -} - -func (_c *ChainClient_GetClient_Call) Run(run func()) *ChainClient_GetClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ChainClient_GetClient_Call) Return(_a0 aptos.AptosRpcClient) *ChainClient_GetClient_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ChainClient_GetClient_Call) RunAndReturn(run func() aptos.AptosRpcClient) *ChainClient_GetClient_Call { - _c.Call.Return(run) - return _c -} - -// NewChainClient creates a new instance of ChainClient. 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 NewChainClient(t interface { - mock.TestingT - Cleanup(func()) -}) *ChainClient { - mock := &ChainClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/sdk/mocks/evm_chain_client.go b/sdk/mocks/evm_chain_client.go deleted file mode 100644 index a9d9db2a5..000000000 --- a/sdk/mocks/evm_chain_client.go +++ /dev/null @@ -1,82 +0,0 @@ -// 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" -) - -// EVMChainClient is an autogenerated mock type for the EVMChainClient type -type EVMChainClient struct { - mock.Mock -} - -type EVMChainClient_Expecter struct { - mock *mock.Mock -} - -func (_m *EVMChainClient) EXPECT() *EVMChainClient_Expecter { - return &EVMChainClient_Expecter{mock: &_m.Mock} -} - -// GetClient provides a mock function with no fields -func (_m *EVMChainClient) GetClient() sdk.ContractDeployBackend { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetClient") - } - - var r0 sdk.ContractDeployBackend - if rf, ok := ret.Get(0).(func() sdk.ContractDeployBackend); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(sdk.ContractDeployBackend) - } - } - - return r0 -} - -// EVMChainClient_GetClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetClient' -type EVMChainClient_GetClient_Call struct { - *mock.Call -} - -// GetClient is a helper method to define mock.On call -func (_e *EVMChainClient_Expecter) GetClient() *EVMChainClient_GetClient_Call { - return &EVMChainClient_GetClient_Call{Call: _e.mock.On("GetClient")} -} - -func (_c *EVMChainClient_GetClient_Call) Run(run func()) *EVMChainClient_GetClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *EVMChainClient_GetClient_Call) Return(_a0 sdk.ContractDeployBackend) *EVMChainClient_GetClient_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *EVMChainClient_GetClient_Call) RunAndReturn(run func() sdk.ContractDeployBackend) *EVMChainClient_GetClient_Call { - _c.Call.Return(run) - return _c -} - -// NewEVMChainClient creates a new instance of EVMChainClient. 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 NewEVMChainClient(t interface { - mock.TestingT - Cleanup(func()) -}) *EVMChainClient { - mock := &EVMChainClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/sdk/mocks/solana_chain_client.go b/sdk/mocks/solana_chain_client.go deleted file mode 100644 index 55e17993d..000000000 --- a/sdk/mocks/solana_chain_client.go +++ /dev/null @@ -1,82 +0,0 @@ -// Code generated by mockery v2.53.5. DO NOT EDIT. - -package mocks - -import ( - rpc "github.com/gagliardetto/solana-go/rpc" - mock "github.com/stretchr/testify/mock" -) - -// SolanaChainClient is an autogenerated mock type for the SolanaChainClient type -type SolanaChainClient struct { - mock.Mock -} - -type SolanaChainClient_Expecter struct { - mock *mock.Mock -} - -func (_m *SolanaChainClient) EXPECT() *SolanaChainClient_Expecter { - return &SolanaChainClient_Expecter{mock: &_m.Mock} -} - -// GetClient provides a mock function with no fields -func (_m *SolanaChainClient) GetClient() *rpc.Client { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetClient") - } - - var r0 *rpc.Client - if rf, ok := ret.Get(0).(func() *rpc.Client); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*rpc.Client) - } - } - - return r0 -} - -// SolanaChainClient_GetClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetClient' -type SolanaChainClient_GetClient_Call struct { - *mock.Call -} - -// GetClient is a helper method to define mock.On call -func (_e *SolanaChainClient_Expecter) GetClient() *SolanaChainClient_GetClient_Call { - return &SolanaChainClient_GetClient_Call{Call: _e.mock.On("GetClient")} -} - -func (_c *SolanaChainClient_GetClient_Call) Run(run func()) *SolanaChainClient_GetClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *SolanaChainClient_GetClient_Call) Return(_a0 *rpc.Client) *SolanaChainClient_GetClient_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SolanaChainClient_GetClient_Call) RunAndReturn(run func() *rpc.Client) *SolanaChainClient_GetClient_Call { - _c.Call.Return(run) - return _c -} - -// NewSolanaChainClient creates a new instance of SolanaChainClient. 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 NewSolanaChainClient(t interface { - mock.TestingT - Cleanup(func()) -}) *SolanaChainClient { - mock := &SolanaChainClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/sdk/mocks/sui_chain_client.go b/sdk/mocks/sui_chain_client.go deleted file mode 100644 index e5fad7bc4..000000000 --- a/sdk/mocks/sui_chain_client.go +++ /dev/null @@ -1,131 +0,0 @@ -// 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" - - sui "github.com/block-vision/sui-go-sdk/sui" -) - -// SuiChainClient is an autogenerated mock type for the SuiChainClient type -type SuiChainClient struct { - mock.Mock -} - -type SuiChainClient_Expecter struct { - mock *mock.Mock -} - -func (_m *SuiChainClient) EXPECT() *SuiChainClient_Expecter { - return &SuiChainClient_Expecter{mock: &_m.Mock} -} - -// GetClient provides a mock function with no fields -func (_m *SuiChainClient) GetClient() sui.ISuiAPI { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetClient") - } - - var r0 sui.ISuiAPI - if rf, ok := ret.Get(0).(func() sui.ISuiAPI); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(sui.ISuiAPI) - } - } - - return r0 -} - -// SuiChainClient_GetClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetClient' -type SuiChainClient_GetClient_Call struct { - *mock.Call -} - -// GetClient is a helper method to define mock.On call -func (_e *SuiChainClient_Expecter) GetClient() *SuiChainClient_GetClient_Call { - return &SuiChainClient_GetClient_Call{Call: _e.mock.On("GetClient")} -} - -func (_c *SuiChainClient_GetClient_Call) Run(run func()) *SuiChainClient_GetClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *SuiChainClient_GetClient_Call) Return(_a0 sui.ISuiAPI) *SuiChainClient_GetClient_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SuiChainClient_GetClient_Call) RunAndReturn(run func() sui.ISuiAPI) *SuiChainClient_GetClient_Call { - _c.Call.Return(run) - return _c -} - -// GetSigner provides a mock function with no fields -func (_m *SuiChainClient) GetSigner() sdk.SuiSigner { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetSigner") - } - - var r0 sdk.SuiSigner - if rf, ok := ret.Get(0).(func() sdk.SuiSigner); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(sdk.SuiSigner) - } - } - - return r0 -} - -// SuiChainClient_GetSigner_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSigner' -type SuiChainClient_GetSigner_Call struct { - *mock.Call -} - -// GetSigner is a helper method to define mock.On call -func (_e *SuiChainClient_Expecter) GetSigner() *SuiChainClient_GetSigner_Call { - return &SuiChainClient_GetSigner_Call{Call: _e.mock.On("GetSigner")} -} - -func (_c *SuiChainClient_GetSigner_Call) Run(run func()) *SuiChainClient_GetSigner_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *SuiChainClient_GetSigner_Call) Return(_a0 sdk.SuiSigner) *SuiChainClient_GetSigner_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SuiChainClient_GetSigner_Call) RunAndReturn(run func() sdk.SuiSigner) *SuiChainClient_GetSigner_Call { - _c.Call.Return(run) - return _c -} - -// NewSuiChainClient creates a new instance of SuiChainClient. 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 NewSuiChainClient(t interface { - mock.TestingT - Cleanup(func()) -}) *SuiChainClient { - mock := &SuiChainClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} From 84d099edbcc73bd08899e56a308ec5d4bd717365 Mon Sep 17 00:00:00 2001 From: Pablo Date: Thu, 15 Jan 2026 11:59:11 -0600 Subject: [PATCH 04/26] fix: use constructor functions for timelock converter Signed-off-by: Pablo --- converters/converters.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/converters/converters.go b/converters/converters.go index d5fb349b2..968db1404 100644 --- a/converters/converters.go +++ b/converters/converters.go @@ -25,9 +25,9 @@ func BuildConvertersForTimelockProposal(proposal mcms.TimelockProposal) (map[typ var converter sdk.TimelockConverter switch fam { case chainsel.FamilyEVM: - converter = evm.TimelockConverter{} + converter = evm.NewTimelockConverter() case chainsel.FamilySolana: - converter = solana.TimelockConverter{} + converter = solana.NewTimelockConverter() case chainsel.FamilyAptos: converter = aptos.NewTimelockConverter() default: From 16ce26980677fc81eb07dbe7ec11c21bc420967f Mon Sep 17 00:00:00 2001 From: Pablo Date: Thu, 15 Jan 2026 15:34:12 -0600 Subject: [PATCH 05/26] feat: add inspector builder and chain accessor interface Signed-off-by: Pablo --- chainsmetadata/sui_helpers_test.go | 96 +++++++++----------------- inspectors/inspectors.go | 76 +++++++++++---------- inspectors/inspectors_test.go | 5 +- inspectors/mocks/inspector_fetcher.go | 34 +++++----- timelock_proposal.go | 47 +++++++++++++ timelock_proposal_test.go | 97 ++++++++++++++++++++++++++- 6 files changed, 230 insertions(+), 125 deletions(-) diff --git a/chainsmetadata/sui_helpers_test.go b/chainsmetadata/sui_helpers_test.go index fe036e806..1df4d45cd 100644 --- a/chainsmetadata/sui_helpers_test.go +++ b/chainsmetadata/sui_helpers_test.go @@ -1,114 +1,78 @@ package chainsmetadata import ( - "encoding/json" "testing" - chainsel "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/mcms" "github.com/smartcontractkit/mcms/sdk/sui" "github.com/smartcontractkit/mcms/types" ) -func buildTestProposalWithMetadata(chainSelector types.ChainSelector, additionalFields string) *mcms.TimelockProposal { - builder := mcms.NewTimelockProposalBuilder() - builder.SetVersion("v1"). - SetAction(types.TimelockActionSchedule). - SetValidUntil(4000000000). - AddTimelockAddress(chainSelector, "0x1234567890123456789012345678901234567890"). - AddChainMetadata(chainSelector, types.ChainMetadata{ - AdditionalFields: []byte(additionalFields), - }). - AddOperation(types.BatchOperation{ - ChainSelector: chainSelector, - Transactions: []types.Transaction{ - { - To: "0x1234567890123456789012345678901234567890", - Data: []byte{0x01}, - AdditionalFields: json.RawMessage(`{}`), - }, - }, - }) - proposal, err := builder.Build() - if err != nil { - panic(err) - } - - return proposal -} - -func TestSuiMetadataFromProposal(t *testing.T) { +func TestSuiMetadata(t *testing.T) { t.Parallel() - chainSelector := types.ChainSelector(chainsel.GETH_TESTNET.Selector) - validMetadataJSON := `{"mcms_package_id":"0x1","role":1,"account_obj":"0x2","registry_obj":"0x3","timelock_obj":"0x4","deployer_state_obj":"0x5"}` - invalidJSON := `{"mcms_package_id":"0x1","role":1` - missingFieldsJSON := `{"role":1}` + 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 - selector types.ChainSelector - proposal *mcms.TimelockProposal + metadata types.ChainMetadata expectError bool errorMsg string }{ { - name: "valid metadata returns success", - selector: chainSelector, - proposal: buildTestProposalWithMetadata(chainSelector, validMetadataJSON), - expectError: false, + name: "valid metadata returns success", + metadata: validMetadata, }, { - name: "invalid JSON returns error", - selector: chainSelector, - proposal: buildTestProposalWithMetadata(chainSelector, invalidJSON), + 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", - selector: chainSelector, - proposal: buildTestProposalWithMetadata(chainSelector, missingFieldsJSON), + 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", - selector: chainSelector, - proposal: buildTestProposalWithMetadata(chainSelector, ""), - expectError: true, - errorMsg: "error unmarshaling sui chain metadata", - }, - { - name: "missing chain selector in metadata", - selector: types.ChainSelector(999), - proposal: buildTestProposalWithMetadata(chainSelector, validMetadataJSON), + 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.proposal.ChainMetadata[tt.selector]) - + 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) - } else { - 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) + + 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/inspectors/inspectors.go b/inspectors/inspectors.go index 9e4dd3ce7..33f0b0f87 100644 --- a/inspectors/inspectors.go +++ b/inspectors/inspectors.go @@ -5,18 +5,17 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/mcms" "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" - "github.com/smartcontractkit/mcms/sdk/sui" + sdkSui "github.com/smartcontractkit/mcms/sdk/sui" "github.com/smartcontractkit/mcms/types" ) type InspectorFetcher interface { - FetchInspectors(chainMetadata map[types.ChainSelector]types.ChainMetadata, proposal *mcms.TimelockProposal) (map[types.ChainSelector]sdk.Inspector, error) + FetchInspectors(chainMetadata map[types.ChainSelector]types.ChainMetadata, action types.TimelockAction) (map[types.ChainSelector]sdk.Inspector, error) } var _ InspectorFetcher = (*MCMInspectorFetcher)(nil) @@ -32,12 +31,12 @@ func NewMCMInspectorFetcher(chains sdk.ChainAccess) *MCMInspectorFetcher { // FetchInspectors gets a map of inspectors for the given chain metadata and chain clients func (b *MCMInspectorFetcher) FetchInspectors( chainMetadata map[types.ChainSelector]types.ChainMetadata, - proposal *mcms.TimelockProposal) (map[types.ChainSelector]sdk.Inspector, error) { + action types.TimelockAction) (map[types.ChainSelector]sdk.Inspector, error) { inspectors := map[types.ChainSelector]sdk.Inspector{} - for chainSelector := range chainMetadata { - inspector, err := GetInspectorFromChainSelector(b.chains, uint64(chainSelector), proposal) + for chainSelector, metadata := range chainMetadata { + inspector, err := BuildInspector(b.chains, chainSelector, action, metadata) if err != nil { - return nil, fmt.Errorf("error getting inspector for chain selector %d: %w", chainSelector, err) + return nil, err } inspectors[chainSelector] = inspector } @@ -45,54 +44,57 @@ func (b *MCMInspectorFetcher) FetchInspectors( return inspectors, nil } -// GetInspectorFromChainSelector returns an inspector for the given chain selector and chain clients -func GetInspectorFromChainSelector(chains sdk.ChainAccess, selector uint64, proposal *mcms.TimelockProposal) (sdk.Inspector, error) { - fam, err := types.GetChainSelectorFamily(types.ChainSelector(selector)) +// 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 chainClient family: %w", err) + return nil, fmt.Errorf("error getting chain family: %w", err) } - action := proposal.Action - var inspector sdk.Inspector - switch fam { + rawSelector := uint64(selector) + switch family { case chainsel.FamilyEVM: - client, ok := chains.EVMClient(selector) + client, ok := chains.EVMClient(rawSelector) if !ok { - return nil, fmt.Errorf("missing EVM chain client for selector %d", selector) + return nil, fmt.Errorf("missing EVM chain client for selector %d", rawSelector) } - inspector = evm.NewInspector(client) + return evm.NewInspector(client), nil case chainsel.FamilySolana: - client, ok := chains.SolanaClient(selector) + client, ok := chains.SolanaClient(rawSelector) if !ok { - return nil, fmt.Errorf("missing Solana chain client for selector %d", selector) + return nil, fmt.Errorf("missing Solana chain client for selector %d", rawSelector) } - inspector = solana.NewInspector(client) + return solana.NewInspector(client), nil case chainsel.FamilyAptos: - role, err := chainsmetadata.AptosRoleFromAction(action) - if err != nil { - return nil, fmt.Errorf("error getting aptos role from proposal: %w", err) - } - client, ok := chains.AptosClient(selector) + client, ok := chains.AptosClient(rawSelector) if !ok { - return nil, fmt.Errorf("missing Aptos chain client for selector %d", selector) + return nil, fmt.Errorf("missing Aptos chain client for selector %d", rawSelector) } - inspector = aptos.NewInspector(client, role) - case chainsel.FamilySui: - metadata, err := chainsmetadata.SuiMetadata(proposal.ChainMetadata[types.ChainSelector(selector)]) + role, err := chainsmetadata.AptosRoleFromAction(action) if err != nil { - return nil, fmt.Errorf("error getting sui metadata from proposal: %w", err) + return nil, fmt.Errorf("error determining aptos role: %w", err) } - client, signer, ok := chains.Sui(selector) + return aptos.NewInspector(client, role), nil + case chainsel.FamilySui: + client, signer, ok := chains.Sui(rawSelector) if !ok { - return nil, fmt.Errorf("missing Sui chain client for selector %d", selector) + return nil, fmt.Errorf("missing Sui chain client for selector %d", rawSelector) } - inspector, err = sui.NewInspector(client, signer, metadata.McmsPackageID, metadata.Role) + suiMetadata, err := chainsmetadata.SuiMetadata(metadata) if err != nil { - return nil, fmt.Errorf("error creating sui inspector: %w", err) + 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", fam) + return nil, fmt.Errorf("unsupported chain family %s", family) } - - return inspector, nil } diff --git a/inspectors/inspectors_test.go b/inspectors/inspectors_test.go index 24054ce72..861c89c45 100644 --- a/inspectors/inspectors_test.go +++ b/inspectors/inspectors_test.go @@ -9,7 +9,6 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/mcms" "github.com/smartcontractkit/mcms/sdk" mcmsTypes "github.com/smartcontractkit/mcms/types" ) @@ -38,7 +37,7 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { }, chainAccess: &fakeChainAccess{}, expectErr: true, - errContains: "error getting inspector for chain selector 1: error getting chainClient family: chain family not found for selector 1", + errContains: "error getting chain family: chain family not found for selector 1", }, { name: "valid input", @@ -71,7 +70,7 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { } builder := NewMCMInspectorFetcher(tc.chainAccess) - inspectors, err := builder.FetchInspectors(tc.chainMetadata, &mcms.TimelockProposal{}) + inspectors, err := builder.FetchInspectors(tc.chainMetadata, mcmsTypes.TimelockActionSchedule) if tc.expectErr { require.Error(t, err) require.Contains(t, err.Error(), tc.errContains) diff --git a/inspectors/mocks/inspector_fetcher.go b/inspectors/mocks/inspector_fetcher.go index 3d3dbf325..59ceff298 100644 --- a/inspectors/mocks/inspector_fetcher.go +++ b/inspectors/mocks/inspector_fetcher.go @@ -3,10 +3,8 @@ package mocks import ( - mcms "github.com/smartcontractkit/mcms" - mock "github.com/stretchr/testify/mock" - sdk "github.com/smartcontractkit/mcms/sdk" + mock "github.com/stretchr/testify/mock" types "github.com/smartcontractkit/mcms/types" ) @@ -24,9 +22,9 @@ func (_m *InspectorFetcher) EXPECT() *InspectorFetcher_Expecter { return &InspectorFetcher_Expecter{mock: &_m.Mock} } -// FetchInspectors provides a mock function with given fields: chainMetadata, proposal -func (_m *InspectorFetcher) FetchInspectors(chainMetadata map[types.ChainSelector]types.ChainMetadata, proposal *mcms.TimelockProposal) (map[types.ChainSelector]sdk.Inspector, error) { - ret := _m.Called(chainMetadata, proposal) +// 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") @@ -34,19 +32,19 @@ func (_m *InspectorFetcher) FetchInspectors(chainMetadata map[types.ChainSelecto var r0 map[types.ChainSelector]sdk.Inspector var r1 error - if rf, ok := ret.Get(0).(func(map[types.ChainSelector]types.ChainMetadata, *mcms.TimelockProposal) (map[types.ChainSelector]sdk.Inspector, error)); ok { - return rf(chainMetadata, proposal) + 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, *mcms.TimelockProposal) map[types.ChainSelector]sdk.Inspector); ok { - r0 = rf(chainMetadata, proposal) + 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, *mcms.TimelockProposal) error); ok { - r1 = rf(chainMetadata, proposal) + 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) } @@ -61,14 +59,14 @@ type InspectorFetcher_FetchInspectors_Call struct { // FetchInspectors is a helper method to define mock.On call // - chainMetadata map[types.ChainSelector]types.ChainMetadata -// - proposal *mcms.TimelockProposal -func (_e *InspectorFetcher_Expecter) FetchInspectors(chainMetadata interface{}, proposal interface{}) *InspectorFetcher_FetchInspectors_Call { - return &InspectorFetcher_FetchInspectors_Call{Call: _e.mock.On("FetchInspectors", chainMetadata, proposal)} +// - 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, proposal *mcms.TimelockProposal)) *InspectorFetcher_FetchInspectors_Call { +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].(*mcms.TimelockProposal)) + run(args[0].(map[types.ChainSelector]types.ChainMetadata), args[1].(types.TimelockAction)) }) return _c } @@ -78,7 +76,7 @@ func (_c *InspectorFetcher_FetchInspectors_Call) Return(_a0 map[types.ChainSelec return _c } -func (_c *InspectorFetcher_FetchInspectors_Call) RunAndReturn(run func(map[types.ChainSelector]types.ChainMetadata, *mcms.TimelockProposal) (map[types.ChainSelector]sdk.Inspector, error)) *InspectorFetcher_FetchInspectors_Call { +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 } diff --git a/timelock_proposal.go b/timelock_proposal.go index 751b8c2ce..ff7a67c93 100644 --- a/timelock_proposal.go +++ b/timelock_proposal.go @@ -13,6 +13,7 @@ import ( "github.com/go-playground/validator/v10" 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" @@ -335,6 +336,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 5a73ba161..7a4878463 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" + mocks "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,6 +306,101 @@ func Test_NewTimelockProposal(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) { + 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) { + 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() From 0a9164a8069765aaf89308d406b3ce64b8406166 Mon Sep 17 00:00:00 2001 From: Pablo Estrada <139084212+ecPablo@users.noreply.github.com> Date: Thu, 15 Jan 2026 15:36:44 -0600 Subject: [PATCH 06/26] Delete mcms --- mcms | Bin 2097054 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 mcms diff --git a/mcms b/mcms deleted file mode 100644 index 415c1678a51a0701a7d94f458a43f594a95a0491..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2097054 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

(AB^kt%dr)1#<(@>5 zVeu0T^(M|#cS46X1xbq&1s0(xC_ZR-D%2(aay^b|vy_>z*`77*M>#olCO4FH_vlp9# zvz2pjsl1<+bEHy9DuMUQl4yLQI6yEX(V2tbfSR*+^OsWD>2B%vS392i03x8QEDQ6Q^o*F!m=x8 zHAwp|KoM{2FzA)iFJ-nBmjIcJ`%~7&T;PBN_{w;$ikvdVFfxmd>^m*N%)sEDp3v01 z32-i&v7DFwsSHQ~51@LJZ#%$!f)lTJUa@GK%D_}^O>F{D5hMT_Jd@CYD6#s$wC;`* zNrI^iPO%&fG%y3!o$#jCko%mLy67}+=^xmnpim*naU`_Lq+yo&<7Yc$KzUuKq_}OIEXuI z2hl|C!u_i$2Z2ezI4~O!c^#PX7lQEkzUf_cIq)NLH;!G?LJb|$afPV{2rMXY8wAw+ zL>HKtT4;g%YE8g8VWN@LhFwnJS%w>j;}{2e1I+eOyM`THrLSTY5Ke`kAhp(58TX{Y z5XRSAja?|h#sqeO37yJV(x*VgfEB(ldtX}8NchYyxCtwJTpHx|c-+?7z{+0I@Pfu% zVf+{^@*dNMrFRpVc+piou`W#!tgOq@lWJLdvP~l9`A=r)$qlhIK4c4$cxoaXV3`u= zl$WXYkaTKKO5rV(6mv)Mrec|2A=6Tsp8iQX;St=-n&^s>)P-P!Y{a3JAaAFo7t;z( zW`voUVKdWKW~L3wTpWi1xW;8JdPi_IZNxd%MDD-n?A%{}c4pO`omr*X!FjBU34z&l zgusVnPAYT%G#Y}%9!qp}qH9Xx0H6DqlQyc;k!Bj`_CS%N=QYgHk2lKE=*T#FUZWg6 z|DrUTU!P_R>e6gMiDu1YA)>@7q%v=c;H`Ra955p@*hr8=NV8p-*7E}4BDqwSP;0Oq zCO+g`k!=HCEv~0#^70_=0Wn##jLQs8xkN&*&3D{E$DSz5bW z4My&=vPj9uBPq8ObVNZS;;*7kx>O#uX1#P%X$jNChy_=<-%^}u!C8=3;EXfB|0vE= z2YA-dx-t8tjVw3Fn-kqq0{t>w;1@!tq=vzUd@Gzm!Y*ogBa@uU3Iq9630@fHidv14 zm6aDzVP%;LRkEr$*cxU?B7jjVv@&>CsS{hsW2vkr zQJe&NEWOY%*+d>sWlf4&q*X5r8+1Uo-SuhABwp6BoZv4(CT?2vmB5}whzX`vaGCJq z7CrSD9A-=F`%DlQPI(Xs{{>~S9)63^DVj6qA9v~mIJ|;|-?mtYoUnwqFu^sv170p! z-w3^%%LZiiro6d`F-x>Vi|)w6-ktyu9eMQQY`6fYjBH9}Gc_SSXa)RLAskI^EMHK^@g&Q|(FbrN}(?eh6QNhk= z(TLnmWk)K{r?}I(11^?HaViv1-CEvkBRf;sl~(c`xC_=e_5=q)atB#uPon!_qgdu6 zI1R@DcQ!ITm&)!`Uf^6aoW)Cn!tRIngoJAk$aYM9$Jw)e2~JIY1uYs|uZg?}Wsw5+ zPWV-H?d?frFKLUpmOVuRULpHZ;m(|qY@U$_yZQr(9!&J*L=W*GWG6jree(K)umC!m zLmc<%{SghjpPB-B#>UP#zn03uR1aXgZx0fA8R20*KyUbMc(#zksT?7r(1j4NK=&Pi z1?myKt1+z3xH0^21M9S@ypqbR9A$7$^O{@0puZYt&G54B2BE1OP35%|6c6(T(YV`= zXI9FRqxBlKm18M0V9C7jl0R1`2!;M}4D?l>CsKNaZA@ zBy&oT$oz`39jcbQ>Z-s1=l)JW_`!ll@{3oTE*gb<^t_%jBu+GLIppP3DsKfbY|%+5 zAV9|uaCq=kr69OmPN(uVYeG;%mEdZKq#PPx{x^f=VI)akvcgNETiFJjXP33(e%7p=H zL9ODXA}CX)8OZWhqVJG6BpN&h7&90L?1Q<+p~3>)EjAbcyO_m#iJVKBcwK{2z;##; z%CEkbN7W0Wgw5pxL$-`2C?6Od7?l77L_WAc4_qzhVISvgq+tLUD#oxMxldZl;-pdt ze1z$NbrI-sI?=a{Y0)W&fpLRraaIz?1^ar%dAzfjHBSoRi1YdMPrJdbh4jryzkpQm z%Lax8%fJKzYG#834&#ySzPSrkJ4l)nWN6Vi2(1G{_Rp2Q1TAF%KDNkiPyq`%jF~fj zHRuLvfDV{%v8?Fq=HL%xjBDdlOZ^G$S>^jL}2xz)-MS%i}(WE1R(#Y(Q^OPSudAz~==zHG6Ryp*x4= z8r}gnli@iTQ5s8VSYl^%6c`chhu6oZiQJ9@k`)c>x5E26v(ZFG=42Enumc5T5IDd* z%naB9f!Vnc7}}b}_NjLPqE0?i~55vSE-M^(lsV zL-h++SrfS@C-)kVh8yC2JyMU!$$b}VFs6Qku{jxcu?A!7HyEFj2^VWHzHWoOOhg7$ zI4uLhgOGtFApcp#y9&LKmq|#2s#g^>N7eUn0<~_{$+*6#URBHus-9DsT(|0!T*Yx6 z-~a?Lhp74izTi{0>QvnFo+~aiuxMZqu$HYdnOa#Hcg^HrsP*Py9EcDw3>5P8T*-%( zml;I~i5|32eDAZgr0R1AURLhQkZm3S<9}{=vN9V7U5j!S>lmX0 zBD2egRLNX?6^QRmf%9 zgnsAeY8{+avM?u$LeJPufDVX6f)pTCSEzTqtsECpDssXvhgai=S+%WXNl^-zl(!x%A+S93OVaPop6+C&;Dk@E@6_g)Gm>ik#VJyq75Kmk_V`8gOC8 zj-8OX1+^}eM!0A{C#!O36^`bt%oR7aP9DQN^9&h&ggy9b9L3E6q{TWRwI_Kxd7)u3 zY3+0>+3QKV4{$pgKEY^<0(VNv>PCj!TGr%bEzu4M8P_2@i`y>Gwst;_L*e&B*ar@# zugNv&mq&g@PS%kl@##rR=DbVssI+EV$od@5cXDEwwZ!OA*yHtt?!wU_=0WvBr3;CJ zoba4%$mzBCKM;B&^1E{Y)f=?M0XqyloT&^XuhHo?;cIX}xB+li%jTRs#R2miE{*pv zSBRGJUV`5I)C_EJ?)Jb=-56N3k9Gp#E;02)8ne3E$aBaKCtQoYSuE`-QWG2mrb6WFYb8P;0X+n85V3f! z5ngh#qr|N{Y^qwz^Y~a)5K~|PO zoN_IlFhO*raFGKNE|kT60Cp?XOgnmLM;beX99wg-klp5ch46g{W{AW5VV3E~DCkm; z{sI0^o4uy;LQY=Hp)HeIfH>VF?T9+zcf#AcJ9?zL=VTA+<9{+QQr>g2F9)fy*ZyuQ z`*U(22e*I+dp+QEq32gu7UO6+(~;)lbO-zu^?>H&AVgG-711JGxCJ3G-{E+j)G?5Qr`PDV6(4f}ki1&5O=N8fjAC1l1 z)B`w7C5&MWqHShopcj~gKo`a!ET>nHVByi=LR|oAAUaPl0mHSnLkFn+4sU8_7@6`` zufm;B8FRqfO8e+?8JI6^qijEfp_I2%Wr703lD`Q)6i~H13uTuR=rk~Y5h7#5ZBz(o zfe05Eq_^hlkPX}OJTE+Z(li>zd?4&baZ~Z2is9yDFg}3GOCn79(yvDI08eX4a=8r2 z%g{WJiiMap1UzItWIXLrQ+Az5Rcue;6T+D?bOj&XMo$jj#$8ZyK46ogG=M4qYDqr(j|-{sYhcDo4dHrkSp+@7b0JGj0= z%!3OD&2C1}18?gJ-pl0;f!Iyt-n`%hPU)h~ zTU7_(Mjfx)z2c4#+!cZwHt(%VUz|b6%YAuJtK1A%ri{s#1T-?~F<K;u_0y zxLUQ2w8+S`JaeOQDU#Jjg=zVsy&x>A*}Zt=?z?p<5BlQ z)!bH==Vb-i6CxeEnLnWWz(m~cuSC28V z?ofnhW!Av%7~d4eWZ{2K9InBG0`Q7(L)bmC&7=23$wKwyqS+ z%euU*&)e3JhA88ET>yVwM$YXS!Pz?njOlktMnvU4tMHM0tK7gYhGD zYF_+w&j2p2A^0RizOfiHzR{4Eo$RytX&M6TiokSdyr{JHkXelrzWf)*Dzc%uMEDWO zUg%8wF*iK9S@t)vC%CTY6}(IMF^}0*_NbSfD*p)0z9P%QlmExwdq7EfT>0Yn`(|!W z?n&J}-94ibAfcQrXW5psEeFY2+I8M_SZBXod%e4UyEZus5CTNbIf#r9IS7G3WD$ix zA_|d&$O6Ip-MaUy>BeKNbk4p#|9Ad79QylJzIChWR=QR71sWECkqQug9uUIgJ!iGL zp4KUNfObWoucn5p*?h7~fDr6XdQPoc)6 zwU0pC2y~9XmB{lGkoEvv?lVj z76A3*CR(R9@U&4q-9(!sPYX2DNqQ;*6C$u(xtF9X>N!boMc{G-PDKER(WQi2N6c$Y z#+cS*d2LM{wD4P#aR~W<4RZfr#QU$)P}qQI&^jCl83G!i=xdSV7ij`)klOt;Nxdf` z5YS9@3TV25kmf5uL~DT%CD9(WBHE|mPTCKEbctRED3s?aPDXxCMc{M<&Z!@w^AWfZ zft59mGNK994g}OS0#`J6KvxxX!E3te)*G+ZdNkgnaf*nh1AsVqTdL7NM8g!^OM@b? zL4Ds#3nQ>10+%CjF#^XTa5w_5M&M`!PDkMN2%L<-1qHa{Qd0+IOB4mPKmpOpTO+E6 z0-?CzYg^Kx#{$~w(ezqZ2}YvGfZ(rBKw~``>CtXPjLHJn5#G+^$>RZaP&=UR9(7Z6 zKb=>a?x#ZvuBT%WIH>^PI{I*fJsPA4X%1He%AZ!WHK12LTI$gukDdhrz3{io+pY2F z1&=m+bikv1ijdj~k1ly+4GFFnyxlpE&MHE>PbVBdfv$MF_TElJu+rDj+x7D3QIC3h z)X$^79u4 zD9cUi4`{td&v~@g$FkF-?H=t=gd836=zvG7RUX3iln-&nyIufNj-U6g9eq2vA?0EQy5jxyR=Y3Ka0Q5Nibqd+G~J^&R$a?)RMI#dgJ*D1; z<5g6T&U83Bi;Dw3>wG|*>rg14Kj2<5R6NXtWzlDxsAHHuJ{n{IHfn9^x``h8s0*}@xdOvNAzzg1OlOm|DKdI@DhjjMnxVkFR^kx0 zN83GG6M5Sbfo%#9>q{P;^ysKZowZiN-xY7yLG6&1b;aL{0Ia5~BdYf0>s|5eLxt8N zgWW}Mchvjq&=~nUp>_z-Lxu6BFdAI}b-T{_W4fx|V0Fr)*VGYqHV6Y+=gCZuj|Oar48tZg~2Q=5a&hTiVN6S5W#-m*x?eu7yM_WBw z<gYM~6K+;n4+;&Uo~eM~}6PxI4t7i5|`HXu3yJJeuv% zGajw*=qZn$_h_w0J3V^Iqt`q-<E_ig=qbnZ0CqOC_ItF?qr)D(=Ftg{PI`38 zqt`vU=+Om_E_>9@j})$YyRP1@k4IxX8sX6dj}~||-=ozYt@3D{N6#z5sAY)G1@{Lu zz@u&I3cH>+x{^K^(2HsZbi|`qJv!vk36HLLbkUDLmU{2YJzDM28jqg$Xp2YN zJ$lij*F8Gs(KesO_8ztI=$!X=#-l49HDzpq57F79J|6Y;XqZRyJ(}jx8jqgy=y{KJ zd9=r)mp$6A2!-~#w>#|7s~(;3=%gZqcGsGIlK)uX8%P4TF|N4-26 z>CqsMhIur}qtPCX^Js=gvpkyX(R`1d_GqC;n>^a+(K(<0zK#bZS`o2 zM=yG`%cI?jz{xkf-9C>Fcy!pKqaGde=yi`ycy!XEQ;Lwrkz1nDy5L>g-yGS!}(zj z^oqJ-7XDfk^gMuD@jVyWT!_HM$mz`pycK~qw^^w65$G6!&JpMmfvyo)tl;~RbpL)N z@Bfv0zzK8wf2DB>eh@kRAaeRa6zYdGUH$x!rYZP+Z#U2h0GuJ}8iDQ+cr*gN0Rr*!7=R1jCjyU0pl<~F0TkAU1n)0Gor8AE#tvhF z1pD1(j5CX6w7-m*rs7`nD#pp4X;s)oU}(TBs-neJw4{obRx!>mE~}#DRkWfCH-*us z!vHZBV#($+VZanC0{Uzi6jMnl(C5OSjLK!9_48p6r%J5+(*t2pO*L4Mr7wg*f(o!) zMqdnr6xBf<(}Q73_32pLWdGNLS42+txbl!7?1=1L&iByl@*f}XCR`4zOFf)-X#mvY8{^gQ&x%K1c4BF*_8v~ft>dx`>)9sm%lxHC4O zJEfUJu-sXRUKFC_&J2XUINTlvrQ&dV89G%s+@3IpTf?9nG2B`lR8SlqZmkU}#lx-H zph|jA65$XqG`8@~l}>n4EfN@cH5U(m5oN;~$yqtAEa$UAyyVZ(Ps=OlY8juy-XoNt z@E&yqJzF6eUsb{91L{-A7Xn&cfrOO-Pgj%({dqYCnfD|l$N1JG!^QA`Ub{pjdp3@Y zLi%P?LAiLywlELq+9X!w45JCjXfZO1Qn)oOLkh9DBdDbWzV}&(hA_bRBA|v!3@{`O z^l){;MD%cJiTjQO#v2%xMBEXMu**3igUD2oaQ1rF5DBcjv^JC5V*e8VrH$76 zcVgevLfm*rDqLWNR_6KuH*nFOigRpiK$C0pMCiH*8G{6|TKtxTN$9J*RKbI!zgQ4w zyruV|L(@RNuZs=AQ4c#d129(lj zFvLUE5QNH7t_VXs)O)dO45dB@0{y5Fg3xMEB?O`9la!JX5IXYG0Pn~G5>)$q&F+*k}HwR6}aMOq_ z4J}Rp>d=Bt0%Gtk{CXX*R3Pd~z)PFb33$1qGggm8OI@N@EYYh{pwuSL&tRJ)E+g7k z5R0X_571KF4`_qh1ArxNd>d@K-xro z^);8E*4m~l*)0X7^DX;Pd|gmgyak<>mN*cV7r{V-y;Z1)GWd_ydv z_PIHgX2X&>rnxcGDNXbSBwCzT-=@T+kxh+DL7%f>JJLGeG;F`nG;BZ96pJrmwd4Gc zrD~QqFpyIv%<^h;mKLsk0r(NbZUnW>wT`zcxT6#D&o&Xfs)^v$j$oN@GER3$M6D4~ zQC>4g6^Go0aO?^8S?liQ`O96K2=Ey-+VVdtN1_&x>jvo>#BM^ukk$%<*v-y}X{-V) z5C|}DCBma&n((cT;Cgg#?c+QGd60#UK?OqaG)NmGcsih~5Yo5usHUKWp#&v_#A*hn zV?kPiP-Hzwt-qCWws__MfAXW71g*f&H7?6nD{@@k~f$wAmWxrzOBH zoLi0a`~rz#VF699E$>t#{rH?UWO;|DtUGxorv>>0-9Ed`=RMgt9_vU zlB<0#t;>MAU_);KT36H#($f0<_JG#$cLuD`F+g`ftS^bw>IH~lufRTlHB>9GA7Fx# z0tW%6B$(7O#$;QHt|c-SFy`1|xCe%+@OtF(rMP5=u(rZWaV5FS^WL~*NHh0Joc6_$ zS6n|%&o*)FInOcL18A~lFQCdA+6Rc0F(Ky=V1+{Io#P6n^R1L|kklU;uz;}QfS+k1 zFfuUOt`Pkm5MAMl21Gw6L?4RNVO$gDO5unj`n5Q(DZrJ`bfa$t5bZYJx?4E!3gLa8 zL63(;yy)bZYB+~bu zMZPsSZ`Ls4E#Mc_@IGhQmSc#$KgWvAcrb@zs z@Zmz5AE(Wg1krXJPjgh#)=H2>+u&NjCkm+(_A%l#JC0$p^#A?wo?L|t2u|WMgGy0> zJWxr~;`CIUrsK(>I329S{ph@{kPcPyi-mN!l6T|Af=b?7h-n4Qiz6F!0p}a}bRl)A z;xmOM*c_MT8n@hjXSCe@8wfpc;y0Djj|r#?3f$5|cZjwU>Grz^C9o0+c@9?CClMek z?y^8}5mselbrFj?YSjx?P~%0{=B#8p<&V-)z~+y#TrI(VkM08I-&a|xzfYUPNCd|E z1~kxJs&*i4trs+(bcK)50KdqCKVVd(=c@RbC=5eBzNT;GtO z&|jr(h#kA70xDo7vG0Nvw)X@?mE)GFBprp@dth@ksDj(Q4%HjEGQEENSh#P8!3Tx9Z%dt&Y<@osJ|q_3mwbO17C#At`^4fWQjx{SB}DfT zvAN`O^ifz{hSkT!>axqo{g6{40fN|va(+JyT;*f}Ce&!pGO3pt?*TlF7w03mbj`KI zot1pFkUCaDP~ce-yp{2Ty(DDQ-uWjw-(Bh%)F*?@RFu+@Uo_H z@bac{@Crbs+%4g0GSPY*pVdy|qmFu65b`e8H`qs(1xe;hv5z^gZkB>#aVv<nw^Qyd9d{HO^ zEhYP`5e7x&^E^YU1=KN=g`ooQQ5b=|g}j;h1&#?0VxM)EWkKw70A=BOk)PRBybZU{ zn}Ne!{peIO!J2R(<>4^l*lIzwJ&{?f|TCQ)<9^#>wj;rn5^w~BG? zAC}mwWR{hmu|PzQMhO2w>Dd{F-7RGuGKLDC%R-yQGO%G8*nOs^FWsj4~iAG zhzb^*jmD+oO=(;tsxWTZcQSe>qj99t_>lLNlau?ruQBTDEAXYYpd$PjXnM1X$4iBs zQOze}w5*2l0Pyk}zEVU}s`+Y>$b9ToX-ZhowJ9!JX<~0I%{E!PK_>?PS@Vot8X_+GDlqR;i-3iwpfg@zXeGZ z;V0xs@t|s&TEttC6mN_1_81MWrXkh51IN89d1uV21VQA!Es97@Aa z3c16og|0m@8d=S_bcOh3A=;_bpuS+ih$?juPLyvBn=7akesD-!4eh=*__6jpzDDOg-0^5 zM?H3%(G_kM2D51QfQky4;Gin=el2ws_P7&A@(v*-Mb3xSP3X%l+*};66|a+rF()sl zRXcgfM`JR!deAKn3;39gt(;dE$;pVd-$N3a@YBMAS=BVVnsKd%)`#IWQVB-X@Gd-T zAyokkda+1q$b=f+TSOCU_+>mpQALw#cwZ48DB{aSB~kzoN$AdS_Y*RTN|1#5msFNi zffhqufmV`qfmMzS%l<3&W*hOvp+~}|dldp)XAv}71lLPItU{nLGzbX-d1dHF<{QGysut4`mqtH@BnPL>?hLS5m z)o{aXJN5&RQWAa^mm|!p=Ce}NPgnCf+*wo2=VQ`-2KXL?1_B~YseB^<-3qW9aX>HY zf(nlxx}1Fu(P81@O^I${HD8L+l4@>KM9);yN*DXH)wHUbI~2(*2OHrgp0E*a(PLU_ z>&q=&m6as#h^7g$JYlQl*vNO=6h{QW)RDh(yBrH*crg_-t6v`pfn<*sw^eJ6dyM~5Y5qyM8Ns36#Qax2}J z9h10IksB=tudpBG4DaCMiYnk zy=Jh1TbTkhbg7myr@|aTg}g?|uM{;6DbWpR9fPz10l&d-b@-r2<0&>t%zpU(5xChRz$NMdz(hPI;fHn z2jrI<61uj2RC)L*;UOPagG4R{Y5uGp%w!GIoZJU~n)jO@QcY4b-3ZF{q|um)b#xf@ z%55>qMuC1qsBnEy5R<9|Y3Cg56Z=Qlm4#oG0$(HjQ5QVuoMc?^vn9>A%472l{9G$n zypYIl1ae1}Fc%ECO#~pim)oR|k_vabR5)1NUJVNwfk1Sl81WS!(ELNi;jYEfPhcwi zPe_OM0vv{bCc`&K>F|CuWJx~4RYSu5N$Q&9Ar&;RmWM)#2|8sJ^mvkISJ03o z4NcOpBtz};sS1X=TWepI%*A~c# z6ry5n!5yed7{UX64xY*dJY>FSBJK*b(3w~acD`o@x5zT5*vRM~Z64@b@Qsn#%;0Ah zOvWrV2sQ%i%P!c6;5O*dA=rrE;|PYyD$w7;cT&L5EtqT;$VhHVP^-bFKpTOfF(6hV zW}p@~CHSuS7F`U;0qA6;)b}*3X|r2rpB6j-PtY%$7W|$07X6Y2kkl(Q-@U@Sg6jyX zS-rxK1=q{D2OtqqEd~5Sf`Pfa5vwmZxOH^{y>kVweZ0)A+o7K0Kr9a;=7-7E}T z9NdU?eJDEtNeSF0KuD4(SHU-0E52A~5Z|k?JfXfv zxQp%q!M%hb7SKPyH#WED6m$+G90=}#aPLRB9tE`shjQ*waGQqffnvUw zK7epN3Lb%PtfBWP@Fj;}ACi(QxK4wOD0rU+8&U981p6?8jVKVNVtso=!5=NPImpvT zFle8H4V{llYIA}QXg!&On)fj&`8mP&gZt^@0)7*Gf<7tWkBIS8l7XPR(EVvagQFaX zCeddIuB!`DaQv)*ns^Z`@8DQW98w5KOwm`7o3iyNuI}?5z!TuM5 zoe6&l-~T9}eN+opAlyHJf)zL)^E=t61d;~$&jP+9k%OikAoCCKv;+M87a6$#wT9cj z3izOTIs#As22V$Vy5Ns)UE&CYSrPqjvHG-ml7l(_j_{pvlIJ@54*`uR{XaP?DWE@# zRn$0Fq7>U8T3QL!tb3>}Vqb}d!_-bKC28aYmiJ5iKv&_=K^(85OhKxE*2umv8t?<~ z*2#JMvIW=;2Q+Gk88?D8DFQbbXn1V4z@8aAMW*;4jh!Y$Gc4jw= zQx_hf9{%9M4$2EVB*!WCFYr(teoL;9+a+U$;l=b~4Ua75(Zv|;n$ov?WywRvC>VjT z8-d84o($gu9+4X%N(X<~Gx;}wGL8AA8roCCWAUVEz~gX2kC&J5gkoNZH?+Z^4{1;L zAzS15P!b8qF~1Mp2!_D7EI;v}VmEaEBO(ngtgPJ1um?pAyGh0TL`g|x_wTUd@L^nq zOE1^ZD>Xbt$3m@<7NTyg+pu8kRHYqt0wexM#Q**po+hUVajfCBVp;z~zxEgFe}97i zlJIY^tAdjdGsJthIL|7kgEc(6Sf&pc)mk9*eKtu(mxm02i9Azt0}+QmtihxH;SXyf zPboPPedNpRER335Njtx;^fgrE@m-sY8q5=rXkO@88!!tQ{aYM$!>NzC<-ERFPJL`F z7WQmXo<5>HeZ-ww0lyxB2AwPpJ(6+d7x0E_aw`eBNuQ<_lNN?VzKuk1E(VEgbBXM5 ziR{!wAj_oSek?oqg-GPbwVKF}vzEyAW)itJHyF+|S?2r9GubTU zSW}$}SPlAdh2<<3eT+AnP!wmr<=dE)Ii4~+n=Ks15E9(5C>LlJlOm>+;vHRL%! z7OhOCnzI_L zTX2v;0lJ;<$wYjX%(7{AEzPN=xwX>oVD@H}8A~?M$CX(=)}36SfbmqV)Ct$tBe~R(rSauE zDWlZMymR|fCl9(x9MziegevY>N-JuiVaJ{E09Y-ptmQ7Hw5pa?*K#+!@mWi|Yk5E^ z9jukTP*h0EI`)XsnaJu82K}~S=qjJPLEy_yJx7k}b<#w2Km?iBRZqcn(~NZ2!~8we z6Q(5uQQ=qug1S0_o~z}ac<8H^p08!Ri@C0r*4NU8TH094z42;QEp4mi{-w0NmUh%K zUUS@8D~so|+yOlD~*pnOE$L?1kFC#KCB?g^p3DEyH~KNLRRpCh_j%UfM( zVNcRn4h>W*tpO4shz*oaiH2(f4KK#aa%~g511~})cxNeUUUaGf9w&qm|HfjX=@>ZH z-5DWExRYV!)^H~~E7_75QLex@;#Vszo zB$L?L0Lh)8ua%%K3F?}l4hfNK-4Y^zyC)d0we?Q$NxW^F;H#xHua=%jaGNq3kf4DH z8kC^H32s}48#x&dIgL)xm_%^`SI{9h#xq$&vugU1%cI-a#ECytQwR3~;*`3K!CnR| z)dL`}0NN>+eSmKJ5tA-JJEn_Mf6+PJgMfBW_Yh!GV>k>5tz(JzRlu~`9s$fK#BsnN ztMDjbJvE45oZgeAL4n5suU8Kz09!aB`H5~xm8j@YPf~ZivF>jn0)ko z)zURH99(dwsP&r3@@c00RytIJkC#+Z@3NKR6)UvTk!8{vN0&(>#L}`HAGN$(1hlFk zXXmW1xCCg8P|nU-Bb2jq)(EcvS|hv)XpOK9x)^JOZ2|4Dd^G%>-`@k&*K zXW~Js1mo$Z7jbbF-n~nR^!p3ZCvp$(FM*>^MKY}hXE~88W9LFZW9K43W9MQ(?Rsem zps9&31vEABWq@&&bU2rzXY{a=32287p8>4V^M@+|YZX2Vn9yLW0Nq6dSPuuR)0X@k zV45=0sMi2ysb1h(zy=NWJm7UMGM*tt;AR`v^k%CC77ym;mDRkwvYMa6Wpw9xg=8ix zBs1j~(h3beQ3|QEk>>dJW=Rt=8rnII%o5#J?dE8s0*`FlYFW2lp z>AKlz37Vdu83~%{s_HDffSsT@2^r}fZyIl&0Mx-Oodm=(g{*tO4p>UXm|yd{9QH=0 zNb;y#Bw@{zUpm_~_+%lk_Fb0Fj;MuTink5iuoki%&`M+npq0o@Kr4}5fL0>VkB&-Y zH=vcsOMq4)djPFO_5xOGF}w^|qrBgl$NLv^vJZ+OYxp6>)PZ4e;-z7H= zxw?vXnRFxsA^b#BF%EFW=mt8_FphXK2+(*k7|?h!1kh^fP(b6!FhJwUa6se92tcc) zP(F@o=_o*z8hkj9JxB7Y=FyzoLRrF@B4(M%m}RDXW}VUCQ-xVg<7bRZaKl7`&$%vj zI>t^`EoK0^Y7yoR5con)EKt4D!GKztTU39qDDhV{z>}Kn&t%R7mE^WKvp`!DysTUX z3N3u9Eu*@~?aF1G5t}CA;^EIF9LBY7t~IX~Qv)Fy>IFKuU6!Eb3FraH1pY1`+1*iO zaw(Cn7|O{vE4O>4*jy1q)eZXhB8Wd2bpWyHk}ik8kaUq!C(tVsbOcxa#Ab+xn0ipNJ^1cqNLGWpQ|rtvkFqh`tctd&~pIoml>WYLXos zAU+)cT4J$sLMLm7u?w^Raypoh*8MUBvDP-;r4@C7=E$u!td8?;;l#cK zUlc2o`dfAO0UP;J~B6>xu+b*b6 zNQ9E24jOo`(z;0EDi41vaUFGoV4`C#lH&BW|sS0hIzlH>Q-3-KA1y;pFA01i-oXQ=p;JcG$Y7neyrRHK(|#2=cLmQf)geS zI!QjJ5iXIiL2RjfYP1}5d4ojApDf4Xg-mL(e(`!F;&uJvlxyE_l*<<4e9UuUYDquwPP!IsKFLM3M$1X<(8DCEr$T6ksVbS~RsK z)TfoI`AUFWo4VG^;yf>_g@9D}PeOnjQqkBXjdMI7pQH&%nwX?XNt&FbDM^}|q$iU! z4Z4&`nvtZLNt%_U*-4s{l=cZO8b2{~P{{~ECNfCsC^Vrl{F1{M7&qVoNEu>aSb<5m zY^PL76O7>jMj5$a>L8aEK*1QJWZ716L`pu~VB$F;nZw`ZN?VcUezz@ZWUG`5w(4`z zg*G>Lv@oziXXJmqaz=x(Hqpp!bH1C31eI>QP19K;bTy5%^H-_|H#O!VzA^L8oREQ; zBAKFY(dgPtCR5C$tH)8e<4&eTCS9|NOu7^knRLz{nRJdBnRJd7nRF6iYw_3AwKK{R zU8m=Bnw7P}gtGAWQlI{!3FF8=n(#%}gs-hFB8gF3Oq8Rxs3d1=Zf|O0*4!@VB<7o` zZ5riE7As6wL{8VbL)>6qoAo5AyKfF0_(rel$*Npo9^pV@aMO7o$8GXWUV8 zJV_^#JR{CCp??&|PKdj>0?Lhaztf+<_eN<>_=;AUNUr<8F5JQQ+xSY8x(`hX0q!#e zto!7s70v+MCyH(|cE9f-c!aM1eGh8@(|zA0G-kqok%y9ZC%HF>l5?Ps;bxU2_leV< zBtIUfy-DteYrm4*KQ3A%c=;9!+5@n&m*hclIs(ZYr`M7^DK1xjKGsyvMbFY?^W%V4 zvV8%qlNJqWn?CmkwCVE`fHr-WlUFu<9t3D>m~uggt+WjT#CbC57e6KCfh?dmb6YWe z1?kCstoS;^HJ^cTCr;elB(~X=Cl67(En+GT|5YAVM87c%mw_eeK$3C!;=!bpfU6{K zt^S5c))@sOGzOFgQg`tLJUTZe9q^A-ip<5O?(|xW(#bio@YLL_O#6$tEMfJ<=Kg}@ zAfeUo^{D!tf@Zx`yr*2no0x*Oy;QuTahjB3OrLPw*Bfy@8|Mr05*#?DAE7BAvptXguvKz(U-(BUm(xie5vMarI-8_(NjjgDV!DvT z>0i2-q&JgvDM^>{yfdD9PBQKkYL}w+DSkdq9a7XW#dtruQ;IsLczv9@q-1-oYf9c7 z?v|qNDc*oeo}x!n)H6lBQj902A4^f66mN^u<0!E?Tin3^A=e^=Cts1C5%+%vqRd=Q1=2HqO?t)x z=^4N7^$fn@T7W#P@J+XUCJ!roOSa6icz=){mL=sZ-tZ%AZ8cIBZ!n4eatmtN3g~Y` zsL2=H2=r}SibFTu4D>y@%DJFKpw6kBhW?ytNw}sioC^&Nper=asot+w9y2ttV+k6GI1C8f{RyMWEKLsG&jRS+`-Z54I8=3^N$ zw>(p-f7ujyyS(F#qZi%c!DVq^RhI6xT3I{CvnSKobn?Y5 z{e4B&0!5(#LdfYeJSf8jQ4)l-fgr+HET9W0jlT@$pNhF$fXHi+OOOvDzkigFE*jrf z(m%t)kKP9lGHCw^2JJBaL_#J7h`ynOgdD>Q#rTT;FP;<@(FF;Huhe6_VJnwz;f5)E zMYUT*8pIr4F~wJWc*zEfM?_~);(#!N7686!5p?+02d&(<5#p{TJbVY2f}!X7j%cK} z#Udl#yo2{l(eyb!b2pDVp0pWIpBs8OBqW_>hkIZOqYCHDhV#xS-wK+O;x zT$r$IDe6=hA!0y^FU3flw)E$K35);yq6D%a3TnPc89trV9J+ln_X2Mp+5*9?GS zFC%x58OYjTrPNuNNp4I>=Y^D!D6TY+P@(%4=GbH4j9yOaS(D!inB`6y`Re~Bw_4cA zjWo5fu&q$MA;mK*>3AjRm1XN?X#Qxe4&7?^C=7M9!2^1vrciUDP+-A!2q6gtpn;I1 z+)zb6t$CHSIt4fCUx^huQHXcp9=S!*LaL8^4EnTaRe8ZneDDPlP=c>c(V7(ZsVqXG zzi!Y-etoZtgns=&i35@SS`L*6cXMe8Vh7;_LETOZjF;e45HEFQw%nDO=qQ@R5*@{m z@Y<8=DC*^CT5Lh=ki>)dU1#}>7NCn8cg-rxaz9dSnzMIRYaNDYQp&Nz5@!*P1BqbT3A?H8`asG5Y*-0XXS-_vV-Cr%6cUeS zz)e;PW?<_>CQyPzKB3yt1h|Q)n*e?35?QSPlKb`0m?i|b1IS=ZmgKNhfo}~wRSUQQ z%N4Z{F;jwjP+>9Hn}TjFrQidYoH(0LLDV69BpDnpaQm&6h3lpwlUZIfQc<6gn~ICb zWP-)KysU8^K~6CI?+_Gp!1<*z-Y4a=H^qmf+oP9Le7KTcN%5j7=kcmtrRRcr(_wTexErdF{T&{kQu0Gckv3xIlo zbL=&tGvou6e6Z5bt=ouY;NEC*BO{$L9jbIAxz{RlPEo~Bc zKDiO86Zdm=tWN4*hNTgLs=2bxyxV73m9Rtg&Mgs*!Zm$M6`ec$poXK?=7oz)|6|F@ z$p2x;|F>#LeyNzLSxZ-iWo#4`;kCY;q%p^6!q#lPzc!$gH|8_XIiK!BYcaTl$Us0xmGiZ z_3iTYf5R=G?*AJp{Pj37F#2!I_nEgV|G!S;e(2e=^X@U*5^AQ zsoALWEt`$nyu1USx^oh7VqC2oI3Jf`aY@+KO*Bu}@dRj|(78IEQA-!;i7ITHLL*%rr#X!2_&`xxoNlsWmCY}V9l zOU<`bQ|t{bsaLUo3xfPu9|aG{5dndp6yDj8zHWG-T1l zHe;Uzw9VKBfVvsWlXYD&f77(L^8J)H3f-UN(^`+t3R(4GPgjq0zZBI6WSp&~!D-np zK37Xa(lj(J6>3--yK|`IG(1fs(tN&_My8?aMx)ZWKA%RTex+qeXlz>6AX@k;*2-70 z8+{eK)mO3G-9iJ-s><~ySd*5uXe??bs8Tk}-Xn|8HL_w1-Cvx?z&dl(%3KwYAzRGl z!dJx$c~#L&IP8g>2C;LJ;h2`gP`PvkCk!X0T|Kx>2!``*?w$*zh{Z6B%#q-!xZWLp zUIGWP3-YPb9a`uBsDgmokQD`i4x(b*5xTu`nwF;NX~uz=&Iy;oZ;=A3&TnOj9YXB4 z?lygV<&qj%ef#Z$ZgGo#`z?HBY3nywkAeMfYiWsU8kOwoqS`4^&gk zanx70$6SCY7BksrfJXMF6hWC4!Esvi`d#%xb zKWg()YD02qw#^7`mLOeSY~IZzYd-1umboUUj59T1$~c!KZ@D)gPD?mt9O$sR)|7FZ zov4n}l^2)Ae^K~&P_RCvt!bVqyx5lJSx!qAtIn4H=$xgyci}Awl(azGomiifpdD$R zD~)Y&f?r6`skB@lv^7C*xJXYF@U{e6 z42y^H6)_K~REidNyQ3c88$`t7`#!0e_l6s8z}uxG`=bAo?R|Tay5-aY=_#Mg^i3UG3H~^hT3d8*l^3FV*Ci zY4UBwGH%K5NlWs3(UQ}=B0>Ap1oi4?aGzuo9YTRz!eu!{&Sr5TU-ei@THUIhnTXYpxMBQn)jMF{_cd$Q$Q!GN^^J<#fk)gc11u z0^dR@@;?H|meX#fq`l<$?yz4_Fe;GJg}ymP#%YGq`M?Yf%5aY)4bIR6>=q|!X*~~u zbgkzRX?muf(c!MFXLPvhE4fdS+GOb2dPdK?s-9NY^O!X4s;BW8>X)Gx>lxyAcRjC8 z(@XWdCQaw+rLQ`Wrt|d-7I$gj^AP3@d?8(&#Zy(j{MspRWlyFnV3BgXo3dGKy92tH zh-J^jm8#e-1T;-B8B&=h*g8Pd1bYF{G{Ig5G)=IxfOh6mo+z?2m+jC@vwHkeZjiHc zrSLAK>0+AqC!{>uW~g0; z+GqF>&i!YoV}?3qsB=bC?BvQmYa?d?p-&{qoCCB+k*OkIMvO{RTP=4rN( zV$`V}+b7@BOqzhkEUVA4&Pv1{oI6cwe~8BHqINELgxQG-ktC`$WZOFZlWu6%MS|ZD z4hRa?1~ekW&>bflmEl29)y^=Kx2I0;~*L3P6_AVwOHpHgL@_+jG< zs8ZOR;@7^K{mwV)KlnENZ@x+Y$+u{^Z_!$`ND9^Mbhl$d%}tUK^-*iaq8)12L5Lpc z_0&Q<$gX%xYE_6k=9D8NGdwUUIs@OT6so}+9Je+%;=#`8JLVL`x(YK(&3SZ&aUU_! zW_V&!`l&aNim~7vpz%Pi`n0XlD}d;-KvArlM41c+1_hIGi>U14<5uIb z8OFuNxRDRX2uDMEv5cX2|5Uk1-3b{wR>9+-dY_?58C{h$8eQkmac4j4<+&7Auxd2fU60IP)(I^g^ zarhPG9zn7JF5aczuZGQJ#H4PM@qVAW&4in%0L_GQg}TiQ+)E<}C&gI{w~p9$FUEef zpjxG+BW`Ls{XOw62e#>sL65uu{`@cla@~u z<{Hy7C*LB=^(yTgSplo*?LM(Sl59yhEGT$CZOYJsIB!eRa6Bj`4UKmu-2|f>x;HQt zx9djwl-(CAfy{PUA`gOIw9bN3F3@8*yV9JVIT98bwb9Q;Wvi@RgYY z*e(hzElb^$0zl5LLahs0sg9_q0_}DcXhTYB?w=Bx*FVV%T&ROZR#PHB!WYzWa6_7@ zV@pRo{VA{Z!N#d=f(KI5quB8}Ptux2FR0SEAiaV+g=lG1{e(T&g(HK4(e8Gf15$@x z$?(A>?aR>q3?0A#CrJl0bSOiIGkh3#z1Q>Wbu_A;PuJ1tdOlZ2W9s>Q9gVH0arJzm zjwaO8#Cm?KPCBCFO?6prE3>+M2GGRt1wb1L$*|D+r8X#ZI{_~0wB>qcP_81kk>?;l z8+i@`w2|j1KpT0E2ef`_3Sgb~fztqOCtG06iU6-W;esfj{%VVH_n&q)jR?jjNj0a|U3iQ>p{A7v-XL&kQ z*0T&<`k`4GmZjlY8j)pa;f~Dm%oL5v@~jk%&NB2|$7Fdcb8EUQLv;1_5 zCS+-1mKUaIQkEB`XmXaJzWQXA*Q97#mY+}2^enGS(TpswPtnXQZ%EOsEN_IOZ5`X_l5{X?d3Sr;2fl`gHa(X9l1Z_Dnz^CHTB|GuHS$HzCgKi!=?^$=Y~xkjI>?n8cj_$SIN)8Bl3;HD-mSK0 z0CDNO*q#N%wetcm077G5;6=a>&<6!x0sIhsSm0H_`{*MA+hBqEqx3O>Z2@r;yuc2C zpU@;a0)CP{CAOUaKTV$z*ctG%^f`fD06$L;2LdY_y&Dbpj@NzEqYks6u?I`$I}7-M#)(U__u2N4B)rbc01sA)b>Td z@2c${!0*xb5g8xTJ`E!`Z!o)NKd~pIMY;~%5C#wf)DA1fhM;SP9)F-%mxp75f=B4A z^Z+<e3I3@XlDACk{_I=mpR3S7<6 zvP~oB!OA_yH|XlBX_$r|uIUd~lTl-CN~u146dR#F#;O02Vk$LyaW|Huw_lbg;Al}+ z2%ngeA=^KB!ZDA6+>=$g-`o5Gqy{`mqtoiGar0EQvkXpC(W`d;RM$MKb7UJAW+8K7?&w&kpyubBY6^8 z%G|-*ZF96nyv;YM7;4__fKoD6D2drvU`3X<2&Y5)__7jlcJ4TzTldl6WXqR>X8Vcx=Fvll_^^c#Ak65FeUTvd!rKy z_qGBHrKHYj9X+2@U`^pJx^NKf^iex(@X;0)&Xq9sOH#| z`F$cve|hk~omcVOJuuG$l!V-5eDgLEhN>59&}NzcxhBccQIf;)oRJp5@bG(<;+VV? zwH>g^Y)AlCIuq5)B>fme>~mV?5hd2#Ph@2}Frbin7sz;C=DKe7H?pw8rAs3VGcuiIyObgd&XIkUoJzqXAXG#imFkNs9z? zvkejn=31NUs9n8G#t<8(TSHUSt)5@3qwe+6b@!;}-E}hE+FwV#>WeXP|I4e^q!*WI zqAnAXY&zJ;Xf~jopqK*~rwZA{mU$#bL;{}z#E2+?AtZ9j zeZ7t>I@I&lI*=!g)Ga|cp_X*n1~sv15~w_!5)`z-0IZ(3OI~pgK&N`%QAfwhcxN4T zuIF8Ka$Zs{E;Y_wEWiN??ZM>^Q`?5nJ51es1#*X}%Nu9|wGp`y)w)#ol4fDL5D|@u zFz(zdL_F$v3x2-h=tsdV0t+m8*`u+7TLOrJ!vYDvtd+nGc6p!1JyPNhBGU{p6c0DMMG zXElJ1<iBYG)(HZj*M+$t~ts5c|Yz0SS-vVwDnSP&=e0p}x^l zP~YH2Awu{tP`cfw1=glD%r0r^El1Y zh|LmgX~h~^k@S1dU?JWW{xd;K09hEv!^F0i)JbB;#ax=9d15LGrv(Ko z-P;xmHl12=Bo>!jy`oc-f>~3Rt0HRU;`95b7%}=^M%wxo|opQ(+r)Y1a|F#MJR7wLo8e^)ohJ0POSH^nfD1C{Fpd*qi$Z{V@5otQ zFEUE3Zjy|kP!{GA2M$AqYC~KoDVAu8FVqv>aYkBO>m@CUlENTMQu?zTP)0(3cCT-V zMJpsD7V<0^_K#w&enkt|D|6~Wz^l|`O&rQaXz>z;*Q&!Jp(7j4a4iVRUakf0trr~w zr)+Sorh(TnSQqISyj(9z1+Uce`m`t&Y)ltJ0p>9CJ$fC$uw^8btYqv={7_rvl@6!hGsYL+6>KU;O8?k)Ljp8WWC1*K$GC25~E{krxIfl z`~}$BqQO=`tF_wzZP8#mpw?FItpq+J1jfTTLBaRr?Y=%j-{TG3HzNm~p|W(MM&xk+ z4E1fGeht#4{8cgIRwQp?G$n`7Fl+>lhGCrv8irmO$&Wj}s=9~v2u*^T2jtKem?`>b zz{sRNBU7_(&01OtdL%bL5;Nrob0*i-ne%k57v`%O&qlZF+$}X*QpPC4B3YpMTq$Lc zuu7s`I?=cWUX-EnuBuFE;3cj=pbd<^5fx@)gLL^QnH6bzqCs@KKjf>)eZH3Xbrt%U z@8v(`tH@`34f(9EAfJos2Yo(TQ{u%rRXIS-l|c*skjnBL`XiHBUh~lbLu6^DWGz$Houn$Ir7&1OvC<`FC!{coNHSeZFBHTN! z40B_-=6$~FsQJ9c=>`>;#;D1u^qNUEB;S$>t5E%Lo2=P1=}fl6;%3%#COhJxXBn?y z^Wb^_*=g?>+zr&EHfd>FqWZy@4tpb6C;gt4ik%9da*D-!8@OAR_BGJ{20G9{2OGFk zmJT(@1-wsW>CNkDKh$;_>CHxZrjf@t(#A$Qg4*9mm#!DF^ATUa(ZirG7cCptuee77 zKIw#wJS&F!4Y?=t`cJ#@izuq2rejZ1F27tQ6k($y>yFu)`0$T_+tb2JL(7G4V!_@92w$^bh_Pl(G!g)c#zK~vT;IR_d zsRkbB);~l+%VLqoe{I&MT+53=SnoJGK99dsl;CxeNLe^PD7X~TrgDB#5;@zz)3Eu^ z>$BABI^L9(rRo+wxmHnXP}+-nL=4khhv;O~bd7qwL|qy#a8aLc;F%Kjg$BCVz_U>M z8hEygxXwq6v7?O`F?O^?7>pg=`jYDip45mpNW_V7VNk$y8SBS9H_P*~^i~5uo#pvi zy3)W4u#t~lzcR*V{Gk+MKYjwHHqZ$u=cU;aDeT*kEaJJ{bl`87`;ug$FDmRYINTu) zXaskNgB-Y%gE=K|a9Z=&TDVgju$k#@@JBPiSG2jL(xCShO|)BN>QpH}uAf31mM4-# zG3{1y5Ph^;#X(f#FlZGWwA;i%6wYoF2b_K3r?jr40Pu%ZDrW{;Jpu*TO;m5!e3s{w z1NsVQ`mg!KHcAoTl2G{w0nzOOTQo^ms{&S2-p7eUYw+g$VpA5c4Wdp_1o@_BBEL3x zt`}MF(1_eK$Ii)d)KH;!1#is`_kbIMfHj1nghRNMPBLE{E^_sI^mTkz>i3xIXzX=T zv(eBopRpE-#$z?RWmK~@IHn-lIIk$!z>Em{|qg*Yr@%oH^`V{2@y#;l(xlIQcHG*c9%mbSIw|1{6&qoTB~DamGnYMsch zR<*9q=i7bI*|`Xs3Bq}v^HTlKeV@(Cp7HNpe~g0saQT+`rnmEHJ#+Vlrp6rT@t~L+ zP~hR31~*WWZXn=CojQwzMq1X$I~r(tqnwr8*+4iei9zG;1{pMN zYGe#Dk2lhZMm~e#Wh0$x<(E(1i*E~70uCu74cIW(nj zw$k%}m^jNp*o}a=n+*3aIwfMLwaI;pat;a)lHrO)lEY6>rI+)LvR~gq4?MmE2(7i& zu-yxI6Wx4^4aYmF(6!GHW$t!iRJNp8mKS09Ouzs6AnB7AJ)DE&Z^?ryUw{&XMnkP?l8kH z%*>s;&M0x;vuUCxF>#4clc!nCX7(8K@?LztCG4{AAfO;1n+viFE`W+6C?Ft$fNUZ= zD7cF#-~Zp;=ggfE-^=&?z90PN^zBnsU0q#WT~*!ZoNBqJn&y}%JsrW1LxP^1K+%bY zUY>bi%>yx`0-M=J=+gyFe(6-J7|!2&$RcbZLg*%sH%v{amiw#qkl zwals3nVn^Bwaly5b)DrY<0f-M!7+GmBZJ&Ea12f~3>sH?5{h>0K*(tFR>NyxFU}1O zUJpA^@^!ip(NANU=Qinq>&Pi9-MvRoh48;u2HPxaWme2&hmJ*JW(xA8a3df3r@=1Byuxk zCW=nVvr%-(TCP3O{ zWQ<-LWq5eYB_A?)_io)$$(##w&7;5+mhI8yWkXQza{AI*;5LcY-R8!+Y4;~rUquj+jio1a^Gs^At1-+n}$zXGuTtp z$2~+h8gbn6XevVU9a?b{xZ((;1=(wxTxr5Q1mxYjFd)a1pFO(Z$xoUcgcGhs1T9wh zI@?NQACWuwFB;@Nf%fWx=0C00-d*IgYVK9_=^|rlWNeL&=py54Xw61;fi;t9H9EbE z%&(CJH9EVCJXWKlIx+WobJW&P!nWjR(Lnzy8tC7KbDb~Mc4qnxW2Kp^kM<{m{bbN{ z;}{&^ua=J8lhxX{i*&1z?lsb*MtasruNu0|-AW@K?ncoi9{Qt*eHA{=fGNkX<3e*FziJiK%k8onNZZ|AJx zu~zmu1^)0mmEfc$B;sVOZn!cmWbOn(GD13B`GR03PB5_MA*Mq3>{EtP1w@9yCsA@t z6QUx=z>uxfGsA+4dZO@qBTxxOj^+_Q3;6zjd<5J#lUw@Qtb z@SZMiB^=Ymt%Os#5^}hELcmVF`=aQK%K#LO@iXh|J%*}|v!iZ^dwQS!wa;jnPOu>N z+sebNY~imm^8(KoAn7GCfl4m-8zs9SYV<-{-ntd%z_siNa+nx`? znBvC9<8iDaIh^9oDXKyohZm!!-90=0u2MHQf!x~UmxJ8iq|))S%hEKa*;D)L)R%ot&`$~J1mZ;C zKwSS^L&w;$z)cq%@SwWtJ7&u5h}qXJ!-tKXZVsb(`mSZ~9V-q?KWOsHtq&p3cC`q9 zov`Td61~)4?ZrOzndkeAYsZMzda?@_9VFx2tnA2>@yOeHVUnj?wK2Z$5kKiH#C~IK z@zhU^_NbPFHQE!7uQ9M6ccL|hbv`-IbJ zG>_ak4b2bSwcbU{guh(nsV~-Eo$6k5Yxkg+4$YlyB}DpS68Pkz<;MuuxRglv*z?t= zRE~e3()tO`UC?RO#=tta+4^=aHyv&YJZxEbpW{>JKW4T9kT*8D=+A0&rb+k1_5ZNF z&Nluh)(|(=Uy6+3+0mGsAC5`z0V#Sqi}X?Of)8zl-Fpa|x4sZuBC}AqosXu!9=9BR zMD);6?pLc%A|$PqU9Hhc8Bi+&Yh_Ta$DQ zx?~?)7MB>Y=~CP9aaOizjEkSCW?Ve9RuSF~tL3Rka4@`9?5@IyTJ9<=p+pubG%wD57p8<@CifGhTFi`QCQ-^XGBvc*9n#SO0_&t%jXc_*jP@2lf@w6t_?w= z4F=t4dFX~7U?bmdWg$*M&H`}?0#`WYQ=lE?`dT%k>E|nABmP)J!0nPRiX6wPCAI1&dLqZ{QN;UKlOkm z+=GO}!5f7)qgTt^TA5d?hpT128NK@&=h66R9)$`K&0ku1wF(i=ZOi(pEA6mBRScff z*^ewsJ&Rc?(kG0m)hD>ZPMzT4T5Ss3JYh-nB8kran*VKQ6LF8-**qEUY$C+4JDUhJ zmelfVqzE^b*2>ehilF0}TJGf!@*)`zN6`fxqfo@k#OIZn39*(%?nBXSc;1hqdo|Ys zDB3Mg^C|-OaxTX6_6tXtXvQE~1FlUicT<@=+4ZS0>uhg!JmEV2IXm9B#_0^^eZLxR zZ8k(bIV;i@xVvtJ{c@-++{(2ptTpJN#Z)WrQ2Le$9c+2&^A8Tf&>A-gPoZGeo5kTE zEC~l;X*dW^hl8*I!g2U zt1-*x-Rwu1lc}{r@Lf79!awXABLc*x@uM|da^457M! z6HW{%iFh1}qOGf}qb5x}21RG9$D-(L^*9u5{y`^Ob_SB2Fwyj)5fh#rtJNtrT(~9x z-i_z|C|YZ(Q!VNsqJ~5EKwF(&Bdcmxo`=73<4KRFc@Bpw6|7Q z*T{ajlC`?FM&34T{32olnKg$sf>=K0j=pSF%EKHfF)P7H-YWGi7Y9vu4q-j3l_Q4Q z?Gd%VkQ&eHgjRfm?Zzk)D02ji`wz#O9Br(T_iN>YTHS)>q?W#8ExUBlCv5l;vsB0(Du!6nVDghNK12@O|3n^wJt&2W7xjwp5-7DBwe zR*m*qzQz!ti@((jSCs4SkAJ?+0FIq7SJ61lltc)Wo z<^DFq%Ke6wi7ADvydj-ohlbb|YHKbs3;U>LqMkcZ<>`lqOl|mf>B|F5yAVx-{bTs}Zsru%)*BnU=<(=IuWd zw(nAWuxO38?^%ocXfbXyt5zBn$23Cwn9I$lQ7DF4L^j^a3$<=PqUkdIqHSb0;ad8K zn~yZyYs`Sv#^u1Yam|=j$fP;UD#V8y!jX4gL(@6h^q14I4YuVuwtGjLi)Lde8aQlj zXpk>+L$k^1mrH3l@{aCSOLs2m;$bTDD^%|t_TD_(=7yr)!p}m4zN?mM;=zc8U2Pq; z=~R2SB{82Q%6&_sC_>#+%LsLEEhE%@wN1`6w~dIlGenstYHt=$mYS#5vGW+_jcvfH zE+jE6nkJ!rfw$jQaSYRb_%*yN?3-Xv1fn6>m7i@K;b>L`QR zv54O}C_2eE75Rsj*g`7|ODytRZ7u}%7wNK(A>KN?WGZI{me4^criNCZ@`*V$EVK` z{7yFL%No(2YeaWi)+1%ShbM}u6j_vBDYs5ysdZ{=llDA@(A(lZS&SRa=y08+>|yxb zRD(C_B=6eqM;froIMkOiMs}bj`V@)A{dbK{hlyL6T_Hh;O zP%EBqc8v}-O$CeDMydZ^(>5NjlP8Sa5Q#Xh3*@>uz;Ri%QI^*wRsb(IpYw2jt&`z= zHkiYUqW+Ju-5qO5EG3E7z9kWLcWIs83umZ~FQvRM#ZcXD2s~349gCwY+qk$~7Lw-^ z5l->03iVFD6NU%Yx)mjiJ-y$uV|Oets`%yjI5;6icNW?~5ZbB7f<&$)6>aNP`ww(#u%c!vCcC$S({> z-qFO!LkFDZFS5AL5jXB|;q_qR!s~gxPPWy__Bz>7Cp+u(iInUz8V*Jrb6+DN<6~Xk z)PXP>-c%loZBx$|vl$t*J#~zX_8MJpTyrs39iO(3p)NdYNiDaePBicFb77A$mShw? zHqM|quVhcEg_K^flwPouJ~fnZ91w0ajsqf(_ab~hlfr4-P=c%Km~soUyR5RLR*+Pg zZ%IY{D>m3`QZU#Y7Q&q9NR+{PcoWiB-iU zB8L#iGS_#u-UD1Xr+QcfI1FAi4c@dQR$CI?e12b|NKl9qzBtNisuXs&Q4d;zYe=xQ z+jNY~Au{HNkzp_oTOCPBw=}(yPgBx8-NZ5Zr-%y(qsScoI5LMW4fK|6 z{AD&?>KeCCQ{j|bogOvb=`SPdzcSS6EV{FG1~JOR9y8R!JnSidxk|U?Ze1XCmDcxB zceL6FB=nN>GfUcmG_`%b>&$|_)(%MzGbDY|%#z=oW_Ae~@V@C5Sd?Ls-LS$WyV>PP z^|LhAkw&@S)6j^f)xfk4sFOiy8JyOEbuuI^L(@8_PKKrF2Q@}fI6h&iN_8ZBn0)60 zxe07G_akq6h;4Vh<=wVBBCW&fWKvotr*(9lJYaagBH|sPljD7Oo!M)7g~;t4)8G~H z4R{@ymQiULou-w&CoN;rG<{>!jM0#WScA!!mV483Us}eeWkOm&G-g0wuARydCf z(_F+S*U6$ZSMeDokqjP0(GBWDD7q>2Fp4e%`3Q(wcL&9S66S+VtRZiL_}TCsJGq!xK2I^W{HM%;4W;=v_4TM%Z;Wtk01G%fk{o7?IV~XYPh$H zub?e6K0u@0gfe54iRj!3E8=D&WLZ^n&wQWg#X1|42U~4B*Tsh7`BQ%IYgL_$t=GqM z=Kb_-$Ta+eHat{HjuA=XaYbC+!PMY&;IS8}Hn*Bfvx^E~q&4oo9FlE-m0EPxGn;40Y8#yj|fOyjSG zjc-otYixEao0WrUeWOnI*2&4V9ZE%{->%bRb<#JZ@7BqHjDAq3AJw(waa=M; zKKSS-Ol!G$r8q0DC5O2F30In-3Ya0(S5#WSiadH!#)_)}fG;Rj{LTR;V5Lx>;PalK zn8*PTtw`eA07&BcD+h=?0fZJ7z0Klh}TL0MrCb0vK`Xt}P4!~pv zfEZv&UI73!o&2Q(ti+2_P+!^B0#@=>dPp2d<@Eq)kLw>TV6cO7RDZA^+vD;4&6YZx zzhQDb?v$NF5bPwBr`ybo3U={V!r{E0CeF6BY)>n^=pAXtvsqyv>sr zoV@KhU1F3c7BOSik!$jTH%PnG(cW!HzL}QZ?PQNxiXbL81x;>+3q-J+C}qvMAcxZW zCL;5+AcWdeCr8rsN3j*-(Ba`b(~7j4v8+bJpn1WY#q@9zX+N;5676G6-=lT;Do|Bf z@jdn%*U+-TywI{G`3wWiOC11d*^-w5kmlt^Yc*)aXxYm7^aB9PYXL~hR{j+WSWYv; zxs90*qSDqpVu9;v0HmpFd#(j+dzAx(IiSUB&&L!%v3&}FFk;gFYZkCQO(7}5iqQnN zGY?JR$}ddP1h%`_0=8qP2pF0`x8PKA!7(QAQVUo~yYB1{T9*#ao_C-y183wYWE0E9mzr~MWHU2q-bIY`I? z{<>7SZdb6|P*JIH-L43`4dEbgkk)Q3Y0b3+8Z523mSAXF|JYH)xWHGEL>Jq3;v4`% z!6orC+jgRN*fzwN!Hp_MvWg@z0i?>2tO`j&yh!;u4+7UT0Q0Q)hHbme4{Y1P5vqF9 zA8Hm896iEpz|o`O8T|~?A|v?5$Y6N=85y6E2^o1fBadY0^3L?a$s)5*bar$Oiq7So zhoUoWkD-{57@nljlh(Yx#YS7WMn_~6@#*A@Jdn};X?ZY1!}c_AoP~J?MN40Mque6NK$heI5LHJ_2)3>NQ_h+EYMs6Fncz0=Ma^7QV;;uh<1 z9%WyU+qFGA#$V;ldp0E_Qw{Hk)1sl6mXYaZC=kOt#&3=o|50Qfe-hc^pN6&=V@xr+ zOYjccEOTvQyoZ@aW@mJCTIOVAZiYHBFT=I?iN;akQ^ao6pF+_spTpTdeD9bfTlvHM z*nSTyr6Rb*Vrjd9gB+u>c7Q9EYpOemG8CjT- zMHzYA$Ov(2C?hIr*QkjvMNMFJcEgG_86GS@YKxWFonmkU^FA9Z5(~m!(1lngd`>LW z8pSfbQ7ki>i$(8`x}uZpc$-GN-~+aWuNGP9!InaXwl4V4+;ZQ={D?nrGXm{~WvdbK zW8PMOq#wIU-r=VsW~GfEzsB$f&^7jB(x5&DbF2~3J`gd_@^qY3O8w!+BG}P?2GhO* z2k<#F{}>7M&!Ir=g!F<>h*{NKdzWW)QCeQe$h3?;o`%w54_Kc-1YJ$*@?_C)!Lj&L zME&+iztD~|DtAP4?_Z+1_ph9L=4|*DV_cxECX|dW#$=ozYw=UCw#2bUzKo4yj;2@R zfbzQ$PS5+80W}^DpNz9Ej%zOXlnqpzqJd|^zCRoGeVOUIZ44TESJdVIh?@G(sLTHq zb@}h12lcrgnmPAbF$1HGAzzb`movINEo(EfE~77`WxbgqD~ewxDDfeU5+Bwm@ez^4g{Q#r zI%_@-%6IMJ!;*X-RMYY9#!2+K@!p(~Ek*(_7qt#Zo*;LIXab7P67gAj=VVSsF&b~v z+wN>2;d;9)qwCX{nAo)cVFIc&r*K#lZg6#wPgs1e+=g zoK@(-CX)UrGZA-Y7{cs=kC>6&8F@1!dor>&Bl|M4KO+Y+auD9L@y+4XxxT=Sb6tVY z;w&DV61R|H!E*~Vyb8NM2R+$jt!om78IK%#6_-mh>Kk35Er?z?nA<5j_|fJBk_#9n^A=4?`QaGI0WX$&9U;v zI0#;bBbf^4scyH6$K9mogN*J>H=cmjH|*UraMKI=5+?52{3xS)((-X8$|T6~jC_)j z6B+r`^aNgo>j}IH*DQ7h+#aRzF9L2I@3l?zBk@*__!Kh(;JjefM~EE8&0PCoO&nRo zU5@Ncp@7_M4*HW=uDRIp#*;%x#o}YZS?P!WZS)9IepwlrRfOoHvvN;Xp|)ePGBzvY zvT|=$5vbpvm5EtJh(0MRle79!S{}&Cl&m6vpPH3vS(y%P&FIIpl6+4JErH{ZkCiwU zX%yTbPD0U+qD)57Y3KteIt`tIVwJ@3T78*{B3^?_4W+k$cLehT@$?q(DK~y0p58*W z)YPK*Ac`r8)uG78RqQKMf&mmosS^bxfT;-ytSHAPuc@?;0@8779deUr8Azm1yZUE| zG$1Pjvoa_vgR?ROb2ux*vNTY1*d2lSC_2Nj07Yjx=*GLlV@K^!4=QFU8tO$=GRn-O z&v}bv$*BpXZdR?qBoWR=Bmt=1=a@kcS^Rs#q>vC2e%gRDyzaGzWdjqkV zlM3vr(*f93r~R<2?tCTesy$!HK*EIuu&b>l;OiF=QdCL6?<)+oGP8_5Z1{O3D>Jk5 zsOc?+(lyu8je(iV-7-aUxktu`ZWt+bbP9owQ(r1nWG|tmmm&bZ0E6-+aHj5wVIngNXPmQ!WX2RFrxRvlEiY~d+4H*iT-RX{^P45U_ zvhMVsFIji`-wVaI65}g__`Y>~S{rX1H=}6BEik?Dg5m5GUW{+X?S(9j#)>SHGrtN2 zqy267M-Vc!Gw3f?7W6kvbXj+UcBUVib0RHzDs%v9-MNLUKnEY>Bsnh_$;;=$VVn4S zEvv`{ZO+nd9hPYlWn2`sad9+tE{SCJ<;YHaHC$<(fy2dk6QkJd=OP>1?CWUIw21(> zII@ZIc=FAt%`2kWiVU5LY_R?`jci7&IbKD>eO#S3nae{ z8w|$SCdQat-QH|tt`79^Y2*xZbqBIKIiu4uW_N}D5e#OzOURcqAE!7R#x%VFa{9WiDa9d|?V`)DK(lDUDn-8t)=T4s6$_pyyK*9P3385x%u zhed3b8AnXzNdGk=jp)jS_Rg@5C%tNatP%G+MdC(kNOYzV_s3bCmr(@ekLGk^M&WhO z&FNOSG>Fu53Qrb(>ytU%50^G0>vM{gXk$)CAo-a!AEt)glz@O49AEB)PW&J&+`mp4iq&hUruoZ`gFHblWtx2&HD@c*)!hd%Z!8lWu<&I)GDRyQBc|@wR{I3=;n82|LjcKu7?ujOJaDOq( zds&?YH`W;30}+hQwpu$UV{Fw#V&Lm1#zenwRxs#mwCW#;@Z>EN?Hmp!5vhekvaZ7M zEKSV<=%dN_!CX4+gSoUOCYVgD)(-0vGYd{+<6Vl3Iq8v;o;m52lioS$ zlasr1(l^IF7-)tg2$gWA1UqETn}IsGI0)i&aS$fFjf0r)wqa%PKr!Q(KS(m+iOCh^ z`YHl1<9S^lwS!REGOkZpQB5K8X-#@$vL`AsxXw|Xi=uHfLcm&pXu$RG2hjljFzO%Do^F9dfMOT8z_94)bGFUtY_pYXb4-p7(%77g z%PH0$ynQIAFPfw#9d_3a9d?c&Og9~NSUwbk8KhI@k24A%Ia(vibp=B4D!DJm@OFHT z&IabNBLzcZbpZ)6YeJ19x3b8Q3mzn4b%gKF>8gxO%yHd-eK2H<;B}4d&O^34mW`-8 z59Act9lR_*rwCiX!YK};@wpqkITFLp0+dQN8KbVEiSG}?jf2Pd0CNC`tizZMIlQ= zf>DSgv(Swe(8J`9HB<|&z#b*Bvd_;x7l}s32SVfH?T#v6Sm{RYbrfw!gIUFlMbX#% zobJfT0@J;njU;x3B<#eQP2A96F3Kq~IAZ(6NprjrkIpxm=CP99wkL1ep3Etx5CvLh zBbp@MZ6xu&AwgT9`z(oVmc-ms3Io0d@%pR z(p_J)weFm+DU+PPt4 z7Rw7BBXYTauOB;rZ(5ftayi0pv44bRBOyz2ii`^$%l;rEOLKbMB<>J8INmP}^?)bW z-KXcjX2j2=;bkVAU45k@gYK0jQz9at=-Yj)2 z;w@K5`pm}r{PaYo6iT(*%aa`z&cJ)F_<_&e-X#<%(o0AhePS({hc{6%a9YGm!V$YW zu6?p#XJM7zot1}LE3!1bJ8A!{ypYqLS?0w$}3_D}u+#UsDGJOY!QQA_20&OyE~A@=pFPLkqPJ zo+!pER)XQ^SS@EC!(fNUFxcpvog+^YH(c~^a2N~Frko7xsG}$x%sphNisv4{F}98t z!aJwF2P>L&fuY#$oFf0WC#Oih?ak?wtnAO} zw5%eXd?cqcv$`N_j&@=FgfOMD*810#=d*EE{2CJiF+e50u4=X55^+MsKnEEtwS!{Q{m}-_+zj?! zWqVuMiPf}?>@th;M~y0X+^C#!{!XCioWIXdw9a4fG|A%Ye#UzVqkTFV?}kK-NqB}} zVInS!6{1`K^*nS+%;_(y3Bj|)SO;=CBP$1u8k!9dV$BL$v7aopcy7H8mJ!|4hm98L zBUuw)m^}zDc#ikV9p7)^Orx7K^P9|>Cb9AE#oHM2Cq3%nI3TQRGUM*N~B@kk@>w<6l|Hj0*0$ihsl z6(pJW$D0}TUO1x!$2B>Z-p>inBt4PUr?S#3ugkK!JS%tSIko!c^~J2N%F3v`uFEPm zU&iHiQ&xHw6bFvpz$Q*Xkt}(!ATJg4?W`Wl%8r75l+{nNvb&(4W?S;Z894R8x2<;Q z;3iB5P6+JQb>Qh3It7?59OQC$OsTv;lg*0n0RX!^<-c)&m@tUFB3;w!jOfr={}077EUv`+3sPp30L3C2P?-3S1@yS`IM36-2^ zl@73yfNfbpz;?LagXqvrxkszHM2p;IhLWT#rO~~&KLVlc+<2m^xCns|9X-<)I{w&8$z{j)P z!g@N(*H4|yDYDJo^3pvoJ@O1W|ETrN>badP8vtUqM^osFw z!7JqNVpnLc-31I@BJX96_y2hd1gh-VX&JEtZFcNnO|k5R(Z;i(6XFG{iW|Yg{`?mh zDY#QOTJIXcKsytaa`WD<&Z~=w!H%r>Vmp$Jh~c!CBZfH38IhINh?vpyf;A)?jx$_m z3?fe9KsD%zTb6>C36l(kl_$)AybR3Cpu7yu%aFVb%`3Kdhvj8>Ua`YFB2Q=TbFPzF zkL>2QdGEkRG~uFk?sJ>ndt*co*%R@myw)02MsqeQ4AvI29O@leK0V@i9YI<&SIv9! z`f66jZAbyRunj4oatU}` z7Ac?#3HV6SEi?uJA1T6absGtI6c4-A?IhsdD|V|pNWjAZKjqng;53wOh0&IPd$2#_ z7Hq(;R{Y%eY9&aa^b6Qo3DPKGYa$~7zg~f@iJSy^ly39Af&}#_{o3~$Bsd+V-}v4c z5_ClgxsxwRa3)H~ot!1X*(m+q_s)^vT$GSIIZuM~QTn6rT_C}QDE-OzE|TD4ly3LE zOC-1yr9b=LmnHZLN_Y6)S0(rwN`LXauS;+lO8??}mrL*sl>X{_-<04Al>XKCu9V;^ zl>W{4z9qr8QTm(jeMf?;QM%LjzAM4^Q2KY@yGDX*QM$|bu9M(;xbhpQgcn(Ws# zG2fetiNSoo`Nig&$Cn&6zR%Lx4(@n63%ODag!%JX(-h@GR?OcEPE{ zoPzGhK6^pt6=Z%v78K;Mf-EfP0qm_8D?<7i396mKNmcf;>}@XA82d zAkP)#`GOwI%JPD|P|(9!Sy5<_^@N`~aS|&!sm1ddPH}iX!zm8WXE?=~jG|KlNgN#Q|}px(P}XDo|72O22<|^iP3H__1+*c8V;u3&yW}`2UG7~k{C_LJQUB8 z7;Oj7Wt=1Do`)jOWt=au3s7W6^g_9aMuQpAOC(0Cu?WR4ON?gYaTLEQU;8?WJd$yl z#4bmXS-x*b?3*Y)h2j+wyAnkv{H~JNw@_Sy;F2%~ayh4Z+3-Tnzj4(s|*?>N^(cT^kQ>Awnys z^{Wd+SW}Rf3$nH#>k9fl_QnfLTOv*3G~>$1q99>n&n@T&hGwvp#6kyWy&?8WK{gcR z)q-p+$fkn4R*=omS3C#PLADfRt6Ai+CFN)%A?K_W_VS(1eJxVCuSXhpS*UQq>%|@3 zSy1eI?JCfTxhNzW%I!pxes3dQ=-IqkP;7YZ!`yS;H$5BXH62^bYg+T6-Et;$++K`s zlTUb!(Vl|#$jROU(O+yt=U%=+XVx&-LDY8sL=$x$!u&N)2_n?Q4x8xRImVtx3)(-Y z1L5r#bQm^ou>)7H*hiRvL~Xr3nA3-IE%D4EgFHmFO`mOG9w+e=jts7S!b}NbNfSD{ zoJu)kC+2a=e-23Of0l=t5{3;Xc62$FBy%djmLzF%H#ee*U;>eav^LQsu3rWu>ZJ8w z0LiEHri85n?9_Q0(qx_{q#5j_bV~h6CSE#XR7m*P!JxL(LiEiINvY8k<}V>^`&sc| z7jZr9$04%L{u``m*@W7$g1l3ZcMI}fLEbm2or#FT;dknn3)L^!O%mn)WIuKodDSY# zX4*?tvZ{)P|D%HRI!%Y<OjEHCnmHLDG_&jmdx%oym^@j~Q90>WFOgo_XU(3k($P72p-Nt_(s4Q2 zQza{^^j>W7*3;7-*vRvsMxN<^yW~FoZ+9S%{3^F8Nw6Y#oWS;AukFDDMrPmw z8-th~h70z9&V%a$od?qgh6tFckb%iC7ni+YAL(hcVdNx-URpxIeu5aRiI##F9I!&M zTtFz3L!lJ0BM{01p-`rVLc!kJ|3{%rDH4hgS?Dy&A;;eQp3(RlU!x({U!b!6>ZN}@ z=K&5RH~}Kybt+pOsq7(=D0AAd!>H`eDj8U>GjlSiUa+_NXbyX;Bs8jVC`Oy1!1+IW z@Z0%FO;z(SDJT3X#&!*>Z?s)=XuE9QY-GL8%jskGVe8O9xkNK^!Z3tTfrLvmCvJxU z;BlbPKAGeWex3_JW1oHj0NSS^VJ7zoc~F0(|HADtv&9-WJbT$<^QB3}(;~L!QNn(#69^Nw1Y} zo=zWEkFM+pbWT82*2V8NZeHK@K?A!?64XWpcST~1~HDhPwX9V(kC{i5hVE(yxJ1lSJ`A6(jEB{*HyjU+U)$0gk3GkBtJX8d` z6;rK>z$npgtaOJjE4iUSvs}qHHE{oLn6nA`(vEHb%g_pXD> zK@s0Zv-Ce9eKqtgNn=}>)v)CBehYV^5pH9>mRJ*ntd4`4Y@t52P!Ic%9J1y96f*a-RQ)AM5Ail`dcv8N@Y7MW*nPPBOl&KAKl#3U}1Y z&5Cs48}+jGG}(>C6e+xV*;B7b7w)ZBWDF10%VGR4*9}O-=H&>C0Jfj<@>ac!Q++M3 z$O*n(kKCzl$tyC0N9$#2Yejx=K|9@^*PVGe2J4a6H}Z=7AcC>IHFK!t8>Y0b%v)i5UvIc}^6 z0PN9?=Qs)oCAkT8MX9kfD0Ff+kokjR%C8dE-ux=d{RW7Ysk!!;CwJI3<&MtC8^93V z(Ul*%0LC4cf&#XR?)ZkIgnV3Qi2H9H4U_V>25Zv(c7a9w+f_h>=Oll-5eU_|{@5Wh z#f3EusV>)6A579(E@`N008kwZVNaOvN`tX}o@=NdV2ttX=Y0j43B(h)cQw$kCDhNm z!8JlpD-X2MUQ5g0Xnc{dAoZ*{8~KXUfi~LvCZNw?;fD^5nX9ho)mUt(QT8YlY-?k^ zOM(9-)_foM$jPJhE1;dl!oNFwM8szcZe7G@>mk02xLwF0J(r0OjL5nC%p;Pg&_wEX z&<&dpSXiyb!i_?r8*aQ&7TIoQI~I61Rk1r}T>?8NgYLu){Fz4Ew^mY%MY?z7dYq4t z3PghSg1Pi8hNq9&w#|HU-x8Z|=9s->%qkp(9;EN-5<=5RhZPoGmlmOTm`GvB+we%^eYU1)E<8CN{R#hiH@2tRUfYWNY~)BuDZ zT>u0u+VZ3C0TA1@Kf2K&AhnLwTYl``*zjZbil84~2n6_t^5bg&h>`s9O%8$ic}VUS z$I>m1rCTnxGwPP_01@${-10LZV3+om-&#cTZXwT^)0NhwSpmBr_8DgTL)R1yk(xT# zbuR#?7?CD0ZZ!YzFWW2++n|-8xucjPdrRHL-g3XJ#(F_-^4=PnDe_!}JkLdDc?AY{ zUtUJHR_rwmXpO~2UZ{{26X0^dRn%rL_fMg$?XRg95wy?_}}hI(*aou_EZ&S_DzSg)wmJ~$pmZ@5D^ zKlG68cOQ1A7#(^~kF|Iy_H>H%W!+^4e;I(cL&vLo3wj97Q3x*|+9u4}?5X|b7S!-! zmrb{N>Sq?gERUZ1rNwJuxa?WxT_3bhfsF^l*p*U$wjcY6;F~;1s^d#*4LaUflkeM( zLj*Ta>Rk7O;Y4U*5e7CW^6w%KHs}gu$Qu~I)|VLz1e}HtM;a7rZm>rXyR$#XkKM^n z`HkK z?EpgCa}q$L#+-8+0O5(BQw>0#5P^MU=B*G%Jv{S567^g<3#ZZUTiwG0aL~OnR4~(i z84~UIeOYTRoj|>;Gf?q*tIKMD%00S^k#mRGF6R2)5m&rU%v`I1z@_x!dLUpaz4#0u zARn)T?7&fw;SX2W=8{`HAF9{Yr<92UziYFX>@!M zo8d24*$mr4hLuf!S;3qd?;p7L4}hGqJ%@Kn^rs4Doil4^$aGUc3(@S}KTx@{SPNdV zKg`thbhZ68ii2L}&+}tHm2nM<9R!irDs@Obp8waO^)jbHhu71;|4L}y1UY^?%LO@p zH_FKIJKugZ3AVKaXEw;4x{fmwy9%FTx2u7xF;d~kh%JOwsMi7TeX%ct30^M?8gx*- z4z4$=G_5ISLKPY$yw}^J&IV2i%crLWM=?XRsfOHq!z>qB zT|46j40~6;Hi{Imw}Pa(oM#%&>w7x)3;@=MHoQ-9QE!`ihm6Zh8zqn%HcB8jY>_~2`wBb;0`J)QTDL`V`*kF@--L3r5AX3fZ(t84_>*jzMP zo^G|j#*h;R$hy6#!qc7h*VyRx?xG4$_Y@I!uG)SJFpe0d{sKStSDDwK2idhZeRtEzB$I-b{9v$LD`qhgs4^t!e31wn>HMR468RQ zs2L1TN7!GkqoeFEGY7)~S6k^WZhYL-HLMtuZ6~(gZwZ*?8HqRh%Zb6>3qed@@xpcs z;xu|jeWT$C%!_h7wRQT41su=uQs0Er{TuXAq^vmWI)=L790Z+R1l~NJHunPmF+cVr zc`U9AnD!c%XEZw5Z%3UnrFxS~ah^kTxg5=VAv2EaCoR_#$y$l=7DX4=liux}NRAjw zEI*Sh`>cDqL7#Tq|0Ux7aYIUt*X8Lli}V1IO8xVJw7o)~2NF{;GXe$&S6WoGb(Nb0 ze(-Hwju;UCJbj^vLio#7hL?wJ;><#Zm4<<^FH@Q7WCU1adV?XcE}~(tsXyt6?PVs% z(~Y+EskYP1KOwQo{1b-^mc~wB-CP6~BH1>YdZybg+;oyl_+JJ&h+!wi@oc5;s+VUf z71@r}4Z6Et)->pw^)z?%#7$<)Wt+L&!x?wW1bl4g45UonnG3(`-QvjeeZ_jd#mt!U zo_d?E4Q7y|cK#xhbzR%Q?Tjevx~>7KOeh#q^XnVrl?G;CCsr!L#s@2Pf4!`$(ANTa zs8SEqw?xXsXfhnDPA=5K9H}-Au=t^ei&0CjE+ZtceDZjx}jm zq+?Ac0qIz*CMF$=4-`WF?HwUxej!Ouca@gZ^18d!{5(`7>?XZccjrNNx|N-YX8!?a zmk|tM|Ka^MdbD1T+5W)s@|i8Dbo&pL+`{4h1GYA}|Ij+ze`xLYA6h$rra4U4YLkm$ z>jO6k`k`g`c5vl20c-lpAVqoJ#`x!CIG7K!UlslnW-ymky1^_?o)=}yx0YgHwR;0H zSjd#4t3dwTn|MtikNWF5a=8AEZYM;72Nleam5=sND94cpFL;ElclMt&t-lef(wa)D zjcCsX>e227?bRS}HfZk#+0&q(l*--)?b9Ip8f1Ti-rb;m8{|NP_G^%X@M#+4P=gL= zXvv5HtukNR$~}tRDtxNG6`!#{zP8oZa3vrzaOAMe4O&^2O2rE17_fqsecb`#3@$^C zmX2b}kYY>s)JDsYBAjx@AQi@c!ZqzER-6Y)2udox>?p#jF(=W&QEU-XY(a`hQnUyu zqFpGv#2v-Bp@`q-GD!gnalSROJk6eaL2b3^yGk$xC97TaU@~#Ah=%VT0jpmaf?sd8-((UfB+{&%D-h>DCdhU z!BV)n=Jwc{UhIT~HaE`AaE^x8K@DatpGl=@=|9dKGfW}^Q?tAvI-S#6hne^mv(1@7 zOh_mh(PO%__)kI+~AhkM~X;zYJdF? z7b9ZuV#fA=g^mc?eadEZ-PU7MD#ompm|a?-G`M`3YGOLvs64d&TF;?iDpKgv7>^G|u7hSIFb!2;gL`^KF%tmvdK8+F*^l^bp& zbx`9OS&sxz>kZW3BOvQuSs*Xy4jzH&7IGtuN*{|3xI`WgF5eyvvw6A??uhPJB=Pis z7U%Iixg1Gt=+E^XxXpZhsc*ID`hw349_G*Wumv}D@L@M^;!VtFldTN;2QUR%UE7eUu7)YL+qK$og#y~WpbeS2AmsRh&b|#vFE|rGu-+GZ4c9o@zaTgt z`-v@M-;o1la2{}@xoW2l%o%As>~=yaX8==*wdX9puZ)2_5Xq zmV^%Rb*L}v5<1M+;l8X%=m=l#N$5zQTa}}H*_uGyJ=&LL2_56h(+NFZBIDxvNr~V= z-4iHR$g4^HtVHgu(32&~4TFo&PdsyTb&~zOI_%2TRp6X+`RW=UwhLXj8vVU4$&Kpk zB4J$D9yjSDU5A@DBz<)GhUn%EZE=&GzX3OIO8Q8Ync*|(*_(Ki?=0l--JJBXFx?zs z-dyW$-i({KCVjAH#@1kBtS#oPxOrRB$4YgZ!Ng$Q*3LJ+*KKJZz844nHURa+I)~hO zPmf@Hwy7sxS&UaXn9>=b#`DiT;Ur04Kq8mc*Ff^wrM?ETiz$VWeF-@T83gP@4Kk2Q zziSXcOQnW|oTE92kRw2|mKV030;Lgne5y{;5&l?~9 zKJQ%6ECA&`qD%!%L>^NON&{$4#mn+f$LO@EEdu>MAWi$t*gPI@Ku_xcC@qx4SbpY(S9v-C;m z9ddV^GvY6DcS8R~J}hHW_^;A8q5rD?rhk)u3B6PQUGI|q3H=ZKPdQnp|E2#e0}}do z?dEBBoUTh~4^Mk~+6x1k(B7W*@uWvw@AkB>he@pcJnfIiT`*}q9q7prOjJ)M#&s|@ z#4%AlZ7stRio+qZ;yTRJ;aJmgdMlx$K`*ZDWnQV?gUv$BQ%}F4V{wKnp-6~5AJ==a zLGIBojK`b2b#X;z}&I8K{o$u)a?BjVdDWMBJ`JhY} zdHOhl^n^a)>619`5Z9+Xc_5*Sv8Z{v6lcW~`n0Fdc={|fE}_ftmJv^%$J_i8x*XxJ zrz`L}zl5%YtK;cQc%NTFS3xjwc`%`?Jzaw%JUA|%(6yef^K?DVizoCIe6G^dS8-rG zp&OAD@$@yE7*FVCq}7o5!jbWWzK%~gAn66ECUl3VJK?c;u<>&e`UVs_p}ReO6L~HV zMpXCWw0J`I;ou5RZzuF^0L1jDr^h_~HcjI@p1$k(Rq|3oKlb!Ep0Q8pC!U_b6ZQ%H z6k8>bwCYJHeVmrIo3GuCDemEGPhZw1w3n~FjWzD$>)pPeko5`e>%;PFNN7J_`}^`j zLUF7%1q*uxUPWRo>=||Lg4kniA$TI?b*CEN3r)2TUz|Lqsk~xfSFR z09|Q}=#>QGw7jw-fVjPIWg0+u>#JM|pr0C(_)`K^;@(fI093`oX#nEO7k>(%KO}uP z?0+CHcnKX!(#k+dlhFay9ov?;WwSzZX4gP9s+AoDD=^9zy( z3N36P^*}L(buv)k7fv=P+=8EMP|je1D71!?4GNzjm~3ra(ud`vjcX~~bzf*uuwiBhlpY*@X3sI18M~Q;^Dhuq(SHW0+pWWy4PW^qLi~!2l zc_GSWKpA0BE@y!#mjh*lLE+<2BZx8uDBt9TC|6*)p907dxsrvBKrw~R{#8tNp(=~! zzQw}nD0~}4rjW=?5cv)-Byu$XXPS1u%L3c|F4~=G+T}x4Gl{YUDA({plxu;q#GqWq z0#U95$`XTeJy4bqWgAew&kIp*0IS;!tN+9TSv7^u{*8QbDyqopO)QYrAAra<5_uOy ze#i^;{GZXtyJ)u{H=7ds$=UZVAqU2i{w=%^@<+HoFh<6HY)YZWH!udsX@L9*FNFLl z=gzcPdo)T{bQ%F>1K?I(2=Frk%#L*cKoS7639tYFKj(!2zaYSZSVsW-5&#Pbumk|V z;)MXW5nxHIlLJ^nfad`4YhDQO8!qb48Gzriz)AW$ka~`ghXMI}UMR*t0PrxH`lI}b zg|vS=!Z4P;1e8CsaGq=BFmc}j?j5`k7nxI(sv)y~Vc{%?`%dgqp!}6pmpR;bh}=l>%JV+~(6o82rtmq?;|VeiAU#n%&46HWH|08j^d^~U zgqaPPKB%7!n3g#F4(*#=!s*!8R8lc)sU!3cCEiYfLO)WNO$zftp+D;98wvwRVLp0Q zfH-QVv65YZ3&A2NECPkWs9$6#4Dm`>Bo9MPC3&zV@?c9Te;6LiG`G(H zt>L7#h_v>C)(F(^HMB;O)?Pzvl&K^wTj~hIW=ox6*-#=NM+;61i=g#^CjEO*|AA6A zV@T@*j zLvSb(Z?UP2@HQK~CB)lIyo1173Xp@qE0L#3`XKP0@o<=yMOrR1w+<4zN6V!DEb4o- zq&${!X7p&uMd&$GS#9x9mxb0CK6|w63JTA&y&f$=VFV~F2k;0(;RW(Jq9yrUVJfN3 zD6x`udnNHk5N{6fUPS#IgU3g_P-M%iOeGf;lvv5Ryqb7(h_@biYf!)5;Js|**|HLN zYfWWa;Gx9(U4XZac8pY-<-B2Tov zsArir*ig{42m6D| zqeVXqU+rD5GKp`1^Gf#L$5#berl3DCwKSLnMReA2wM3&DHaGHtabe<{JQ!kS3%tH{{hmi$#zn7*bq7eQY| z=xdXHKh|GM;{6T5YYp)Mw%kbk+Q1v=cS_5LfgnEW!h1?2Xdl}C(S-9lW!wEAl>59J&ptb5(&~PF1_Q@CvKAr(l0Lk;|RwG z#1Zokj3d04!EqT9XSh2oF2mz8A}%B2GAb^k<8n`2#>A1N>m*C!vNVnuU7m@{vvFA# zm*?Ve_mBbjx-5_DYCzMA-TbMmmWNX}y%eJ^|kK_3T*%_Bzad{&yyW=?5A$#JoH!l0)vOg{d;&L!9 zhmeYl>veJ@uGb@yeLF5k<8mx6@5GUXM*Mo7=Z`NfM`9kAQal-fJt~ws#&B+rh0ZZN zbm*~^#us4#j}olY>E*Fj_-hd8X`S94cj+mgj+rflR|tHU1HLN+zAFU23&5kj@)$zy(O#)*cQkg~EKwXak99Pe($NeQ=K!)3FNQEy z&p9}0PhL@|1`4vFbG#HVD2F*-z2j&Oan}PE+0FG9S6S+4ao2mDO>?NJ!7CsPYz~j~ zgW7uUOHTCbz4INl^`tf=RvxS7CG6smnCs(^SlG!Sv9Omz=<81}DUa3gVo<=~^pa4} z(@R20Pp6x?3y`(Egv581w2!5@t-h945#;Egt%DpLba9ZQ3HcBp z&*UZS!b6~GbnhXcSap3U2uJ)OqC5!{WLKVyP@W9hSd=G&)1X)6{K>%C43vPf0w`zm z61K7e#7!$Jf)1{g6+w;b>!XrNDnTeXROO}=hQDd-uer}1Rx zwJMKYhLmjtIj>cFKwb{Wd96YXnMa>@1t7n{OGtA?t180}>%#S61tAXt@|(PboF4>D zqe}+?NX5Xtl+(k5twL*g5V%+Tp*(ga{yNMn{!j&@dKD_Na3socJu~)g$(Nw;73}H} z{z}Y5-uQOxYIFUk*mngfuq%*Ky`qO-9=nDYHyu%`GIUtSNrpFwpajUf0eKxS1`=-~ zxf_tzLmg1);!y7P^FYCyMoWVm(tijNuVs91|xJM3t2GLnuV^ho5Dq$R2lm* zWPw6kJTHLZMyU(r1}lgXZuEg&|0yp9CB{-^>{g=mDQRbM`(PyiuFt9zJH$f95$OX< zf6F8g`57-^yOT=n_@j!WiX#{(r7iBHk_N7ZU|Xc?5L@a{SL#8 z!g;aZ%O6p zSG-Rtt~GLRT=BY#xHjnN+%!8w>*T?>cGWM*LvcM*&yt7ZdN!T(N8);p%#7=~@@QPo z<7V3VGCQsp=!G&Tt{3UWGB>W5$h^2-DhuNJW$smdg%0x9JozdZYVG;e6?9vxjkLhK zU)=>>D|WPfgsUyH74T47W_c5SDN5D$X3H#W!;Ka6P;cbT1kBKlZDTlA01?WKxOr)Z8%{waSz}>-{*oQ%>9d7c?OLySrofR?oV|Vgq4es69K2~dX zhwiKe5E;Qpita*`K9P9o%7 zK*ATn9y4g>06Eud3!2~p|zh~&B6|xp?PfhA7zU5 zW;g;?-YL_ou)XDew9;#_D{ju8wDik$q~|AL&T-gdC{AtwR}n6Z#HKl7e!oo>RkjWJ zVTIp@Ql!eZLEEhrc@n_`-KN1xMJ@uLr^c@bJio1u_5IFx!Pe?>KDIs`2XS;pOxEKK zA~C36W3o7@FOBDrAgURE?diWB{F$Q9UhZslJaa) zpD&SRNp4BMh(ujdSCz=VR=T=Go=?j1q`Z)n6-j-$MAw$c%A~F<(e)+rVp3j8>e!gR zQlcA>WJ~I+C9*n+2dL%cq^wQq#uDjMF6)vElh-HZK)G%zkyn!XT8VB(k}QdXDzXuG zW4fh8HYMe?q;4(2OX6iql1Ae764{!R*OR)fM7AY$dx>mM%8sP$Ovg|yOZ)}QuZVf`Ti2r0yt@14$hjlY>clJRyhB$D|xd%3Dc!J1Iw# zIG6B$xOx*XDT{0WzxwSyGd;jeZ!nFZY$~{+xZoBQ#XWI}d%Sv0Zj4crc;iiO;x#b| z$R>*{A|QgSiYN#Of+7maF1Vn8E25}?fPkQ=faw48J#TkUe*b5lXR7+GZ=KptRh>F@ zD(uSWX#V3=*qyNrsqj@Me4Pn?=oR;hNJ!PWL0AutI=$0l-w>Z2-I*sc_2My8>(gz;1Oz17Jg>DMx?} z0&E8W*WDfiDE)RAAlKU6*B0b4Ah!#-4?)#C7$l4N*=cO3&mmM3Di%o@&4DHQ8imIhDHVUZW<|!FqRXCi(*4V7+expf5X- z7|>UM(E!+HjV=My3ZwOXGT%>=Q=vS$MymkTz+?et0bpx2s{t^pMs=tI`dI=j1i%6P z!Un*?nsN_WD8M%W*d%=u11Q`#>c^`&ow9MLG7WOXv4vV9rR=#b>u;T(`7 z8XZ+aj?ngH8py74Jllj%Yt#nhxlByc8XYU7Je~2J2k~i&vY066%PB`$-00xs1ysAf z9a$p2Sjbf%nVwcvkgFhmQMef7sz#@kkgJ4z7vxXnRBG?tMjE2t!36jez|Z7V0G~Ee zC%=STeJa3i0GG-s=W2JOa^>u%@Nwnr7IJLkEE^@93aPP;%YAihV*pPAU?P380q|sF zb&{Wx){_Ff2;d4i6$&plZe7alivp|!aHX6IU}fV&XsWBAuu_0M0MIYk(*W4hSPPzO z0PGRqz9!iu+6MPEsZhADiOQ=AxvvR;@c^!qQvr-`QXZ1y1$Z35FXU7Jk2fh7^Kk*j z)n=2|%ZUN%$>VDI{x;wLLrx{)+qLS4Hvo8BfOP{tP&0r-`iGO1~G zhm?Bbw7POvpC;sdkpCs8LTY}U`j|+~7hoxXU&|?zT3XkJjoVMi-_kmb1y%l1Ay+^Zy;^{&0RAecoWxWI+$F$N0iFZ!e{#xz=dvxK@Dl-^6JQyDyXBMt z%bda`0xT2YZ2*6hQwF@9Ekfbv0=zB27Xbb)rwsT4z&&(80AC2O55PaJQIY_b>8AI*Ed)u$iLi(6rY1|Nv2AbRt8Y6D_wzFi41Rfy+7^a1gF2|>o6 z&#Ukrc37zoKQHKFp!We?97Ej~4-kFRaztHov7jq~_64xAA>EaEvBQ3xzw#BxY9Kt0 zgIme`Y7#C%RtxeD5R`CmE0A~c8ngF{$~%Ir2Qm=I`Uc4Qym;XtLDmcM0}v_V{LldT z!Ko;>KM2vckWCH&(YH`Zr*A>Iy%j`Xj3k6fARYiQsR1#mp!reUW0DXrffx$nr3S=H z1vR#ovM&iSs%bX)Ac#@%_R)RK${l%BQxFqCNX=(L1u>y%1u;R0*&v34m|a24W(&$- z@Nb8boch*mL6-rQLeR3(ZdHAGnF2m4W|I#Q@KMoAOQ-v&cu;aA)-vQfGWoE~uF89A zax^yo+%pl)ybWSJpWm*Kd%Jmkasmcz{bPAO@pkj7bEA6W ziKoVFIoYY%)QBDT_$X|zwP}$}io%Xsn;wOo=v_zQ%UXLn3cG4;W)ybU+9Of;s@7&j z>{IQT$Yw`jPp!>~?Aa)MQ)|yfHa802qJtgTyokNBEsJb<6#B3`k8DL09;&nVFrXTR zC+h6;$hJgbN}cVD?8_+3uCwk*yEhr0tFwN|Ft^V7C&Tk~HXs>#*4h0@8<=EIY=e?v zRGqQI9zyFhrAh0Vc~I`>*OG*e;{C$Kl7#f}s;Rssl9nt3kd`Arjp}Y$LOMRW2C__m zR{=DZBLMe5Q0wDjFSGqF-ydl6E02w&~pw}#Kn-XA+0Ph0eZ1P

_*Kq8%?kM_GAAYav)3i_%V8~1kX!9l=eMI8zLgkDL)kW{Rx}}FFdOnelZhx znE-sm$rj8@9%hKY!xZaHq^WFVgAY}BPb$O_N_^4t!(ri`h6O*{_|Vqx)z*c)nM)pi zyU+B8r@z{XmhLS`fy(8V?|%-n9|o*@3RoWiTMB28@7KT}E+63Bji+KMf|DYlOM~SD zU|}Cdt9y!8p`7-8>&YLQ)P0%M2WWWs(5UXwr~->9eEXU2M3ZF`JWg9Sl$tUKwqA&Rdz2(F}TG1AZCH3`b*u@5eL4FDBVaP3B#?A%d2>&2nh125L^~XstK= z#eB1ATIIm{j<9-jjoe8#OP2O0|qZdpR zB=Kuw_Db#1k;moE8}6H!bv zSC5g6Fqsrfg9ua(=T!a+r%`gGU8ItxKpxjmyb{Q2oo^$8d4*uvQeEU19ZZeE@+PDw z_Bo|KN-+LLsnkA|q@s`^14tq|j;B<&OGe%Om2WIBmGgU*QL{N-zGg?yGX8mCOWnd z(bU`>V<)T{Ka@6_QM!gjOqmT@5>`0jMNn=`-$R<;?{_kGC7(cN@`eTSrk=Fmz26-_HR~tXu7lmHpv2$aeH!6|N zt!2vNTQkbJ=$;oBtGnA*oB;Ox`^lEiZ2HIbA|yZc~S)<+~g z-N;p8EZv~vN+{(DJM&Y`*4#yNE1zF$&Mn(pv*?CcKY5rjjEnZIyE4CO9OuuhJ;Nwn zyF6~EB14v0Y9vg-EP(ry@6g1W28vWYQRD6j)dDU?JSB}Snxxs|=>ZCvyKcw{m}}cA z2!69TFUhuG<_d02G2HkuJ91KH`7hej^f+IvgPqJ=Q$eUFKr=YbDh^zR9~W=E3A z%l7Tb{EYEQGM-Qe38;=9O+#2U@098Y#|YP_FgjwYI?@PToxm7* zSgu*~G8=brFuQJD8TDG3-QBWTv&zek13T~Sruk-97<}{S4JyW3EJsg=<%da!*m7j8 z3Kzh%9J3cVeD->UtSbfsXA4}u@aC?MPEHyNvqpX5rg7s;tTpFN3$38WED*seOIV7* zPG}itFEFvy*dF2PN|LVpK&Zcnc|BJ@*?^nA;r5_47oNb%TZeWVEpw)krQA(-=A^=w zKnl$J(>O{bY!Z$-B1y$a&{j26#7PK(>YI5ah6Lu_2}de9$d-{v5;AZ)m8!64^RjNa zO?;ev#q{7>RVRyo`k%UZaEWEgZ%?rZ0dh50$X|?~7gknocAM3$oy&S{T<3*W8Kq2^ zzN~aG`SPOWF3CBL3sTJT*3sQ*6{BQ^22DQ@o=C zedr5K3zaXm}Xz9koLzG5TYr2$q1Goy&@G2SOkMJYhx0=?5LHj9Lyn+Z zzJi##lX6oeBAV!W!KNYu=tj8;bUjgV1l|M^$Tv*~Ue>U!9oySCjdB}rArEEo z4-J+(!s~CqbVie47bX^wFB`fXFFswSyf-eZMww7HyO7$#BP3l&SAij&d{u~2N;m>l zcQO`{CY17$ZJAw&SO!lg-w>9R!d2nvPO?5m|D23p>E)OebRS6;Hs#*IH=dAJc#L8# zdjRz$Z)I2mxD_SSf_;dJnWaZD_;;1MQO&%YWlb-jBIW*i;sG^OAjk;nHFKy-rV;TJ zKJ71eWz<{f$s*Q2l1~;%1#f+_Pf_6xD+9Yzaj{NR9kb7T5{2@>tb1lOO{gom3u_rt zo6CK47PgrC>XjJ{(}<$=JNg{h3|f zF&d;f`;NEfduCH(lZErK!`o~3)^yGnoz0o0{B_`fqItU6oXD>grcSR;uIFm=8?Exy z4r*~PVSsQQwxqjo6-m@$^kE{z?ki|Q{G1t^_*s^;y?i{Eg@V?2mA?BF`QQNNssQ{XG{e$1M8 z9M)q$DCn)7|7{Rk?# zYtvI{<$n5Pit(*a=+-~9e6JUC4P{BcP!#wei3NTxY-$r`?54c!3^ zAHc?raPQhswuxmDOY{R)Jr&)9)_uz& zgIBm>p|4{SA?xAlmea?=yDDlj;YMc$q=law;4uPSM1!!gtBlzFtwLoNR0F^UWvh{^ z+Hd&3m+VHvwz6x6d-k$thEvAT~2=YxD>qg1}S5l&GC6%Sq~WZhjxEGBR>epUOjN@koXFCTcUtYX@Sg6X8INT8e zWJGc=?In@#FYnaU%=?V#gy!`=xuVl>gK($8Hjp`$;GN8hoozaHxmALDvV>`Z@~|O$!MR~J;29jF zK0Wy>->9$;tEFPibF-skqk;bjZx)=UC>x%U9d48wF1s8Uj#Sjj_!1O+EH2AXG5izb zVf+%leY0fNuFNt=g${|q4a2nts`YCc-dQYL6oS)OX<4PGohTj3K#YY0lW*X@hDrN4 z=|ynOaA8!v!<6;eA+nX^MrdYzi+r%pI6dr>SO#J31Pq)}jhoN<~JZ68INltf&ALsK`<>EvT?@o_d5!U@D|kerbWGN;yE+3Js&; ztS9oz2t)$k5y}h$rdMSc7w0CKA|o&f>|iynTP53aYp!Qn-lA<)YE@UArHqZwLYji9 z;W+S;eZfSh)@^5AR({~y1^HVs&P7q7vW|E$#9>P!QY~CuAS9jIYuQe#L2mPaJtXoZ zgv@_HI`WsIaFp26Nv0#JBw~q2B+G=pl;Pk0GwulRP5R;X6nXfdD>Gp1|V2^C)#>8Rb%}!pNStf83a~w&Ca3>!gOGz_UZ6St!@tC4_JJ~ za*wc9G6*tsc*`8Wh=396)8PZMK3Pl;hV)U4R`v??p_}zX`H+~B#i@dpfN)^k19rA_ zpfYho8D!Oj#6TK=mE~sfXK+D>ffkcQ$_bz*5kbsJfLPa@?|yVFNG-Xz5JVD|SrQu? zL#S~CRD|UeBsW`i>{db@TeeZJ!rGzHq|o=v0O`IDy-WT*K07u!YRpbejvHfBkiE&$ zeKGqIf`6;zWxkrZFxwf0AH9`Vq{L+D-HCQkg)g_Qx{>uU!GxrFUT1p@&fs@;TJt{9~nu1v?g)V zA0l|%FL_Q~mbP2BJ@*Z!TG;YAgJN2|qa=qloL@v|2C#|cO-~Z^WG>mom`spi3WRRc z$PZUVO;5_qL=D&hE>e%t0{L9}!nld3p;;6Q5tL3MzupYAYAWO?uAqg6D*}Ia0}{iJ zb<^`9CV*YgLLi1FWIh0!#u_Eb3Y^~wYJqJj6zMYF!#EmHh(u1WWGOIAjDWJ=z>V(kIpf|$xoSlDUXb0K+b170N}3l@iW2!Bbq{o_sG~|Cg-kgz4;jSXE#W%DcCDA0+&B9k~B#BWnI*s<3=cEiOfCeIA( z9VX7fF5>tU=cO#;Nxw;zP__>zVdg?(9vethsn;fEPdgV2^p?g{w_IuNV zG9;j+l0?dYBwo7Zi|i6Eg?FCeU2QVrqb&wVPlqy3VTAXal>NZc&bc8hb2gpnELjzIGlAuWaRtWC%j6Cm+zv0aG0W46ZGS;B?u9 zN8vCkIbsG{NM>Nr|Clkzw8&9`;9>y{Cq6N;ObLOzQO6x+dx`2P`d<{)fP=>fCBo>4 zplmMC8;@Heb`%wM3IBye9IR1M_OJFUWmAk^@`31vg4wCFSJJc4Op!7}>f0&RS%z~r zP+i+y9!&d)jR%N*xgH`G2n7*|N-W02b1W=}*zS5tqo5iMB?vL-&dJ0g43ZaSp%9G0m{&$03nu4?UCT!JZdI>U#qg=KxE6i?co;=~a(=#v^bI^HMNCc-LE z+-d7RxJXL6O(&yXbQ&ivSfnK+GIgevPzX^vp4DhNbMXw{zM6VL8C~6)sBVRANYH*U zqn#-nB5U4hWh<3c#zq!@gN*j8K_T1u3s`U9L$(*2TFz_!4a*iji&A~aDK?Pkh*j;DnJV>SKV$Wr4F32CaOVX0vw&T zh~DEoa9db4JvtqVH0-p?CH-3j=}XUCrrS6}MhUXo$AG-JEE+Y5HPr;UaS!ovK2doH z>?NagGm_Dm^cUz7*i4?(b^#yaW7~9HqZ-ngP^rITTP0YpQx4cbNvC8@@iiX?qrT)M z9)>HY)MVgvNz7!V{E7d`k<%jsa>*RQA~eHC2jo_&BLw3@`K>Ih$N@&Y(J*y*C2Plu zK0B@D2|be)4B^C@V4eEY3W18AEYJz~1a%}>dehnZNW&>x+N1cf+)}nfbne=^rf`WF40b`o$5aT+grih32Mz z36BegS32|Sm}m&pF1!jtQ_?jxuYl$B&6iN=EG>~W@E^)@TvGe&qFc#Ybu&{kV5otI zOWIAtb>-sFC9`g{DatbXU2edFG`-CUOrMn5dbNgGw@VlP=SotPmB9t0?y)*$ip_qbhT&osOGO!Sz7jwzgqO3517vKTl?~(5q?LDwsnuN9 z>Q#4o!nwnGTA7i46s@L|c|Sn6R znGWQdfg_;Lp!_u^Nl)V;N+LDgCdfrB5SsO?*o*`8*Wr)|gvQBdAs-5;0sAxllXPsc zS`N{XslQ5rG(@MK2?z>RC+6>AL9eZ_(*ogpCT2SJJ;Wocp&&3goE{siGcFeY&mtFLHwV?iV2 zfiS)qkgpKYePIdMHWUHHM0bT-=XnQWTVSz#=9XVq$E;>_63 z-(^N0stMl(n}WS|jFq9O6*(m=YZ+`v{RKDlfaNkG(%RAe;pv^tL~*QLq+ zA77sqhKLMI%4r7+<=wJ+$0u1Bn~Q7_mC@auMfH_xJyT>ghD-uvH!FI+h6HlYxvb`B zq~bsmG~s%*S_W}_-BAi0*DW2Z-`mnjX3GI}G6TmS`URlf#iL|Zr@g3EO+CriG!IE+ zNuYe0;#kQwMPsSDiYb(wN2R;UQ3d6L=$ThOnT*}yQg)bxO{PV0BPn{_g1MVNpa98n zy#?428po}}g~zH73bWkUNOeFbBZ^&#(_LgtohAw@jW(QEG8144FP8Fj<~`2^*Zq>| zz}S*i((GXafEW6VjxBf_v{Bj3D=lkut%P{Ry(FdGaBC$FMp|V z#0fOfQr6ve!DWU@@zjD67J)?T6F%mKAb-g57hAP@Ih3Nf1S4<84n9RHLz$d0iwx4& z*Qqeho~co#GKg59j*`GC;bMi$M_|0#F|S$ZQp=shex{{6o|nfm7)^~PXkdmBpG1@X zf|E9l6q<>PiIy27Rsl8xO>!9`QSO?c{pHkcTcw=g!4*AQ7pS)^f~jY0k2f9TW%A-L_L&+^Ja_qHS5&i`6eDJQp2Mgl)D0EGg>Vq zu3a}QqZ=7SU`Qf{2o&0q=m4Kc7)H~>ua>5^2Q`8uqEKVdmP9moB0;#VT305a08b(W zRrlH=hyqR|01_8i6orUDi<41NGx`-DsW`B4tn^bvH<`!X33g@xcY>UV_D)a}fzzYD zLs@iYGljwe@V;J>sU?6T5eeB6Y-gs?>`E8`Y(>X3E_MwMj&oRUZwRyL!&CQ>%bK^c+pvs`25ELS|2f;7s;37C?uU=#dh7>PGh@+ z`CrKkJglY9DVtH>3x{%N;!Kq=!RD(1&k_4%aH|}#A-7gtG~oDchuLo$Y~9f2pQ!4J zCJ75)X(G$lfkl)Z+gq_)R(Tn{9;#krjDs4=z=;aD7DQa&i}#dhDi}V#M$-#yftVPV zuSA%RBv?6BiGvDcDRGSxB`9&og4tS!+$0&IxU?i0w#bYm8JfssBn_Glc}OyJol}rx zxMH%8WXLoVj}%Bd#&}yJEaStds%8UX--vhcZ{8Gk!-=OP3dq1SPBdQc{CX^%RNBL zW|6(a$f9-cFb2YQ@6g(KM%g=jB#`$SAB*U{!z+aL-XRrZeDAQTf_;y%`%(W6@b(a8 z`O<|+XYUZAfu&C|UQR=`#|aYXhoUDe=$mX4?&HM)eYx&+n3hDel_wwT7JdenP3X`= zuj15$oMFid^DZSf*(fx4&cOSGZm!@h)iQohR{CzfR5F{M`aAJ*p{TCdG$q-zCk|VZ zNlzTEs{LjO4#HIIY||)Rz)gpi(J*6Wi|g53*sa396!6q;D2tT@2r)Wzx@Hzr>cRa| zxV(&g1>a1JR<(T9L-CwDbAn#B+E!n42(11qXo0GbKF7mOmz zFySgK_SMtjqW|ThcQXWs!HsggX2I)+O@>wQl{k>>LfbQ4U!0g&0bJ>7IaJEB z2y#UVSTdV+yNxtsT4e`_nES9C`Se^s-y#}2$c?f5bZqM>csx4zM#$~v-u6L`Wt)Q+?XeGEo#I`jp2_NAyD zrAY+V92t~Pk+vJqTkXOK#z*lr`m^jC?5OM_x$KT%!FB++d|C2^KrEesV+>7f z+D{#p;9YpL<&OloAPMIm{0m}**~gZhfrwwFFiBPT|^bZ=!`+ zm-km`c>E7GZ27I(6jz%%?7s4ID?Ykd=6vv$SF5`@*Ql5!!xbou#ejmRR(~b*!2KKU z|Igl+z{yoq>klLXvM3-5$TmqpNFcLhfrK?73j_lRB!Ch^x--*BhRjS4-7{H0kWCOo zMHIvZ35W=8AcDAnvORG93+@XlB8un}aN+Tkr~JQD_tfp%x4zq5-Fcb>_G^_Ub(>>~7))`N^c9fPHx z3JQ`hyFB7Y=#Ig$rX;<~Xw#nS>MlmS7SV~?knQTil65fRgGdjqm1NFParxRT4w*#; zLKvUrJ^k6j`jTR%29|bNg0n3P2BfS7=VPi*6ah75lv|hU8XC+66wVdhT~HGHNbA19?1xHo+D=&=_egQ(LZ}=0p&~F}_{$`T&mpmn=OrFh>z`ND_TDCB@Yrg8K7&9k0OjFA4=;4eQY1!@2_MX-<&|WJyzBMRK zF$U4BsaesoGorkliaTTJT3fG({#Csnv(1Fk44PM@Wi=&8c)j6>=0Q}8jWL=H>sM1u zB3Cnx;Mk06u`$M^Vg0;f65btZYlywosG$Psbq{D3pf`Rs%VHSLT9x7# z5_t>+Py3@Rt91#V52iDEY2{e0r{+Y%!pdA0)}Bf(3yIQmS(Ifp!y9&4!@^1~Gg0Hd z^4gcIe^<>M(W<|D$%I9Cwu79Nt6c1o9^Dfuf|h|tR%|-^Z<~asWx<@CD|QunBB!28 z-v)<}!#$X4%dn8J{t?+2i<0I@(y-7a{FJX8^b5A+;h0kwSX%q z7vg&4p8QZz9vZ=GmgnA0BfAZzZZ*Q7%(SqSS4oPHF3qHfG98AbXjojC=gbwGC->uu z51tC)TDn@52np+VL1Qe+&B86+;Ys(>H_NlQbzDz92M0|e-vu`Y$KmMtHgc}e<33_5 zP?vT~%g)F(y30`gm}FW?SBvXLvU9T8A?E&evjb5|?&f82v>a8d5gT1>qRLmx@8tcB zSDsnTO`LRhB8JcVo5W6l=Oqql%?g`@Pnw&~;m*y*Q~pAgHie?rn6k}{t>>Q5@YSG3 zcA18`G&G`WbE9gH5k#l|jc4$BA0CLRzbOp#;WMnc=@ag!Zag^?s841+vQse2VH3(c2RM4jyi%v(O&&+JO(74` zRl2T_Mwc8LPc)-iZ3=-*P2aj=XioE%3TL?cweiF=NyAMcwoTE!rZ|UJ9K`3H`mSP+ zbI}RV>zadjU#o#xqJIn8Pl{C0>vjcC!>YI1nzG^<3Y+NLmE(p9>~ zkk)Y^+Unb!NN;pUQxnWhVf=1{H#k%>w#Lj72Nm1w^FlVNG7(W~Qz#H=sas%>o>3njDo6Ai%~{?V@^(XbimzU1}QF z7|EpFhj1nxhOpMX#}FzxqA?y}^=k}xc;adp0vpO2(fFjJMcmE7-cjsGSp*3v7YRJCr^Pa0L@u<@wNW9KZ1Q;w6vzna5Rb9uUwx%Z+IR?3cxvK}^{ zr6#oGF5G)-7wr0ESm(^VIer|e8l_H&(GiF~jEQrYKNydT^C^P3I3%It|b` zo01i{Nh~-7UMXY3AUTrOypeGjnJ9h7U){^V zYF>@bqY=HTb*mnXO-kcZ5HU7p=kWCYN<$-Z#ML)`)%>Yph;Xjfqk06YaY$Ka$%nx} z2#de3kHQYs6t8Z2I;`Rr*#i^K3dq+&?;UnWLgOwOA=z;s)_B-6jpK%98I%U2k}aqb zi?Y25HwUM1;BnZG9yVKG$#p?-utO=jFiw3GMVSxd07^}4$!W;9aMjY?UBIK8aq?7F z6o-~*Dlb36isU@^89aXWbRd5S>wU9*@&ZQmeT6(3r+}`Y{F>!Zcr zw@hrbv5Oj0EwigH%3t|r4o`WNSus*gZSgVB!Pke!M@q}an}l`G?$uH;TACxCsMc*` z%-~JRN5hl;;repp&FoOcO)=%tQGR%Gp~j;L!#@M1aoEB0Hh{EO@oA_&JXz4l!Gz&Y z3GV}OoBHZ&_zfMNbPIRIH{J;-RB=7VI+;CN=%a$3gl;{PJY(<9=@k=7#O))ahN#-gfMlH*pj zYqCQ}RE3B)mo${4_^s6uHDrXvm;7j!O<{$v@dRWf!6K^yx`b|IHPpO0gBwt7bZk`1 zn$6A$v)8VqP5CdS_=N0WzOSdNZDHR0*n9NnjH_KDu~c^_a%agBvaPtjzpK3gZUy`j zcTZogtuNP?J8LN0+ws8NE8@y7=~x=Q*hH62f=1G^n%;(KJ$)ixTSE1yLyg+Iv_*b> zIqLJ6ua*VQDe1f>0HR&$3AzyzWzwIYl^<9ildk)a4WtA1pdxnIENH}%irsEB;u66W}nBX*B8XFU-`n1LbH={ot zr`996iC%49+SX|3NF{mG)hq>XR=#f_Tgc7q?_RVPhZgvh5~(6kEwV)>g&N92t!B!} zqDa;choq9D=I68B+&#%TaUymQxN1HN{shhH?^@r2(^11*aphcrokqf-{Fb}R0Z4gI%POzh?>M8rUMcMh zINIO>UXLo|bgQpd#E3}B2W6_}T|P&rr6`f*$xt>uq!o3qLhLAKYD6O|U5BHXTfMeB z-Ham5@IF$a-23C3;{G}_uL=HdM3dnOKs+KFQ$XrZ-gHM%ol&e`eJAwgqsARZt+LNh z7P>lyeZ6MZyuacUoQ5UG9agc-H&7H!UNz7^u4lz^SVstJ+i7v)5Z`&xV{_%%SJAii zOg9bqGZ^RfI4YIF8C#I#i*4OKg?are@*aCB5n?m(L{dZc6G~s}ur3Ep7Xn4OFeXtf z;Nc)_5meH~Z=D{Y$Jj1ym2G$~yGy-gAzIoh+lVY1lWTveuOFv~GXti{@kS1pxR({; zD()=nXd>dJzuT<_Wy?KRi?-!G{naJ?>ejbjPnYWuEcS1rAjo|WnYv;xNw|fB-P6o@FnG<6Hy$k#4hU6sIF0wQJRw46)7SjV`Er`XWIZ) zPv#ceIlY4(rQ7Xe)QAX?%Ir|7J@h-nAo-gp>k6F7R{`UsFIaJM^!6+HZa1X712W8W z9&mU`5qCg_c})%ur+U~&;zVZ*R|rO%1C}Med>g;^!RaA8`VJTw8x1n4-7Ff0I_#o+ zYBnsHOG=gz@26!fVV#csNsJwrIEh8w>F$Eo&@X0DSwT*gW_rcdWg{UP3-*0UeB!rp zG460Hp9&r0qcdW{mmV@m(4xi>tw@iOxi!#7l*0)KbFHC$K7eWfII<_kpDba!#6xFU z#&71RfpxsAD?-oc>LVUQ))A#EU7Vxc;%tLDZ~T#4m+KlD%q3gnK5| zITE9~x<UG*MJ;AIXqq}4pb?q^Y6G>nl` z{s*;2HpaK&3dZO-iwLfiGV-|mvZtR^BQ}DlYJpe6+ZgSGVM3siiZtQWHz9*EJ-vER zW#zJ15)a#p^7MbAogW!;z1R;@EO@J3qPpAcK&o)kSK7gaQ!ds6C9I+c4;YLja( zm0j7jyl1f3Hg(F>sU4lMADN8|+xTrBB=mYONts`pcgsp`*0!E&k|XeQ+?L27uQVRY zp3P*9_3djCwDsJW*Ryz)eBRL!&)~9KDC%>084F)+<(^J^?_!;nM*KaZDnxU*{Fam& z{h8t&Ep_E?dUv$cB|hTEq|zUmNE0m&?#-*K zHCWQDqFTEOk>o5ZHud$T=E#wgAMs+W*wp056bohTK8z_IVbJ{e zMf{gkBIUNvIcD!MUr4b=a@(T9YO9jbo`IUFmq|~RQ&|~T&4Q@CaZmZz=O~w9DbUq@ zSXNo$mQ;01^02SkwcHnRpO)3QWGUrL$`Y}RLse~(MO5utu7fco$jOn^AW~^!1uxms zaznKE#ClitMl$=VUCZSgM~qR|%L%leeI6U<_lx7@Mu409Q8RFcqYuP|4 zEr+W{hy-_O)lOxSjnczcvO|mG&Wcw$VwvvNmZ?9&MLRTSM5}gOi%1TZmAv|VTE?Pk zawW^C+BFtflOZEexGQ)wR{fG~jhQksr8{m&O#7h#l##5gRJ`rEqG4Tg z$AuDwtCaFMhheYiaRrPC!≶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%0DeJL>#S_7dopz;$Fkm&z}vpRsxWvmF}ZP=-DqFN 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 z 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%0AhW=V_i7vKS(O{y3+s*aVWn3Rx^21zL{ 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 z Date: Wed, 3 Dec 2025 13:59:41 -0600 Subject: [PATCH 07/26] fix: update e2e tests workflow for pushes to main trigger (#558) Update the push main workflow to mimick the pr checks workflow. They were not in sync. As future enhancement we can extract this into a separate reusable action that can be reused in both Signed-off-by: Pablo --- .github/workflows/push-main.yml | 66 ++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/.github/workflows/push-main.yml b/.github/workflows/push-main.yml index 99a3e05a5..434f25587 100644 --- a/.github/workflows/push-main.yml +++ b/.github/workflows/push-main.yml @@ -78,11 +78,73 @@ jobs: with: CLI_VERSION: 7.10.0 - - name: Build and test + - name: Install Sui CLI + shell: bash + run: | + SUI_VERSION="1.57.2" + curl -L "https://github.com/MystenLabs/sui/releases/download/mainnet-v${SUI_VERSION}/sui-mainnet-v${SUI_VERSION}-ubuntu-x86_64.tgz" -o sui.tgz + tar -xzf sui.tgz + sudo mv sui /usr/local/bin/ + sui --version + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Compute Solana programs cache key + id: solana-programs-cache-key + shell: bash + run: | + key="$(go list -m github.com/smartcontractkit/chainlink-ccip/chains/solana)" + echo "key=${key}" >> "$GITHUB_OUTPUT" + + - name: Cache Solana programs + uses: actions/cache@v4 + id: cache-solana-programs + with: + path: ./e2e/artifacts/solana + key: "${{ runner.os }}-mcms-contracts-${{ steps.solana-programs-cache-key.outputs.key }}" + + - name: Build Solana programs + if: steps.cache-solana-programs.outputs.cache-hit != 'true' + shell: bash + run: | + ./e2e/tests/solana/compile-mcm-contracts.sh + + - name: Run e2e tests uses: smartcontractkit/.github/actions/ci-test-go@ci-test-go/1.0.0 with: - go-test-cmd: go generate -tags=e2e ./e2e/... && CTF_CONFIGS=../config.toml go test -tags=e2e -v ./e2e/tests/... + checkout-repo: false use-go-cache: true + go-test-cmd: | + set +e + + echo "::group::EVM" + CTF_CONFIGS=../config.evm.toml go test -p=1 -tags=e2e -v ./e2e/tests/... -run=TestEVMSuite || evm_failure=true + echo "::endgroup::" + + echo "::group::Solana" + CTF_CONFIGS=../config.solana.toml go test -p=1 -tags=e2e -v ./e2e/tests/... -run=TestSolanaSuite || solana_failure=true + echo "::endgroup::" + + echo "::group::Aptos" + CTF_CONFIGS=../config.aptos.toml go test -p=1 -tags=e2e -v ./e2e/tests/... -run=TestAptosSuite || aptos_failure=true + echo "::endgroup::" + + echo "::group::Sui" + CTF_CONFIGS=../config.sui.toml go test -p=1 -tags=e2e -v ./e2e/tests/... -run=TestSuiSuite || sui_failure=true + echo "::endgroup::" + + [[ -n "${evm_failure}" ]] && echo "🚨 EVM e2e tests failed." + [[ -n "${solana_failure}" ]] && echo "🚨 Solana e2e tests failed." + [[ -n "${aptos_failure}" ]] && echo "🚨 Aptos e2e tests failed." + [[ -n "${sui_failure}" ]] && echo "🚨 Sui e2e tests failed." + [[ -n "${evm_failure}" || -n "${solana_failure}" || -n "${aptos_failure}" || -n "${sui_failure}" ]] && { + exit 1 + } || { + echo "Exiting" + exit 0 + } + cd-release: runs-on: ubuntu-latest From ae0d7082156d243443257d38ea0b1694008ab9e9 Mon Sep 17 00:00:00 2001 From: Pablo Estrada <139084212+ecPablo@users.noreply.github.com> Date: Wed, 3 Dec 2025 20:03:25 -0600 Subject: [PATCH 08/26] Update docs link in README.md (#559) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 80d567f80..0c446444d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

Many Chain Multisig System

- + Official documentation
From 4265edb8b96697770b432dc02f1883dfe5dcc470 Mon Sep 17 00:00:00 2001 From: Kristijan Rebernisak Date: Thu, 4 Dec 2025 13:37:39 +0100 Subject: [PATCH 09/26] Bump golangci-lint (#557) Supports and extracted from #486 --- .github/workflows/pull-request-main.yml | 10 +- .github/workflows/push-main.yml | 10 +- .github/workflows/push-tag-release.yml | 10 +- .golangci.yml | 3 + builder_timelock_test.go | 2 +- e2e/ledger/ledger_test.go | 20 +- e2e/tests/aptos/common.go | 17 +- e2e/tests/aptos/set_config.go | 2 +- e2e/tests/aptos/timelock_cancel.go | 12 +- e2e/tests/aptos/timelock_proposal.go | 17 +- e2e/tests/common/signing.go | 95 ++++++++++ e2e/tests/evm/error_decoding.go | 37 ++-- e2e/tests/evm/executable.go | 3 - e2e/tests/evm/inspection.go | 4 - e2e/tests/evm/set_root.go | 18 +- e2e/tests/evm/signing.go | 97 +--------- e2e/tests/evm/timelock_inspection.go | 17 +- e2e/tests/runner_test.go | 5 +- e2e/tests/setup.go | 12 +- e2e/tests/solana/chunking.go | 9 +- e2e/tests/solana/common.go | 51 +++--- e2e/tests/solana/execute.go | 27 +-- e2e/tests/solana/inspection.go | 7 +- e2e/tests/solana/set_config.go | 12 +- e2e/tests/solana/set_root.go | 7 +- e2e/tests/solana/simulator.go | 11 +- e2e/tests/solana/timelock_converter.go | 40 ++-- e2e/tests/solana/timelock_execution.go | 15 +- e2e/tests/solana/timelock_inspection.go | 22 +-- e2e/tests/sui/common.go | 10 +- e2e/tests/sui/inspection.go | 4 +- e2e/tests/sui/mcms_e2e.go | 11 +- e2e/tests/sui/mcms_user_upgrade.go | 39 ++-- e2e/tests/sui/proposal_helpers.go | 1 + e2e/tests/sui/set_config.go | 2 +- e2e/tests/sui/set_root.go | 8 +- e2e/tests/sui/timelock_cancel.go | 8 +- e2e/tests/sui/timelock_inspection.go | 4 +- e2e/tests/sui/timelock_proposal.go | 9 +- e2e/utils/solana/testutils.go | 9 +- e2e/utils/testutils.go | 2 +- errors.go | 2 +- executable_test.go | 8 +- factory_test.go | 29 +-- go.mod | 105 ++++++----- go.sum | 221 ++++++++++++----------- internal/testutils/signer.go | 37 ++++ internal/utils/abi/encoding.go | 8 +- internal/utils/abi/encoding_test.go | 8 +- internal/utils/safecast/safecast.go | 1 - internal/utils/safecast/safecast_test.go | 16 +- proposal.go | 8 +- proposal_test.go | 26 +-- sdk/aptos/configurer.go | 4 +- sdk/aptos/decoded_operation.go | 3 +- sdk/aptos/decoder.go | 7 +- sdk/aptos/encoder.go | 4 +- sdk/aptos/inspector.go | 6 +- sdk/aptos/timelock_converter.go | 10 +- sdk/aptos/timelock_converter_test.go | 14 +- sdk/aptos/timelock_executor.go | 14 +- sdk/aptos/timelock_executor_test.go | 17 +- sdk/aptos/timelock_inspector.go | 5 +- sdk/aptos/timelock_inspector_test.go | 6 +- sdk/aptos/transaction.go | 6 +- sdk/errors/errors.go | 2 +- sdk/evm/bindings/abigen.go | 6 +- sdk/evm/bindings/generate/wrap.go | 2 +- sdk/evm/config_transformer.go | 2 +- sdk/evm/config_transformer_test.go | 4 +- sdk/evm/decoded_operation.go | 4 +- sdk/evm/encoder.go | 12 +- sdk/evm/encoder_test.go | 6 +- sdk/evm/executor.go | 4 +- sdk/evm/executor_test.go | 33 ++-- sdk/evm/inspector_test.go | 12 +- sdk/evm/timelock_converter.go | 20 +- sdk/evm/timelock_converter_test.go | 18 +- sdk/evm/timelock_executor_test.go | 6 +- sdk/evm/timelock_inspector_test.go | 40 ++-- sdk/evm/transaction.go | 6 +- sdk/evm/transaction_test.go | 2 +- sdk/evm/utils.go | 7 +- sdk/evm/utils_test.go | 8 +- sdk/solana/chain_metadata_test.go | 19 +- sdk/solana/common.go | 7 +- sdk/solana/common_test.go | 45 +++-- sdk/solana/config_transformer.go | 8 +- sdk/solana/config_transformer_test.go | 10 +- sdk/solana/configurer.go | 13 +- sdk/solana/configurer_test.go | 22 ++- sdk/solana/contract_address_test.go | 2 +- sdk/solana/encoder.go | 2 +- sdk/solana/executor.go | 11 +- sdk/solana/executor_test.go | 22 ++- sdk/solana/inspector.go | 8 +- sdk/solana/inspector_test.go | 22 ++- sdk/solana/simulator.go | 8 +- sdk/solana/simulator_test.go | 8 +- sdk/solana/timelock_converter.go | 12 +- sdk/solana/timelock_converter_test.go | 2 +- sdk/solana/timelock_executor.go | 11 +- sdk/solana/timelock_executor_test.go | 13 +- sdk/solana/timelock_inspector.go | 10 +- sdk/solana/timelock_inspector_test.go | 4 +- sdk/solana/transaction.go | 13 +- sdk/solana/transaction_test.go | 6 +- sdk/sui/configurer.go | 5 +- sdk/sui/decoded_operation.go | 3 +- sdk/sui/decoder.go | 1 + sdk/sui/decoder_test.go | 10 +- sdk/sui/encoder.go | 11 +- sdk/sui/executing_callback.go | 8 +- sdk/sui/executing_callback_test.go | 16 +- sdk/sui/executor.go | 3 +- sdk/sui/inspector.go | 6 +- sdk/sui/inspector_test.go | 8 +- sdk/sui/timelock_executor_test.go | 4 +- sdk/sui/timelock_inspector.go | 1 + sdk/sui/transaction.go | 12 +- sdk/usbwallet/eip191.go | 13 +- sdk/usbwallet/hub.go | 2 +- sdk/usbwallet/ledger.go | 25 ++- sdk/usbwallet/wallet.go | 2 + signable_test.go | 15 +- signer_test.go | 4 +- taskfiles/test/Taskfile.yml | 7 + timelock_executable.go | 3 +- timelock_executable_test.go | 80 ++++---- timelock_proposal.go | 18 +- timelock_proposal_test.go | 26 +-- types/chain.go | 2 +- types/chain_selector.go | 2 +- types/chain_selector_test.go | 7 +- types/config.go | 2 +- types/config_test.go | 14 +- types/duration.go | 2 +- types/duration_test.go | 14 +- types/operation.go | 2 +- types/proposal_kind.go | 2 +- types/signature.go | 30 +-- types/signature_test.go | 10 +- types/timelock.go | 2 +- types/transaction.go | 2 +- validation.go | 3 +- validation_test.go | 6 +- 146 files changed, 1148 insertions(+), 971 deletions(-) create mode 100644 e2e/tests/common/signing.go create mode 100644 internal/testutils/signer.go diff --git a/.github/workflows/pull-request-main.yml b/.github/workflows/pull-request-main.yml index febf6897d..dc0606f0b 100644 --- a/.github/workflows/pull-request-main.yml +++ b/.github/workflows/pull-request-main.yml @@ -16,11 +16,12 @@ jobs: actions: read steps: - name: Linting Go - uses: smartcontractkit/.github/actions/ci-lint-go@5ef875a78da521085ad768ecf2ed5e25009496f7 # ci-lint-go@2.0.0 + uses: smartcontractkit/.github/actions/ci-lint-go@bd2ca3d8fa2dc89f98b49b297e9b72c2e3e68cdc # ci-lint-go@3.1.0 with: - golangci-lint-version: v2.1.6 + golangci-lint-version: v2.6.2 use-go-cache: true only-new-issues: false + golangci-lint-config: .golangci.yml ci-lint-e2e: name: Lint E2E tests @@ -31,12 +32,13 @@ jobs: actions: read steps: - name: Linting Go - uses: smartcontractkit/.github/actions/ci-lint-go@5ef875a78da521085ad768ecf2ed5e25009496f7 # ci-lint-go@2.0.0 + uses: smartcontractkit/.github/actions/ci-lint-go@bd2ca3d8fa2dc89f98b49b297e9b72c2e3e68cdc # ci-lint-go@3.1.0 with: - golangci-lint-version: v2.1.6 + golangci-lint-version: v2.6.2 golangci-lint-args: --build-tags="e2e" use-go-cache: true only-new-issues: false + golangci-lint-config: .golangci.yml ci-lint-misc: name: Lint GH Actions and scripts diff --git a/.github/workflows/push-main.yml b/.github/workflows/push-main.yml index 434f25587..87c5c9f35 100644 --- a/.github/workflows/push-main.yml +++ b/.github/workflows/push-main.yml @@ -15,11 +15,12 @@ jobs: actions: read steps: - name: Linting Go - uses: smartcontractkit/.github/actions/ci-lint-go@5ef875a78da521085ad768ecf2ed5e25009496f7 # ci-lint-go@2.0.0 + uses: smartcontractkit/.github/actions/ci-lint-go@bd2ca3d8fa2dc89f98b49b297e9b72c2e3e68cdc # ci-lint-go@3.1.0 with: - golangci-lint-version: v2.1.6 + golangci-lint-version: v2.6.2 use-go-cache: true only-new-issues: false + golangci-lint-config: .golangci.yml ci-lint-e2e: name: Lint E2E tests @@ -30,12 +31,13 @@ jobs: actions: read steps: - name: Linting Go - uses: smartcontractkit/.github/actions/ci-lint-go@5ef875a78da521085ad768ecf2ed5e25009496f7 # ci-lint-go@2.0.0 + uses: smartcontractkit/.github/actions/ci-lint-go@bd2ca3d8fa2dc89f98b49b297e9b72c2e3e68cdc # ci-lint-go@3.1.0 with: - golangci-lint-version: v2.1.6 + golangci-lint-version: v2.6.2 golangci-lint-args: --build-tags="e2e" use-go-cache: true only-new-issues: false + golangci-lint-config: .golangci.yml ci-lint-misc: name: Lint GH Actions and scripts diff --git a/.github/workflows/push-tag-release.yml b/.github/workflows/push-tag-release.yml index 328c42517..45274dd16 100644 --- a/.github/workflows/push-tag-release.yml +++ b/.github/workflows/push-tag-release.yml @@ -14,9 +14,10 @@ jobs: actions: read steps: - name: ci-lint - uses: smartcontractkit/.github/actions/ci-lint-go@5ef875a78da521085ad768ecf2ed5e25009496f7 # ci-lint-go@2.0.0 + uses: smartcontractkit/.github/actions/ci-lint-go@bd2ca3d8fa2dc89f98b49b297e9b72c2e3e68cdc # ci-lint-go@3.1.0 with: - golangci-lint-version: v2.1.6 + golangci-lint-version: v2.6.2 + golangci-lint-config: .golangci.yml ci-lint-e2e: name: Lint E2E tests @@ -27,10 +28,11 @@ jobs: actions: read steps: - name: Linting Go - uses: smartcontractkit/.github/actions/ci-lint-go@5ef875a78da521085ad768ecf2ed5e25009496f7 # ci-lint-go@2.0.0 + uses: smartcontractkit/.github/actions/ci-lint-go@bd2ca3d8fa2dc89f98b49b297e9b72c2e3e68cdc # ci-lint-go@3.1.0 with: - golangci-lint-version: v2.1.6 + golangci-lint-version: v2.6.2 golangci-lint-args: --build-tags="e2e" + golangci-lint-config: .golangci.yml ci-test: runs-on: ubuntu-latest diff --git a/.golangci.yml b/.golangci.yml index da649389c..39d79b70a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -42,6 +42,9 @@ linters: settings: goconst: min-len: 5 + gomoddirectives: + replace-allow-list: + - github.com/gogo/protobuf govet: enable: - shadow diff --git a/builder_timelock_test.go b/builder_timelock_test.go index 0890d3022..a23bba2f5 100644 --- a/builder_timelock_test.go +++ b/builder_timelock_test.go @@ -12,7 +12,7 @@ import ( "github.com/smartcontractkit/mcms/types" ) -func TestTimelockProposalBuilder(t *testing.T) { +func TestTimelockProposal_Builder(t *testing.T) { t.Parallel() // Define a fixed validUntil timestamp for consistency diff --git a/e2e/ledger/ledger_test.go b/e2e/ledger/ledger_test.go index c3a37b45f..cbfec273c 100644 --- a/e2e/ledger/ledger_test.go +++ b/e2e/ledger/ledger_test.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package ledger @@ -10,16 +9,10 @@ import ( "os" "testing" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/usbwallet" - "github.com/ethereum/go-ethereum/common" - gethTypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/gagliardetto/solana-go" - cselectors "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/suite" + cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/mcms" e2e "github.com/smartcontractkit/mcms/e2e/tests" solanae2e "github.com/smartcontractkit/mcms/e2e/tests/solana" @@ -29,6 +22,15 @@ import ( "github.com/smartcontractkit/mcms/sdk/evm/bindings" solanamcms "github.com/smartcontractkit/mcms/sdk/solana" "github.com/smartcontractkit/mcms/types" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/usbwallet" + "github.com/ethereum/go-ethereum/common" + gethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + + "github.com/gagliardetto/solana-go" ) func TestManualLedgerSigningSuite(t *testing.T) { diff --git a/e2e/tests/aptos/common.go b/e2e/tests/aptos/common.go index 0938dfe64..d6787bb23 100644 --- a/e2e/tests/aptos/common.go +++ b/e2e/tests/aptos/common.go @@ -5,20 +5,23 @@ package aptos import ( "time" - "github.com/aptos-labs/aptos-go-sdk" - "github.com/aptos-labs/aptos-go-sdk/crypto" "github.com/stretchr/testify/suite" cselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/crypto" + "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" mcmstest "github.com/smartcontractkit/chainlink-aptos/bindings/mcms_test" - "github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain" e2e "github.com/smartcontractkit/mcms/e2e/tests" "github.com/smartcontractkit/mcms/types" ) -type AptosTestSuite struct { +type TestSuite struct { suite.Suite e2e.TestSetup @@ -29,7 +32,7 @@ type AptosTestSuite struct { MCMSTestContract mcmstest.MCMSTest } -func (a *AptosTestSuite) SetupSuite() { +func (a *TestSuite) SetupSuite() { a.TestSetup = *e2e.InitializeSharedTestSetup(a.T()) details, err := cselectors.GetChainDetailsByChainIDAndFamily(a.AptosChain.ChainID, cselectors.FamilyAptos) a.Require().NoError(err) @@ -46,7 +49,7 @@ func (a *AptosTestSuite) SetupSuite() { a.Require().NoError(err) } -func (a *AptosTestSuite) deployMCMSContract() { +func (a *TestSuite) deployMCMSContract() { mcmsSeed := mcms.DefaultSeed + time.Now().String() addr, tx, mcmsContract, err := mcms.DeployToResourceAccount(a.deployerAccount, a.AptosRPCClient, mcmsSeed) a.Require().NoError(err) @@ -57,7 +60,7 @@ func (a *AptosTestSuite) deployMCMSContract() { a.MCMSContract = mcmsContract } -func (a *AptosTestSuite) deployMCMSTestContract() { +func (a *TestSuite) deployMCMSTestContract() { if a.MCMSContract == nil { a.T().Fatal("MCMS contract not found. Can only deploy MCMS user contract after MCMS contract has been deployed.") } diff --git a/e2e/tests/aptos/set_config.go b/e2e/tests/aptos/set_config.go index c01489201..d8c8c809a 100644 --- a/e2e/tests/aptos/set_config.go +++ b/e2e/tests/aptos/set_config.go @@ -13,7 +13,7 @@ import ( "github.com/smartcontractkit/mcms/types" ) -func (a *AptosTestSuite) Test_Aptos_SetConfig() { +func (a *TestSuite) TestSetConfig() { /* This tests setting and retrieving the config for all three timelock roles: - Bypasser diff --git a/e2e/tests/aptos/timelock_cancel.go b/e2e/tests/aptos/timelock_cancel.go index 9b71e03b0..0f22be332 100644 --- a/e2e/tests/aptos/timelock_cancel.go +++ b/e2e/tests/aptos/timelock_cancel.go @@ -8,17 +8,19 @@ import ( "slices" "time" + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" - "github.com/smartcontractkit/mcms" - "github.com/smartcontractkit/mcms/sdk" aptossdk "github.com/smartcontractkit/mcms/sdk/aptos" - "github.com/smartcontractkit/mcms/types" ) -func (a *AptosTestSuite) Test_Aptos_TimelockCancel() { +func (a *TestSuite) TestTimelock_Cancel() { /* This tests that a timelock proposal scheduled by the Proposer MCM can be cancelled by the Canceller MCM. @@ -192,7 +194,7 @@ func (a *AptosTestSuite) Test_Aptos_TimelockCancel() { var opCount uint64 opCount, err = proposerInspector.GetOpCount(a.T().Context(), mcmsAddress.StringLong()) a.Require().NoError(err) - a.Require().EqualValues(opCount, 1) + a.Require().EqualValues(1, opCount) timelockExecutor := aptossdk.NewTimelockExecutor(a.AptosRPCClient, a.deployerAccount) timelockExecutors := map[types.ChainSelector]sdk.TimelockExecutor{ diff --git a/e2e/tests/aptos/timelock_proposal.go b/e2e/tests/aptos/timelock_proposal.go index 25ce20746..7ed56b9c9 100644 --- a/e2e/tests/aptos/timelock_proposal.go +++ b/e2e/tests/aptos/timelock_proposal.go @@ -9,21 +9,25 @@ import ( "slices" "time" - "github.com/aptos-labs/aptos-go-sdk/api" + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + + "github.com/aptos-labs/aptos-go-sdk/api" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" module_mcms_user "github.com/smartcontractkit/chainlink-aptos/bindings/mcms_test/mcms_user" "github.com/smartcontractkit/chainlink-aptos/relayer/codec" - "github.com/stretchr/testify/assert" - "github.com/smartcontractkit/mcms" - "github.com/smartcontractkit/mcms/sdk" aptossdk "github.com/smartcontractkit/mcms/sdk/aptos" - "github.com/smartcontractkit/mcms/types" ) -func (a *AptosTestSuite) Test_Aptos_TimelockProposal() { +func (a *TestSuite) TestTimelockProposal() { /* This tests that both the Proposers and the Bypassers can successfully perform operations via the timelock. @@ -286,6 +290,7 @@ func (a *AptosTestSuite) Test_Aptos_TimelockProposal() { startingOpCount, errr := inspector.GetOpCount(a.T().Context(), mcmsAddress.StringLong()) a.Require().NoError(errr) + validUntil := uint32(time.Now().Add(time.Hour * 24).Unix()) mcmsTestProposalBuilder := mcms.NewTimelockProposalBuilder(). SetVersion("v1"). diff --git a/e2e/tests/common/signing.go b/e2e/tests/common/signing.go new file mode 100644 index 000000000..821bbd0e7 --- /dev/null +++ b/e2e/tests/common/signing.go @@ -0,0 +1,95 @@ +//go:build e2e + +//nolint:revive +package common + +import ( + "encoding/json" + "io" + "os" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/suite" + + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + + e2e "github.com/smartcontractkit/mcms/e2e/tests" + testutils "github.com/smartcontractkit/mcms/e2e/utils" +) + +// SigningTestSuite tests signing a proposal and converting back to a file +type SigningTestSuite struct { + suite.Suite + e2e.TestSetup +} + +// SetupSuite runs before the test suite +func (s *SigningTestSuite) SetupSuite() { + s.TestSetup = *e2e.InitializeSharedTestSetup(s.T()) +} + +func (s *SigningTestSuite) TestReadAndSign() { + file, err := testutils.ReadFixture("proposal-testing.json") + s.Require().NoError(err, "Failed to read fixture") // Check immediately after ReadFixture + defer func(file *os.File) { + if file != nil { + err = file.Close() + s.Require().NoError(err, "Failed to close file") + } + }(file) + s.Require().NoError(err) + proposal, err := mcms.NewProposal(file) + s.Require().NoError(err) + s.Require().NotNil(proposal) + + inspectors := map[types.ChainSelector]sdk.Inspector{} // empty + signable, err := mcms.NewSignable(proposal, inspectors) + s.Require().NoError(err) + signature, err := signable.SignAndAppend( + mcms.NewPrivateKeySigner(testutils.ParsePrivateKey(s.Settings.PrivateKeys[1])), + ) + s.Require().NoError(err) + expected := types.Signature{ + R: common.HexToHash("0x1ed7807767b09344df63797fa4986ce092730813922ce01563062cf51728ac34"), + S: common.HexToHash("0x556721244f77182c1130a5ee8d78ac7067cef52662dbb57b4132c6ec567ecbc8"), + V: 0, + } + s.Require().Equal(expected, signature) + // Write the proposal back to a temp file + tmpFile, err := os.CreateTemp("", "signed-proposal-*.json") + s.Require().NoError(err) + defer func(name string) { + err = os.Remove(name) + s.Require().NoError(err, "Failed to remove temp file") + }(tmpFile.Name()) + err = mcms.WriteProposal(tmpFile, proposal) + s.Require().NoError(err) + + // Read back the written proposal + _, err = tmpFile.Seek(0, io.SeekStart) + s.Require().NoError(err, "Failed to reset file pointer to the start") + + writtenProposal, err := mcms.NewProposal(tmpFile) + s.Require().NoError(err) + + // Validate the appended signature + signedProposalJSON, err := json.Marshal(writtenProposal) + s.Require().NoError(err) + + var parsedProposal map[string]any + err = json.Unmarshal(signedProposalJSON, &parsedProposal) + s.Require().NoError(err) + + // Ensure the signature is present and matches + signatures, ok := parsedProposal["signatures"].([]any) + s.Require().True(ok, "Signatures field is missing or of the wrong type") + s.Require().NotEmpty(signatures, "Signatures field is empty") + + // Verify the appended signature matches the expected value + appendedSignature := signatures[len(signatures)-1].(map[string]any) + s.Require().Equal(expected.R.Hex(), appendedSignature["R"]) + s.Require().Equal(expected.S.Hex(), appendedSignature["S"]) + s.Require().InDelta(expected.V, appendedSignature["V"], 1e-9) +} diff --git a/e2e/tests/evm/error_decoding.go b/e2e/tests/evm/error_decoding.go index a82191255..53eda264d 100644 --- a/e2e/tests/evm/error_decoding.go +++ b/e2e/tests/evm/error_decoding.go @@ -1,17 +1,11 @@ //go:build e2e -// +build e2e package evme2e import ( - "context" "math/big" "testing" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms" @@ -20,6 +14,11 @@ import ( "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/sdk/evm/bindings" mcmtypes "github.com/smartcontractkit/mcms/types" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" ) const mcmsABIErrorMsg = "Failed to get MCMS ABI" @@ -35,7 +34,6 @@ func (s *ExecutionTestSuite) TestTimelockExecuteRevertErrorDecoding() { transferMCMSOwnershipToTimelock( s.T(), - ctx, mcmsContract, timelockContract.Address(), s.ChainA.auth, @@ -44,7 +42,6 @@ func (s *ExecutionTestSuite) TestTimelockExecuteRevertErrorDecoding() { acceptMCMSOwnership( s.T(), - ctx, mcmsContract, timelockContract, s.ChainA.auth, @@ -84,7 +81,7 @@ func (s *ExecutionTestSuite) TestTimelockExecuteRevertErrorDecoding() { converters := map[mcmtypes.ChainSelector]sdk.TimelockConverter{ s.ChainA.chainSelector: &evm.TimelockConverter{}, } - proposal, _ := convertTimelockProposal(s.T(), ctx, timelockProposal, converters) + proposal, _ := convertTimelockProposal(s.T(), timelockProposal, converters) tree, err := proposal.MerkleTree() s.Require().NoError(err) @@ -93,7 +90,7 @@ func (s *ExecutionTestSuite) TestTimelockExecuteRevertErrorDecoding() { s.ChainA.chainSelector: evm.NewInspector(s.ClientA), } - _ = signAndValidateProposal(s.T(), ctx, &proposal, inspectors, []string{ + _ = signAndValidateProposal(s.T(), &proposal, inspectors, []string{ s.Settings.PrivateKeys[1], s.Settings.PrivateKeys[2], }) @@ -113,7 +110,6 @@ func (s *ExecutionTestSuite) TestTimelockExecuteRevertErrorDecoding() { setRootAndVerify( s.T(), - ctx, executable, s.ChainA.chainSelector, [32]byte(tree.Root), @@ -182,7 +178,6 @@ func (s *ExecutionTestSuite) TestBypassProposalRevertErrorDecoding() { transferMCMSOwnershipToTimelock( s.T(), - ctx, mcmsContract, timelockContract.Address(), s.ChainA.auth, @@ -191,7 +186,6 @@ func (s *ExecutionTestSuite) TestBypassProposalRevertErrorDecoding() { acceptMCMSOwnership( s.T(), - ctx, mcmsContract, timelockContract, s.ChainA.auth, @@ -229,7 +223,7 @@ func (s *ExecutionTestSuite) TestBypassProposalRevertErrorDecoding() { converters := map[mcmtypes.ChainSelector]sdk.TimelockConverter{ s.ChainA.chainSelector: &evm.TimelockConverter{}, } - proposal, _ := convertTimelockProposal(s.T(), ctx, timelockProposal, converters) + proposal, _ := convertTimelockProposal(s.T(), timelockProposal, converters) tree, err := proposal.MerkleTree() s.Require().NoError(err) @@ -237,7 +231,7 @@ func (s *ExecutionTestSuite) TestBypassProposalRevertErrorDecoding() { inspectors := map[mcmtypes.ChainSelector]sdk.Inspector{ s.ChainA.chainSelector: evm.NewInspector(s.ClientA), } - _ = signAndValidateProposal(s.T(), ctx, &proposal, inspectors, []string{ + _ = signAndValidateProposal(s.T(), &proposal, inspectors, []string{ s.Settings.PrivateKeys[1], // Signer for Group 0 s.Settings.PrivateKeys[2], // Signer for Group 1 }) @@ -257,7 +251,6 @@ func (s *ExecutionTestSuite) TestBypassProposalRevertErrorDecoding() { setRootAndVerify( s.T(), - ctx, executable, s.ChainA.chainSelector, [32]byte(tree.Root), @@ -315,13 +308,13 @@ func (s *ExecutionTestSuite) TestBypassProposalRevertErrorDecoding() { // 2. Accept ownership (must be called by the new owner, i.e., timelock) func transferMCMSOwnershipToTimelock( t *testing.T, - ctx context.Context, mcmsContract *bindings.ManyChainMultiSig, timelockAddr common.Address, currentOwnerAuth *bind.TransactOpts, client *ethclient.Client, ) { t.Helper() + ctx := t.Context() // Step 1: Transfer ownership from current owner to timelock tx, err := mcmsContract.TransferOwnership(currentOwnerAuth, timelockAddr) @@ -336,13 +329,13 @@ func transferMCMSOwnershipToTimelock( // This creates a proposal that calls acceptOwnership() on MCMS and executes it through the timelock. func acceptMCMSOwnership( t *testing.T, - ctx context.Context, mcmsContract *bindings.ManyChainMultiSig, timelockContract *bindings.RBACTimelock, timelockAuth *bind.TransactOpts, client *ethclient.Client, ) { t.Helper() + ctx := t.Context() // Get the acceptOwnership method from MCMS ABI mcmsABI, err := bindings.ManyChainMultiSigMetaData.GetAbi() @@ -476,12 +469,11 @@ func createBypassTimelockProposal( // convertTimelockProposal converts a TimelockProposal to a Proposal using the provided converters. func convertTimelockProposal( t *testing.T, - ctx context.Context, timelockProposal mcms.TimelockProposal, converters map[mcmtypes.ChainSelector]sdk.TimelockConverter, ) (mcms.Proposal, []common.Hash) { t.Helper() - proposal, hashes, err := timelockProposal.Convert(ctx, converters) + proposal, hashes, err := timelockProposal.Convert(t.Context(), converters) require.NoError(t, err) return proposal, hashes @@ -492,12 +484,13 @@ func convertTimelockProposal( // proposal must be a pointer to ensure signatures are added to the same instance used by NewExecutable. func signAndValidateProposal( t *testing.T, - ctx context.Context, proposal *mcms.Proposal, inspectors map[mcmtypes.ChainSelector]sdk.Inspector, signerPrivateKeys []string, ) *mcms.Signable { t.Helper() + ctx := t.Context() + signable, err := mcms.NewSignable(proposal, inspectors) require.NoError(t, err) @@ -521,7 +514,6 @@ func signAndValidateProposal( // setRootAndVerify sets the root on the MCMS contract and verifies it was set correctly. func setRootAndVerify( t *testing.T, - ctx context.Context, executable *mcms.Executable, chainSelector mcmtypes.ChainSelector, expectedRoot [32]byte, @@ -530,6 +522,7 @@ func setRootAndVerify( mcmsContract *bindings.ManyChainMultiSig, ) { t.Helper() + ctx := t.Context() tx, err := executable.SetRoot(ctx, chainSelector) require.NoError(t, err, "SetRoot failed") diff --git a/e2e/tests/evm/executable.go b/e2e/tests/evm/executable.go index adf0fbf46..bfae1beed 100644 --- a/e2e/tests/evm/executable.go +++ b/e2e/tests/evm/executable.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package evme2e @@ -47,7 +46,6 @@ type ExecutionTestSuite struct { ChainA EVMChainMeta ChainB EVMChainMeta signerAddresses []common.Address - deployerKey common.Address e2e.TestSetup } @@ -64,7 +62,6 @@ func (s *ExecutionTestSuite) SetupSuite() { privateKeyHex := s.Settings.PrivateKeys[0] privateKey, err := crypto.HexToECDSA(privateKeyHex[2:]) // Strip "0x" prefix s.Require().NoError(err, "Invalid private key") - s.deployerKey = crypto.PubkeyToAddress(privateKey.PublicKey) // Define signer addresses s.signerAddresses = []common.Address{ diff --git a/e2e/tests/evm/inspection.go b/e2e/tests/evm/inspection.go index 80042d091..92539c0c3 100644 --- a/e2e/tests/evm/inspection.go +++ b/e2e/tests/evm/inspection.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package evme2e @@ -10,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/suite" e2e "github.com/smartcontractkit/mcms/e2e/tests" @@ -23,7 +21,6 @@ import ( type InspectionTestSuite struct { suite.Suite contractAddress string - deployerKey common.Address signerAddresses []common.Address auth *bind.TransactOpts e2e.TestSetup @@ -52,7 +49,6 @@ func (s *InspectionTestSuite) SetupSuite() { s.auth = auth s.contractAddress = s.deployContract() - s.deployerKey = crypto.PubkeyToAddress(privateKey.PublicKey) } // deployContract is a helper to deploy the contract diff --git a/e2e/tests/evm/set_root.go b/e2e/tests/evm/set_root.go index 31c3aa81f..94c98c327 100644 --- a/e2e/tests/evm/set_root.go +++ b/e2e/tests/evm/set_root.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package evme2e @@ -8,27 +7,29 @@ import ( "encoding/json" "math/big" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - cselectors "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/suite" + cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/mcms" e2e "github.com/smartcontractkit/mcms/e2e/tests" testutils "github.com/smartcontractkit/mcms/e2e/utils" "github.com/smartcontractkit/mcms/sdk" + mcmtypes "github.com/smartcontractkit/mcms/types" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/sdk/evm/bindings" - mcmtypes "github.com/smartcontractkit/mcms/types" ) // SetRootTestSuite tests the SetRoot functionality type SetRootTestSuite struct { suite.Suite mcmsContract *bindings.ManyChainMultiSig - deployerKey common.Address signerAddresses []common.Address auth *bind.TransactOpts timelockContract *bindings.RBACTimelock @@ -60,7 +61,6 @@ func (s *SetRootTestSuite) SetupSuite() { s.mcmsContract = s.deployMCMSContract() s.timelockContract = s.deployTimelockContract(s.mcmsContract.Address().String()) - s.deployerKey = crypto.PubkeyToAddress(privateKey.PublicKey) chainDetails, err := cselectors.GetChainDetailsByChainIDAndFamily(s.BlockchainA.Out.ChainID, s.BlockchainA.Out.Family) s.Require().NoError(err) s.chainSelector = mcmtypes.ChainSelector(chainDetails.ChainSelector) diff --git a/e2e/tests/evm/signing.go b/e2e/tests/evm/signing.go index 33891daf7..3d2cb63b2 100644 --- a/e2e/tests/evm/signing.go +++ b/e2e/tests/evm/signing.go @@ -1,105 +1,12 @@ //go:build e2e -// +build e2e package evme2e import ( - "encoding/json" - "io" - "os" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - cselectors "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/suite" - - "github.com/smartcontractkit/mcms" - e2e "github.com/smartcontractkit/mcms/e2e/tests" - testutils "github.com/smartcontractkit/mcms/e2e/utils" - "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/sdk/evm" - mcmtypes "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/mcms/e2e/tests/common" ) // SigningTestSuite tests signing a proposal and converting back to a file type SigningTestSuite struct { - suite.Suite - e2e.TestSetup - - client *ethclient.Client - chainSelector mcmtypes.ChainSelector -} - -// SetupSuite runs before the test suite -func (s *SigningTestSuite) SetupSuite() { - s.TestSetup = *e2e.InitializeSharedTestSetup(s.T()) - - chainDetails, err := cselectors.GetChainDetailsByChainIDAndFamily(s.BlockchainA.Out.ChainID, s.BlockchainA.Out.Family) - s.Require().NoError(err) - s.chainSelector = mcmtypes.ChainSelector(chainDetails.ChainSelector) -} - -func (s *SigningTestSuite) TestReadAndSign() { - file, err := testutils.ReadFixture("proposal-testing.json") - s.Require().NoError(err, "Failed to read fixture") // Check immediately after ReadFixture - defer func(file *os.File) { - if file != nil { - err = file.Close() - s.Require().NoError(err, "Failed to close file") - } - }(file) - s.Require().NoError(err) - proposal, err := mcms.NewProposal(file) - s.Require().NoError(err) - s.Require().NotNil(proposal) - inspectors := map[mcmtypes.ChainSelector]sdk.Inspector{ - s.chainSelector: evm.NewInspector(s.client), - } - signable, err := mcms.NewSignable(proposal, inspectors) - s.Require().NoError(err) - signature, err := signable.SignAndAppend( - mcms.NewPrivateKeySigner(testutils.ParsePrivateKey(s.Settings.PrivateKeys[1])), - ) - s.Require().NoError(err) - expected := mcmtypes.Signature{ - R: common.HexToHash("0x1ed7807767b09344df63797fa4986ce092730813922ce01563062cf51728ac34"), - S: common.HexToHash("0x556721244f77182c1130a5ee8d78ac7067cef52662dbb57b4132c6ec567ecbc8"), - V: 0, - } - s.Require().Equal(expected, signature) - // Write the proposal back to a temp file - tmpFile, err := os.CreateTemp("", "signed-proposal-*.json") - s.Require().NoError(err) - defer func(name string) { - err = os.Remove(name) - s.Require().NoError(err, "Failed to remove temp file") - }(tmpFile.Name()) - err = mcms.WriteProposal(tmpFile, proposal) - s.Require().NoError(err) - - // Read back the written proposal - _, err = tmpFile.Seek(0, io.SeekStart) - s.Require().NoError(err, "Failed to reset file pointer to the start") - - writtenProposal, err := mcms.NewProposal(tmpFile) - s.Require().NoError(err) - - // Validate the appended signature - signedProposalJSON, err := json.Marshal(writtenProposal) - s.Require().NoError(err) - - var parsedProposal map[string]any - err = json.Unmarshal(signedProposalJSON, &parsedProposal) - s.Require().NoError(err) - - // Ensure the signature is present and matches - signatures, ok := parsedProposal["signatures"].([]any) - s.Require().True(ok, "Signatures field is missing or of the wrong type") - s.Require().NotEmpty(signatures, "Signatures field is empty") - - // Verify the appended signature matches the expected value - appendedSignature := signatures[len(signatures)-1].(map[string]any) - s.Require().Equal(expected.R.Hex(), appendedSignature["R"]) - s.Require().Equal(expected.S.Hex(), appendedSignature["S"]) - s.Require().InDelta(expected.V, appendedSignature["V"], 1e-9) + common.SigningTestSuite } diff --git a/e2e/tests/evm/timelock_inspection.go b/e2e/tests/evm/timelock_inspection.go index bd3f06763..a9589293e 100644 --- a/e2e/tests/evm/timelock_inspection.go +++ b/e2e/tests/evm/timelock_inspection.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package evme2e @@ -24,7 +23,6 @@ import ( // TimelockInspectionTestSuite is a suite of tests for the RBACTimelock contract inspection. type TimelockInspectionTestSuite struct { suite.Suite - deployerKey common.Address signerAddresses []common.Address auth *bind.TransactOpts publicKey common.Address @@ -32,7 +30,7 @@ type TimelockInspectionTestSuite struct { e2e.TestSetup } -func (s *TimelockInspectionTestSuite) granRole(role [32]byte, address common.Address) { +func (s *TimelockInspectionTestSuite) grantRole(role [32]byte, address common.Address) { ctx := context.Background() tx, err := s.timelockContract.GrantRole(s.auth, role, address) s.Require().NoError(err) @@ -74,29 +72,28 @@ func (s *TimelockInspectionTestSuite) SetupSuite() { s.publicKey = address s.timelockContract = testutils.DeployTimelockContract(&s.Suite, s.ClientA, s.auth, address.String()) - s.deployerKey = crypto.PubkeyToAddress(privateKey.PublicKey) // Grant Some Roles for testing // Proposers role, err := s.timelockContract.PROPOSERROLE(&bind.CallOpts{}) s.Require().NoError(err) - s.granRole(role, s.signerAddresses[0]) + s.grantRole(role, s.signerAddresses[0]) // Executors role, err = s.timelockContract.EXECUTORROLE(&bind.CallOpts{}) s.Require().NoError(err) - s.granRole(role, s.signerAddresses[0]) - s.granRole(role, s.signerAddresses[1]) + s.grantRole(role, s.signerAddresses[0]) + s.grantRole(role, s.signerAddresses[1]) // By passers role, err = s.timelockContract.BYPASSERROLE(&bind.CallOpts{}) s.Require().NoError(err) - s.granRole(role, s.signerAddresses[1]) + s.grantRole(role, s.signerAddresses[1]) // Cancellers role, err = s.timelockContract.CANCELLERROLE(&bind.CallOpts{}) s.Require().NoError(err) - s.granRole(role, s.signerAddresses[0]) - s.granRole(role, s.signerAddresses[1]) + s.grantRole(role, s.signerAddresses[0]) + s.grantRole(role, s.signerAddresses[1]) } // TestGetProposers gets the list of proposers diff --git a/e2e/tests/runner_test.go b/e2e/tests/runner_test.go index 499dedbe9..caaae0074 100644 --- a/e2e/tests/runner_test.go +++ b/e2e/tests/runner_test.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package e2e_test @@ -24,11 +23,11 @@ func TestEVMSuite(t *testing.T) { //go:generate ./solana/compile-mcm-contracts.sh func TestSolanaSuite(t *testing.T) { - suite.Run(t, new(solanae2e.SolanaTestSuite)) + suite.Run(t, new(solanae2e.TestSuite)) } func TestAptosSuite(t *testing.T) { - suite.Run(t, new(aptose2e.AptosTestSuite)) + suite.Run(t, new(aptose2e.TestSuite)) } func TestSuiSuite(t *testing.T) { diff --git a/e2e/tests/setup.go b/e2e/tests/setup.go index 1659efa45..6deec0774 100644 --- a/e2e/tests/setup.go +++ b/e2e/tests/setup.go @@ -164,13 +164,13 @@ func InitializeSharedTestSetup(t *testing.T) *TestSetup { aptosBlockchainOutput, err = blockchain.NewBlockchainNetwork(in.AptosChain) require.NoError(t, err, "Failed to initialize Aptos blockchain") - nodeUrl := fmt.Sprintf("%v/v1", aptosBlockchainOutput.Nodes[0].ExternalHTTPUrl) + nodeURL := fmt.Sprintf("%v/v1", aptosBlockchainOutput.Nodes[0].ExternalHTTPUrl) - aptosClient, err = aptos.NewNodeClient(nodeUrl, 0) + aptosClient, err = aptos.NewNodeClient(nodeURL, 0) require.NoError(t, err, "Failed to initialize Aptos RPC client") // Test liveness, will also fetch ChainID - t.Logf("Initialized Aptos RPC client @ %s", nodeUrl) + t.Logf("Initialized Aptos RPC client @ %s", nodeURL) nodeInfo, infoErr := aptosClient.Info() require.NoError(t, infoErr, "Failed to get Aptos node info") require.NotEmpty(t, nodeInfo.LedgerVersionStr) @@ -196,11 +196,11 @@ func InitializeSharedTestSetup(t *testing.T) *TestSetup { suiBlockchainOutput, err = blockchain.NewBlockchainNetwork(in.SuiChain) require.NoError(t, err, "Failed to initialize Sui blockchain") - nodeUrl := suiBlockchainOutput.Nodes[0].ExternalHTTPUrl - suiClient = sui.NewSuiClient(nodeUrl) + nodeURL := suiBlockchainOutput.Nodes[0].ExternalHTTPUrl + suiClient = sui.NewSuiClient(nodeURL) // Test liveness, will also fetch ChainID - t.Logf("Initialized Sui RPC client @ %s", nodeUrl) + t.Logf("Initialized Sui RPC client @ %s", nodeURL) } sharedSetup = &TestSetup{ diff --git a/e2e/tests/solana/chunking.go b/e2e/tests/solana/chunking.go index e95d2fd03..407335fb5 100644 --- a/e2e/tests/solana/chunking.go +++ b/e2e/tests/solana/chunking.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package solanae2e @@ -11,17 +10,17 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/gagliardetto/solana-go" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" "github.com/smartcontractkit/mcms" + e2eutils "github.com/smartcontractkit/mcms/e2e/utils/solana" "github.com/smartcontractkit/mcms/sdk" mcmsSolana "github.com/smartcontractkit/mcms/sdk/solana" "github.com/smartcontractkit/mcms/types" - e2eutils "github.com/smartcontractkit/mcms/e2e/utils/solana" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" ) -func (s *SolanaTestSuite) Test_Solana_Chunk_LargeInstructions() { +func (s *TestSuite) TestChunkLargeInstructions() { s.T().Setenv("MCMS_SOLANA_MAX_RETRIES", "20") mcmPDASeed := [32]byte([]byte("hEjRE08jHA2ilqk12fgjE9OIjRJRd7m8"[:])) @@ -41,7 +40,7 @@ func (s *SolanaTestSuite) Test_Solana_Chunk_LargeInstructions() { s.Require().NoError(err) accounts := []solana.PublicKey{auth.PublicKey(), mcmSignerPDA, timelockSignerPDA} - e2eutils.FundAccounts(s.T(), ctx, accounts, 1, s.SolanaClient) + e2eutils.FundAccounts(s.T(), accounts, 1, s.SolanaClient) s.AssignRoleToAccounts(ctx, timelockPDASeed, auth, []solana.PublicKey{mcmSignerPDA}, timelock.Proposer_Role) s.AssignRoleToAccounts(ctx, timelockPDASeed, auth, []solana.PublicKey{mcmSignerPDA}, timelock.Executor_Role) diff --git a/e2e/tests/solana/common.go b/e2e/tests/solana/common.go index 33e889d2d..9814f9ea2 100644 --- a/e2e/tests/solana/common.go +++ b/e2e/tests/solana/common.go @@ -1,25 +1,32 @@ //go:build e2e -// +build e2e package solanae2e import ( + "bytes" "context" "crypto/ecdsa" "fmt" "slices" - "strings" "testing" "time" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + + cselectors "github.com/smartcontractkit/chain-selectors" + + "go.uber.org/zap" + evmCommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" + bin "github.com/gagliardetto/binary" "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/programs/system" "github.com/gagliardetto/solana-go/rpc" - cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/testutils" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/access_controller" cpistub "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/external_program_cpi_stub" @@ -28,9 +35,6 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/accesscontroller" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" timelockutils "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/timelock" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "go.uber.org/zap" e2e "github.com/smartcontractkit/mcms/e2e/tests" solanasdk "github.com/smartcontractkit/mcms/sdk/solana" @@ -83,7 +87,7 @@ func generateTestEVMAccounts(t *testing.T, numAccounts int) []EVMTestAccount { } slices.SortFunc(testAccounts, func(a, b EVMTestAccount) int { - return strings.Compare(strings.ToLower(a.HexAddress), strings.ToLower(b.HexAddress)) + return bytes.Compare(a.Address[:], b.Address[:]) }) return testAccounts @@ -97,8 +101,8 @@ type RoleAccounts struct { AccessController solana.PrivateKey } -// SolanaTestSuite is the base test suite for all solana e2e tests -type SolanaTestSuite struct { +// TestSuite is the base test suite for all solana e2e tests +type TestSuite struct { suite.Suite e2e.TestSetup @@ -111,7 +115,7 @@ type SolanaTestSuite struct { } // SetupSuite runs before the test suite -func (s *SolanaTestSuite) SetupSuite() { +func (s *TestSuite) SetupSuite() { s.TestSetup = *e2e.InitializeSharedTestSetup(s.T()) s.MCMProgramID = solana.MustPublicKeyFromBase58(s.SolanaChain.SolanaPrograms["mcm"]) s.TimelockProgramID = solana.MustPublicKeyFromBase58(s.SolanaChain.SolanaPrograms["timelock"]) @@ -123,7 +127,7 @@ func (s *SolanaTestSuite) SetupSuite() { s.ChainSelector = types.ChainSelector(details.ChainSelector) } -func (s *SolanaTestSuite) SetupTest() { +func (s *TestSuite) SetupTest() { // reset all programID to a random key // this ensures all methods in the sdk correctly sets the programID itself // and not rely on the global programID to be set by something else @@ -192,14 +196,14 @@ func InitializeMCMProgram(ctx context.Context, t *testing.T, solanaClient *rpc.C require.Equal(t, chainSelector, configAccount.ChainId) require.Equal(t, wallet.PublicKey(), configAccount.Owner) } -func (s *SolanaTestSuite) SetupMCM(pdaSeed [32]byte) { +func (s *TestSuite) SetupMCM(pdaSeed [32]byte) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) s.T().Cleanup(cancel) InitializeMCMProgram(ctx, s.T(), s.SolanaClient, s.MCMProgramID, pdaSeed, uint64(s.ChainSelector)) } -func (s *SolanaTestSuite) SetupTimelock(pdaSeed [32]byte, minDelay time.Duration) { +func (s *TestSuite) SetupTimelock(pdaSeed [32]byte, minDelay time.Duration) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) s.T().Cleanup(cancel) @@ -299,7 +303,7 @@ func (s *SolanaTestSuite) SetupTimelock(pdaSeed [32]byte, minDelay time.Duration }) } -func (s *SolanaTestSuite) AssignRoleToAccounts( +func (s *TestSuite) AssignRoleToAccounts( ctx context.Context, pdaSeed solanasdk.PDASeed, auth solana.PrivateKey, accounts []solana.PublicKey, role timelock.Role, ) { @@ -308,7 +312,7 @@ func (s *SolanaTestSuite) AssignRoleToAccounts( testutils.SendAndConfirm(ctx, s.T(), s.SolanaClient, instructions, auth, rpc.CommitmentConfirmed) } -func (s *SolanaTestSuite) SetupCPIStub(pdaSeed solanasdk.PDASeed) { +func (s *TestSuite) SetupCPIStub(pdaSeed solanasdk.PDASeed) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) s.T().Cleanup(cancel) @@ -328,7 +332,7 @@ func (s *SolanaTestSuite) SetupCPIStub(pdaSeed solanasdk.PDASeed) { rpc.CommitmentConfirmed) } -func (s *SolanaTestSuite) getInitAccessControllersIxs(ctx context.Context, roleAcAccount solana.PublicKey, authority solana.PrivateKey) []solana.Instruction { +func (s *TestSuite) getInitAccessControllersIxs(ctx context.Context, roleAcAccount solana.PublicKey, authority solana.PrivateKey) []solana.Instruction { ixs := []solana.Instruction{} dataSize := uint64(8 + 32 + 32 + ((32 * 64) + 8)) // discriminator + owner + proposed owner + access_list (64 max addresses + length) @@ -348,7 +352,7 @@ func (s *SolanaTestSuite) getInitAccessControllersIxs(ctx context.Context, roleA return ixs } -func (s *SolanaTestSuite) getBatchAddAccessIxs( +func (s *TestSuite) getBatchAddAccessIxs( ctx context.Context, timelockID [32]byte, roleAcAccount solana.PublicKey, role timelock.Role, addresses []solana.PublicKey, authority solana.PrivateKey, chunkSize int, ) []solana.Instruction { @@ -386,13 +390,13 @@ func (s *SolanaTestSuite) getBatchAddAccessIxs( return ixs } -func (s *SolanaTestSuite) initOperation(ctx context.Context, op timelockutils.Operation, timelockID [32]byte, auth solana.PrivateKey) { +func (s *TestSuite) initOperation(ctx context.Context, op timelockutils.Operation, timelockID [32]byte, auth solana.PrivateKey) { ixs := s.getInitOperationIxs(timelockID, op, auth.PublicKey()) tx := testutils.SendAndConfirm(ctx, s.T(), s.SolanaClient, ixs, auth, rpc.CommitmentConfirmed) s.Require().NotNil(tx) } -func (s *SolanaTestSuite) getInitOperationIxs(timelockID [32]byte, op timelockutils.Operation, authority solana.PublicKey) []solana.Instruction { +func (s *TestSuite) getInitOperationIxs(timelockID [32]byte, op timelockutils.Operation, authority solana.PublicKey) []solana.Instruction { configPDA, err := solanasdk.FindTimelockConfigPDA(s.TimelockProgramID, timelockID) s.Require().NoError(err) operationPDA, err := solanasdk.FindTimelockOperationPDA(s.TimelockProgramID, timelockID, op.OperationID()) @@ -455,6 +459,7 @@ func (s *SolanaTestSuite) getInitOperationIxs(timelockID [32]byte, op timelockut appendIx, err := timelock.NewAppendInstructionDataInstruction( timelockID, op.OperationID(), + uint32(i), // which instruction index we are chunking chunk, // partial data operationPDA, @@ -484,7 +489,7 @@ func (s *SolanaTestSuite) getInitOperationIxs(timelockID [32]byte, op timelockut return ixs } -func (s *SolanaTestSuite) scheduleOperation(ctx context.Context, timelockID [32]byte, delay time.Duration, opID [32]byte) { +func (s *TestSuite) scheduleOperation(ctx context.Context, timelockID [32]byte, delay time.Duration, opID [32]byte) { operationPDA, err := solanasdk.FindTimelockOperationPDA(s.TimelockProgramID, timelockID, opID) s.Require().NoError(err) @@ -509,7 +514,7 @@ func (s *SolanaTestSuite) scheduleOperation(ctx context.Context, timelockID [32] s.Require().NotNil(tx) } -func (s *SolanaTestSuite) executeOperation(ctx context.Context, timelockID [32]byte, opID [32]byte) { +func (s *TestSuite) executeOperation(ctx context.Context, timelockID [32]byte, opID [32]byte) { operationPDA, err := solanasdk.FindTimelockOperationPDA(s.TimelockProgramID, timelockID, opID) s.Require().NoError(err) @@ -540,7 +545,7 @@ func (s *SolanaTestSuite) executeOperation(ctx context.Context, timelockID [32]b s.Require().NotNil(tx) } -func (s *SolanaTestSuite) waitForOperationToBeReady(ctx context.Context, timelockID [32]byte, opID [32]byte) { +func (s *TestSuite) waitForOperationToBeReady(ctx context.Context, timelockID [32]byte, opID [32]byte) { const maxAttempts = 20 const pollInterval = 500 * time.Millisecond const timeBuffer = 2 * time.Second @@ -575,6 +580,6 @@ func (s *SolanaTestSuite) waitForOperationToBeReady(ctx context.Context, timeloc s.Require().Fail(fmt.Sprintf("Operation %s is not ready after %d attempts", opID, maxAttempts)) } -func (s *SolanaTestSuite) contextWithLogger() context.Context { +func (s *TestSuite) contextWithLogger() context.Context { return context.WithValue(context.Background(), solanasdk.ContextLoggerValue, zap.NewNop().Sugar()) } diff --git a/e2e/tests/solana/execute.go b/e2e/tests/solana/execute.go index d3a64d4ff..fb44ae614 100644 --- a/e2e/tests/solana/execute.go +++ b/e2e/tests/solana/execute.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package solanae2e @@ -10,27 +9,29 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/sdk" + mcmsSolana "github.com/smartcontractkit/mcms/sdk/solana" + "github.com/smartcontractkit/mcms/types" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/programs/system" "github.com/gagliardetto/solana-go/programs/token" "github.com/gagliardetto/solana-go/rpc" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/config" "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/testutils" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" solanaCommon "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens" - - "github.com/smartcontractkit/mcms" - "github.com/smartcontractkit/mcms/sdk" - mcmsSolana "github.com/smartcontractkit/mcms/sdk/solana" - "github.com/smartcontractkit/mcms/types" ) var testPDASeedExec = [32]byte{'t', 'e', 's', 't', '-', 'e', 'x', 'e', 'c'} -// Test_Solana_Execute tests the Execute functionality by creating a mint tokens transaction and +// TestExecute tests the Execute functionality by creating a mint tokens transaction and // executing it via the MCMS program. -func (s *SolanaTestSuite) Test_Solana_Execute() { +func (s *TestSuite) TestExecute() { ctx := context.Background() s.SetupMCM(testPDASeedExec) @@ -164,12 +165,12 @@ func (s *SolanaTestSuite) Test_Solana_Execute() { s.Require().NoError(err) // final balance should be 1000000000000 more units - s.Require().Equal(initialBalance.Value.Amount, "0") - s.Require().Equal(finalBalance.Value.Amount, "1000000000000") + s.Require().Equal("0", initialBalance.Value.Amount) + s.Require().Equal("1000000000000", finalBalance.Value.Amount) } // buildMintTx builds a mint transaction for the proposal -func (s *SolanaTestSuite) buildMintTx(mint, receiverATA, signerPDA solana.PublicKey) types.Transaction { +func (s *TestSuite) buildMintTx(mint, receiverATA, signerPDA solana.PublicKey) types.Transaction { amount := 1000 * solana.LAMPORTS_PER_SOL ix2, err := token.NewMintToInstruction(amount, mint, receiverATA, signerPDA, nil).ValidateAndBuild() accounts := ix2.Accounts() @@ -198,7 +199,7 @@ func (s *SolanaTestSuite) buildMintTx(mint, receiverATA, signerPDA solana.Public } // setupTokenProgram sets up a token program with a mint and an associated token account for the receiver -func (s *SolanaTestSuite) setupTokenProgram(ctx context.Context, auth solana.PrivateKey, signerPDA solana.PublicKey, mint solana.PrivateKey) (receiverATA solana.PublicKey) { +func (s *TestSuite) setupTokenProgram(ctx context.Context, auth solana.PrivateKey, signerPDA solana.PublicKey, mint solana.PrivateKey) (receiverATA solana.PublicKey) { tokenProgram := solana.Token2022ProgramID // Use CreateToken utility to get initialization instructions createTokenIxs, err := tokens.CreateToken( @@ -220,7 +221,7 @@ func (s *SolanaTestSuite) setupTokenProgram(ctx context.Context, auth solana.Pri s.Require().NoError(err) ix1, receiverATA, err := tokens.CreateAssociatedTokenAccount(tokenProgram, mint.PublicKey(), receiver.PublicKey(), auth.PublicKey()) s.Require().NoError(err) - s.Require().NotEqual(receiverATA.String(), "") + s.Require().NotEmpty(receiverATA.String()) testutils.SendAndConfirm(ctx, s.T(), s.SolanaClient, []solana.Instruction{ix1}, auth, config.DefaultCommitment, solanaCommon.AddSigners(mint)) return receiverATA diff --git a/e2e/tests/solana/inspection.go b/e2e/tests/solana/inspection.go index d062d5990..9b22a95f4 100644 --- a/e2e/tests/solana/inspection.go +++ b/e2e/tests/solana/inspection.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package solanae2e @@ -16,7 +15,7 @@ var testPDASeedGetRoot = [32]byte{'t', 'e', 's', 't', '-', 'g', 'e', 't', 'r', ' var testPDASeedGetRootMeta = [32]byte{'t', 'e', 's', 't', '-', 'g', 'e', 't', 'm', 'e', 't', 'a'} // TestGetOpCount tests the GetOpCount functionality -func (s *SolanaTestSuite) TestGetOpCount() { +func (s *TestSuite) TestGetOpCount() { ctx := context.Background() s.SetupMCM(testPDASeedGetOpCount) @@ -28,7 +27,7 @@ func (s *SolanaTestSuite) TestGetOpCount() { } // TestGetRoot tests the GetRoot functionality -func (s *SolanaTestSuite) TestGetRoot() { +func (s *TestSuite) TestGetRoot() { ctx := context.Background() s.SetupMCM(testPDASeedGetRoot) @@ -41,7 +40,7 @@ func (s *SolanaTestSuite) TestGetRoot() { } // TestGetRootMetadata tests the GetRootMetadata functionality -func (s *SolanaTestSuite) TestGetRootMetadata() { +func (s *TestSuite) TestGetRootMetadata() { ctx := context.Background() s.SetupMCM(testPDASeedGetRootMeta) diff --git a/e2e/tests/solana/set_config.go b/e2e/tests/solana/set_config.go index 0a0fa9bc0..431003356 100644 --- a/e2e/tests/solana/set_config.go +++ b/e2e/tests/solana/set_config.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package solanae2e @@ -7,10 +6,11 @@ import ( "context" "github.com/ethereum/go-ethereum/common" - "github.com/gagliardetto/solana-go" + "github.com/google/go-cmp/cmp" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" - "github.com/google/go-cmp/cmp" + solanaCommon "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" mcmsSolana "github.com/smartcontractkit/mcms/sdk/solana" @@ -19,8 +19,8 @@ import ( var testPDASeedSetConfigTest = [32]byte{'t', 'e', 's', 't', '-', 's', 'e', 't', 'c', 'o', 'n', 'f'} -// Test_Solana_SetConfig tests the SetConfig functionality by setting a config on the MCM program -func (s *SolanaTestSuite) Test_Solana_SetConfig() { +// TestSetConfig tests the SetConfig functionality by setting a config on the MCM program +func (s *TestSuite) TestSetConfig() { // --- arrange --- ctx := context.Background() s.SetupMCM(testPDASeedSetConfigTest) @@ -102,7 +102,7 @@ func (s *SolanaTestSuite) Test_Solana_SetConfig() { s.Require().NoError(err) // --- assert --- - s.Require().Empty(err, result.Hash) + s.Require().Empty(result.Hash) gotConfig, err := mcmsSolana.NewInspector(s.SolanaClient).GetConfig(ctx, mcmAddress) s.Require().NoError(err) diff --git a/e2e/tests/solana/set_root.go b/e2e/tests/solana/set_root.go index 4a1b5ddea..5586faf2d 100644 --- a/e2e/tests/solana/set_root.go +++ b/e2e/tests/solana/set_root.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package solanae2e @@ -10,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/gagliardetto/solana-go" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" "github.com/smartcontractkit/mcms" @@ -20,9 +20,9 @@ import ( var testPDASeedSetRootTest = [32]byte{'t', 'e', 's', 't', '-', 's', 'e', 't', 'r', 'o', 'o', 't'} -// Test_Solana_SetRoot tests the SetRoot functionality by setting a root on the MCM program +// TestSetRoot tests the SetRoot functionality by setting a root on the MCM program // and doing the preload signers setup. -func (s *SolanaTestSuite) Test_Solana_SetRoot() { +func (s *TestSuite) TestSetRoot() { // --- arrange --- ctx := s.contextWithLogger() @@ -118,6 +118,7 @@ func (s *SolanaTestSuite) Test_Solana_SetRoot() { signers = append(signers, signer.Address) mcmsSigners = append(mcmsSigners, mcms.NewPrivateKeySigner(signer.PrivateKey)) } + multiSignersMcmConfig := types.Config{Quorum: uint8(len(signers)), Signers: signers} proposal = buildProposal() diff --git a/e2e/tests/solana/simulator.go b/e2e/tests/solana/simulator.go index ef8a8f26d..d1cff212d 100644 --- a/e2e/tests/solana/simulator.go +++ b/e2e/tests/solana/simulator.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package solanae2e @@ -10,8 +9,10 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/programs/system" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" "github.com/smartcontractkit/mcms" @@ -22,7 +23,7 @@ import ( var testPDASeedSetRootSimulateTest = [32]byte{'t', 'e', 's', 't', '-', 's', 'e', 't', 'r', 'o', 'o', 't', '-', 's', 'i', 'm', 'u', 'l', 'a', 't', 'e'} -func (s *SolanaTestSuite) TestSimulator_SimulateSetRoot() { +func (s *TestSuite) TestSimulatorSimulateSetRoot() { s.SetupMCM(testPDASeedSetRootSimulateTest) ctx := context.Background() @@ -34,7 +35,7 @@ func (s *SolanaTestSuite) TestSimulator_SimulateSetRoot() { auth, err := solana.PrivateKeyFromBase58(privateKey) s.Require().NoError(err) - validUntil := time.Now().Add(10 * time.Hour).Unix() + validUntil := uint32(time.Now().Add(10 * time.Hour).Unix()) solanaTx, err := solanasdk.NewTransaction( auth.PublicKey().String(), []byte("test data"), @@ -54,7 +55,7 @@ func (s *SolanaTestSuite) TestSimulator_SimulateSetRoot() { s.Require().NoError(err) proposal, err := mcms.NewProposalBuilder(). SetVersion("v1"). - SetValidUntil(uint32(validUntil)). + SetValidUntil(validUntil). SetDescription("proposal to test SetRoot"). SetOverridePreviousRoot(true). AddChainMetadata(s.ChainSelector, metadata). @@ -119,7 +120,7 @@ func (s *SolanaTestSuite) TestSimulator_SimulateSetRoot() { s.Require().NoError(err) } -func (s *SolanaTestSuite) TestSimulator_SimulateOperation() { +func (s *TestSuite) TestSimulatorSimulateOperation() { ctx := context.Background() recipientAddress, err := solana.NewRandomPrivateKey() diff --git a/e2e/tests/solana/timelock_converter.go b/e2e/tests/solana/timelock_converter.go index 827d2a0d1..366188e26 100644 --- a/e2e/tests/solana/timelock_converter.go +++ b/e2e/tests/solana/timelock_converter.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package solanae2e @@ -13,14 +12,17 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" + "github.com/google/go-cmp/cmp" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" - "github.com/google/go-cmp/cmp" + cpistub "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/external_program_cpi_stub" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" solanaCommon "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms" e2eutils "github.com/smartcontractkit/mcms/e2e/utils/solana" @@ -31,7 +33,7 @@ import ( var testPDASeedTimelockConverter = [32]byte{'t', 'e', 's', 't', '-', 't', 'i', 'm', 'e', 'l', 'o', 'c', 'k', 'c', 'o', 'n', 'v', 'e', 'r', 't', 'e', 'r'} -func (s *SolanaTestSuite) Test_TimelockConverter() { +func (s *TestSuite) TestTimelockConverter() { // --- arrange --- ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) s.T().Cleanup(cancel) @@ -53,9 +55,9 @@ func (s *SolanaTestSuite) Test_TimelockConverter() { timelockSignerPDA, err := solanasdk.FindTimelockSignerPDA(s.TimelockProgramID, testPDASeedTimelockConverter) s.Require().NoError(err) - e2eutils.FundAccounts(s.T(), ctx, []solana.PublicKey{mcmSignerPDA, timelockSignerPDA}, 1, s.SolanaClient) + e2eutils.FundAccounts(s.T(), []solana.PublicKey{mcmSignerPDA, timelockSignerPDA}, 1, s.SolanaClient) - validUntil := 2051222400 // 2035-01-01T12:00:00 UTC + validUntil := uint32(2051222400) // 2035-01-01T12:00:00 UTC mcmAddress := solanasdk.ContractAddress(s.MCMProgramID, testPDASeedTimelockConverter) timelockAddress := solanasdk.ContractAddress(s.TimelockProgramID, testPDASeedTimelockConverter) converters := map[types.ChainSelector]sdk.TimelockConverter{ @@ -112,7 +114,7 @@ func (s *SolanaTestSuite) Test_TimelockConverter() { } timelockProposalBuilder := func() *mcms.TimelockProposalBuilder { return mcms.NewTimelockProposalBuilder(). - SetValidUntil(uint32(validUntil)). + SetValidUntil(validUntil). SetDescription("proposal to test the timelock proposal converter"). SetOverridePreviousRoot(true). SetVersion("v1"). @@ -140,7 +142,7 @@ func (s *SolanaTestSuite) Test_TimelockConverter() { // build expected output Proposal wantProposal, err := mcms.NewProposalBuilder(). - SetValidUntil(uint32(validUntil)). + SetValidUntil(validUntil). SetDescription("proposal to test the timelock proposal converter"). SetOverridePreviousRoot(true). SetVersion("v1"). @@ -329,7 +331,7 @@ func (s *SolanaTestSuite) Test_TimelockConverter() { s.Require().NoError(err) // --- assert --- - s.Require().Equal([]common.Hash{mcms.ZERO_HASH, operation1ID}, gotPredecessors) + s.Require().Equal([]common.Hash{mcms.ZeroHash, operation1ID}, gotPredecessors) s.Require().Empty(cmp.Diff(toJSONString(s.T(), wantProposal), toJSONString(s.T(), &gotProposal))) // --- act --- @@ -355,7 +357,7 @@ func (s *SolanaTestSuite) Test_TimelockConverter() { // build expected output Proposal wantProposal, err := mcms.NewProposalBuilder(). - SetValidUntil(uint32(validUntil)). + SetValidUntil(validUntil). SetDescription("proposal to test the timelock proposal converter"). SetOverridePreviousRoot(true). SetVersion("v1"). @@ -396,7 +398,7 @@ func (s *SolanaTestSuite) Test_TimelockConverter() { s.Require().NoError(err) // --- assert --- - s.Require().Equal([]common.Hash{mcms.ZERO_HASH, operation1ID}, gotPredecessors) + s.Require().Equal([]common.Hash{mcms.ZeroHash, operation1ID}, gotPredecessors) s.Require().Empty(cmp.Diff(toJSONString(s.T(), wantProposal), toJSONString(s.T(), &gotProposal))) }) @@ -419,7 +421,7 @@ func (s *SolanaTestSuite) Test_TimelockConverter() { // build expected output Proposal wantProposal, err := mcms.NewProposalBuilder(). - SetValidUntil(uint32(validUntil)). + SetValidUntil(validUntil). SetDescription("proposal to test the timelock proposal converter"). SetOverridePreviousRoot(true). SetVersion("v1"). @@ -615,7 +617,7 @@ func (s *SolanaTestSuite) Test_TimelockConverter() { s.Require().NoError(err) // --- assert --- - s.Require().Equal([]common.Hash{mcms.ZERO_HASH, bypassOperation1ID}, gotPredecessors) + s.Require().Equal([]common.Hash{mcms.ZeroHash, bypassOperation1ID}, gotPredecessors) s.Require().Empty(cmp.Diff(toJSONString(s.T(), wantProposal), toJSONString(s.T(), &gotProposal))) // --- act: executed converted proposal --- @@ -629,7 +631,7 @@ func (s *SolanaTestSuite) Test_TimelockConverter() { }) } -func (s *SolanaTestSuite) executeConvertedProposal( +func (s *TestSuite) executeConvertedProposal( ctx context.Context, wallet solana.PrivateKey, gotProposal mcms.Proposal, mcmAddress string, ) { // set config @@ -664,7 +666,7 @@ func (s *SolanaTestSuite) executeConvertedProposal( } } -func (s *SolanaTestSuite) executeTimelockProposal( +func (s *TestSuite) executeTimelockProposal( ctx context.Context, wallet solana.PrivateKey, timelockProposal *mcms.TimelockProposal, ) { timelockExecutors := map[types.ChainSelector]sdk.TimelockExecutor{ @@ -675,12 +677,12 @@ func (s *SolanaTestSuite) executeTimelockProposal( tx, err := timelockExecutable.Execute(ctx, 0) s.Require().NoError(err) - s.Require().Contains(getTransactionLogs(s.T(), ctx, s.SolanaClient, tx.Hash), "Called `empty`") - s.Require().Contains(getTransactionLogs(s.T(), ctx, s.SolanaClient, tx.Hash), "Called `u8_instruction_data`") + s.Require().Contains(getTransactionLogs(ctx, s.T(), s.SolanaClient, tx.Hash), "Called `empty`") + s.Require().Contains(getTransactionLogs(ctx, s.T(), s.SolanaClient, tx.Hash), "Called `u8_instruction_data`") tx, err = timelockExecutable.Execute(ctx, 1) s.Require().NoError(err) - s.Require().Contains(getTransactionLogs(s.T(), ctx, s.SolanaClient, tx.Hash), "Called `account_mut`") + s.Require().Contains(getTransactionLogs(ctx, s.T(), s.SolanaClient, tx.Hash), "Called `account_mut`") } func marshalAdditionalFields(t *testing.T, additionalFields solanasdk.AdditionalFields) []byte { @@ -710,7 +712,7 @@ func toJSONString(t *testing.T, proposal *mcms.Proposal) string { return buffer.String() } -func getTransactionLogs(t *testing.T, ctx context.Context, client *rpc.Client, signature string) string { +func getTransactionLogs(ctx context.Context, t *testing.T, client *rpc.Client, signature string) string { t.Helper() opts := &rpc.GetTransactionOpts{Commitment: rpc.CommitmentConfirmed} diff --git a/e2e/tests/solana/timelock_execution.go b/e2e/tests/solana/timelock_execution.go index 7254696ec..6530ee4ff 100644 --- a/e2e/tests/solana/timelock_execution.go +++ b/e2e/tests/solana/timelock_execution.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package solanae2e @@ -8,12 +7,13 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/programs/token" "github.com/gagliardetto/solana-go/rpc" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/testutils" - "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/testutils" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" e2eutils "github.com/smartcontractkit/mcms/e2e/utils" @@ -26,9 +26,9 @@ var testTimelockExecuteID = [32]byte{'t', 'e', 's', 't', '-', 'e', 'x', 'e', 'c' const BatchAddAccessChunkSize = 24 -// Test_Solana_TimelockExecute tests the timelock Execute functionality by scheduling a mint tokens transaction and +// TestTimelockExecute tests the timelock Execute functionality by scheduling a mint tokens transaction and // executing it via the timelock ExecuteBatch -func (s *SolanaTestSuite) Test_Solana_TimelockExecute() { +func (s *TestSuite) TestTimelockExecute() { // --- arrange --- ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) s.T().Cleanup(cancel) @@ -48,7 +48,7 @@ func (s *SolanaTestSuite) Test_Solana_TimelockExecute() { s.Require().NoError(err) accountsToFund := []solana.PublicKey{auth.PublicKey(), proposerKey.PublicKey(), executorKey.PublicKey()} - e2esolanautils.FundAccounts(s.T(), ctx, accountsToFund, 1, s.SolanaClient) + e2esolanautils.FundAccounts(s.T(), accountsToFund, 1, s.SolanaClient) s.AssignRoleToAccounts(ctx, testTimelockExecuteID, auth, getPublicKeys(proposers), timelock.Proposer_Role) s.AssignRoleToAccounts(ctx, testTimelockExecuteID, auth, getPublicKeys(executors), timelock.Executor_Role) @@ -88,7 +88,7 @@ func (s *SolanaTestSuite) Test_Solana_TimelockExecute() { } // scheduleMintTx schedules a MintTx on the timelock -func (s *SolanaTestSuite) scheduleMintTx( +func (s *TestSuite) scheduleMintTx( ctx context.Context, mint, receiverATA, // The account that will receive the mint funds. @@ -179,6 +179,7 @@ func (s *SolanaTestSuite) scheduleMintTx( appendIx, appendErr := timelock.NewAppendInstructionDataInstruction( testTimelockExecuteID, operationID, + uint32(i), // which instruction index we are chunking chunk, // partial data operationPDA, diff --git a/e2e/tests/solana/timelock_inspection.go b/e2e/tests/solana/timelock_inspection.go index 975a6f716..dfbd9dc76 100644 --- a/e2e/tests/solana/timelock_inspection.go +++ b/e2e/tests/solana/timelock_inspection.go @@ -1,5 +1,4 @@ //go:build e2e -// +build e2e package solanae2e @@ -8,6 +7,7 @@ import ( "time" "github.com/gagliardetto/solana-go" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" timelockutils "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/timelock" @@ -24,7 +24,7 @@ var testPDASeedTimelockIsOperationsReady = [32]byte{'t', 'e', 's', 't', '-', 't' var testPDASeedTimelockIsOperationsDone = [32]byte{'t', 'e', 's', 't', '-', 't', 'i', 'm', 'e', 'o', 'p', 's', 'd', 'o', 'n', 'e'} var testPDASeedTimelockMinDelay = [32]byte{'t', 'e', 's', 't', '-', 't', 'i', 'm', 'e', 'm', 'i', 'n', 'd', 'e', 'l', 'a', 'y'} -func (s *SolanaTestSuite) TestGetProposers() { +func (s *TestSuite) TestGetProposers() { s.SetupTimelock(testPDASeedTimelockGetProposers, 1*time.Second) ctx := context.Background() @@ -40,7 +40,7 @@ func (s *SolanaTestSuite) TestGetProposers() { s.Require().ElementsMatch(expected, proposers, "Proposers don't match") } -func (s *SolanaTestSuite) TestGetExecutors() { +func (s *TestSuite) TestGetExecutors() { s.SetupTimelock(testPDASeedTimelockGetExecutors, 1*time.Second) ctx := context.Background() @@ -56,7 +56,7 @@ func (s *SolanaTestSuite) TestGetExecutors() { s.Require().ElementsMatch(expected, executors, "Executors don't match") } -func (s *SolanaTestSuite) TestGetCancellers() { +func (s *TestSuite) TestGetCancellers() { s.SetupTimelock(testPDASeedTimelockGetCancellers, 1*time.Second) ctx := context.Background() @@ -72,7 +72,7 @@ func (s *SolanaTestSuite) TestGetCancellers() { s.Require().ElementsMatch(expected, cancellers, "Cancellers don't match") } -func (s *SolanaTestSuite) TestGetBypassers() { +func (s *TestSuite) TestGetBypassers() { s.SetupTimelock(testPDASeedTimelockGetBypassers, 1*time.Second) ctx := context.Background() @@ -88,7 +88,7 @@ func (s *SolanaTestSuite) TestGetBypassers() { s.Require().ElementsMatch(expected, bypassers, "Bypassers don't match") } -func (s *SolanaTestSuite) TestIsOperation() { +func (s *TestSuite) TestIsOperation() { ctx := context.Background() admin, err := solana.PrivateKeyFromBase58(privateKey) s.Require().NoError(err) @@ -104,7 +104,7 @@ func (s *SolanaTestSuite) TestIsOperation() { s.Require().True(operation, "Operation should exist") } -func (s *SolanaTestSuite) TestIOperationPending() { +func (s *TestSuite) TestIOperationPending() { ctx := context.Background() admin, err := solana.PrivateKeyFromBase58(privateKey) s.Require().NoError(err) @@ -121,7 +121,7 @@ func (s *SolanaTestSuite) TestIOperationPending() { s.Require().True(operation, "Operation should be pending") } -func (s *SolanaTestSuite) TestIsOperationReady() { +func (s *TestSuite) TestIsOperationReady() { ctx := context.Background() admin, err := solana.PrivateKeyFromBase58(privateKey) s.Require().NoError(err) @@ -140,7 +140,7 @@ func (s *SolanaTestSuite) TestIsOperationReady() { s.Require().True(operation, "Operation should be ready") } -func (s *SolanaTestSuite) TestIsOperationDone() { +func (s *TestSuite) TestIsOperationDone() { ctx := context.Background() admin, err := solana.PrivateKeyFromBase58(privateKey) s.Require().NoError(err) @@ -159,7 +159,7 @@ func (s *SolanaTestSuite) TestIsOperationDone() { s.Require().True(operation, "Operation should be done") } -func (s *SolanaTestSuite) TestGetMinDelay() { +func (s *TestSuite) TestGetMinDelay() { ctx := context.Background() minDelay := 1 * time.Second s.SetupTimelock(testPDASeedTimelockMinDelay, minDelay) @@ -171,7 +171,7 @@ func (s *SolanaTestSuite) TestGetMinDelay() { s.Require().Equal(delay, uint64(minDelay.Seconds()), "Min delay should match the configured value") } -func (s *SolanaTestSuite) createOperation(timelockID [32]byte) timelockutils.Operation { +func (s *TestSuite) createOperation(timelockID [32]byte) timelockutils.Operation { salt, serr := timelockutils.SimpleSalt() s.Require().NoError(serr) diff --git a/e2e/tests/sui/common.go b/e2e/tests/sui/common.go index ff4c00733..8aa36fb2f 100644 --- a/e2e/tests/sui/common.go +++ b/e2e/tests/sui/common.go @@ -25,7 +25,7 @@ import ( "github.com/smartcontractkit/mcms/types" ) -type SuiTestSuite struct { +type TestSuite struct { suite.Suite e2e.TestSetup @@ -60,7 +60,7 @@ type SuiTestSuite struct { entrypointArgEncoder suisdk.EntrypointArgEncoder } -func (s *SuiTestSuite) SetupSuite() { +func (s *TestSuite) SetupSuite() { s.TestSetup = *e2e.InitializeSharedTestSetup(s.T()) account := s.SuiBlockchain.NetworkSpecificData.SuiAccount @@ -80,7 +80,7 @@ func (s *SuiTestSuite) SetupSuite() { s.chainSelector = types.ChainSelector(cselectors.SUI_TESTNET.Selector) } -func (s *SuiTestSuite) DeployMCMSContract() { +func (s *TestSuite) DeployMCMSContract() { gasBudget := uint64(300_000_000) mcmsPackage, tx, err := mcms.PublishMCMS(s.T().Context(), &bind.CallOpts{ Signer: s.signer, @@ -120,7 +120,7 @@ func (s *SuiTestSuite) DeployMCMSContract() { } } -func (s *SuiTestSuite) DeployMCMSUserContract() { +func (s *TestSuite) DeployMCMSUserContract() { gasBudget := uint64(300_000_000) signerAddress, err := s.signer.GetAddress() s.Require().NoError(err, "Failed to get address") @@ -165,7 +165,7 @@ func (s *SuiTestSuite) DeployMCMSUserContract() { } } -func (s *SuiTestSuite) extractByteArgsFromEncodedCall(encodedCall bind.EncodedCall) []byte { +func (s *TestSuite) extractByteArgsFromEncodedCall(encodedCall bind.EncodedCall) []byte { var args []byte for _, callArg := range encodedCall.CallArgs { if callArg.CallArg.UnresolvedObject != nil { diff --git a/e2e/tests/sui/inspection.go b/e2e/tests/sui/inspection.go index b2d966c25..a15d42e29 100644 --- a/e2e/tests/sui/inspection.go +++ b/e2e/tests/sui/inspection.go @@ -15,12 +15,12 @@ import ( // InspectionTestSuite defines the test suite for Sui inspection tests type InspectionTestSuite struct { - SuiTestSuite + TestSuite } // SetupSuite runs before the test suite func (s *InspectionTestSuite) SetupSuite() { - s.SuiTestSuite.SetupSuite() + s.TestSuite.SetupSuite() s.DeployMCMSContract() } diff --git a/e2e/tests/sui/mcms_e2e.go b/e2e/tests/sui/mcms_e2e.go index 6d49cf8f8..a10d6651d 100644 --- a/e2e/tests/sui/mcms_e2e.go +++ b/e2e/tests/sui/mcms_e2e.go @@ -4,7 +4,6 @@ package sui import ( "crypto/ecdsa" - "testing" "time" "github.com/smartcontractkit/mcms" @@ -16,23 +15,23 @@ import ( ) type MCMSUserTestSuite struct { - SuiTestSuite + TestSuite } // SetupSuite runs before the test suite func (s *MCMSUserTestSuite) SetupSuite() { - s.SuiTestSuite.SetupSuite() + s.TestSuite.SetupSuite() s.DeployMCMSContract() s.DeployMCMSUserContract() } // TestMCMSUserFunctionOne tests MCMS user function one -func (s *MCMSUserTestSuite) Test_MCMSUser_Function_One() { - s.T().Run("Proposer Role", func(t *testing.T) { +func (s *MCMSUserTestSuite) TestMCMSUserFunctionOne() { + s.Run("Proposer Role", func() { RunMCMSUserFunctionOneProposal(s, suisdk.TimelockRoleProposer) }) - s.T().Run("Bypasser Role", func(t *testing.T) { + s.Run("Bypasser Role", func() { RunMCMSUserFunctionOneProposal(s, suisdk.TimelockRoleBypasser) }) } diff --git a/e2e/tests/sui/mcms_user_upgrade.go b/e2e/tests/sui/mcms_user_upgrade.go index e6196d78e..1a717553a 100644 --- a/e2e/tests/sui/mcms_user_upgrade.go +++ b/e2e/tests/sui/mcms_user_upgrade.go @@ -3,7 +3,7 @@ package sui import ( - "context" + "errors" "fmt" "strconv" "strings" @@ -28,11 +28,11 @@ const ( ) type MCMSUserUpgradeTestSuite struct { - SuiTestSuite + TestSuite } -func (s *MCMSUserUpgradeTestSuite) Test_Sui_MCMSUser_UpgradeProposal() { - s.T().Run("TimelockProposal - MCMS User Upgrade through Schedule", func(t *testing.T) { +func (s *MCMSUserUpgradeTestSuite) TestMCMSUserUpgradeProposal() { + s.Run("TimelockProposal - MCMS User Upgrade through Schedule", func() { RunMCMSUserUpgradeProposal(s) }) } @@ -81,7 +81,7 @@ func RunMCMSUserUpgradeProposal(s *MCMSUserUpgradeTestSuite) { s.Require().NoError(err, "setting proposer config") // Phase 3: Setup ownership and registration - executeMCMSSelfOwnershipTransfer(s.T(), ctx, s, proposerConfig) + executeMCMSSelfOwnershipTransfer(s.T(), s, proposerConfig) deployerContract, err := module_mcms_deployer.NewMcmsDeployer(s.mcmsPackageID, s.client) s.Require().NoError(err) @@ -104,7 +104,7 @@ func RunMCMSUserUpgradeProposal(s *MCMSUserUpgradeTestSuite) { WaitForExecution: true, }) s.Require().NoError(err) - s.Require().Equal(version, "MCMSUser 1.0.0") + s.Require().Equal("MCMSUser 1.0.0", version) // Phase 5: Execute upgrade signerAddr, err := s.signer.GetAddress() @@ -117,7 +117,7 @@ func RunMCMSUserUpgradeProposal(s *MCMSUserUpgradeTestSuite) { }) s.Require().NoError(err) - newAddress := executeUpgradePTB(s.T(), ctx, s, compiledPackage, proposerConfig) + newAddress := executeUpgradePTB(s.T(), s, compiledPackage, proposerConfig) // Phase 6: Verify upgrade completion mcmsUserContract, err := module_mcms_user.NewMcmsUser(newAddress, s.client) @@ -128,7 +128,7 @@ func RunMCMSUserUpgradeProposal(s *MCMSUserUpgradeTestSuite) { WaitForExecution: true, }) s.Require().NoError(err) - s.Require().Equal(mcmsUserVersion, "MCMSUser 2.0.0") + s.Require().Equal("MCMSUser 2.0.0", mcmsUserVersion) s.T().Log("✅ MCMS User upgrade committed successfully - Complete MCMS → Upgrade workflow completed!") } @@ -148,8 +148,9 @@ func logDeploymentInfo(s *MCMSUserUpgradeTestSuite) { s.T().Logf("MCMS User State Object ID: %s", s.stateObj) } -func executeMCMSSelfOwnershipTransfer(t *testing.T, ctx context.Context, s *MCMSUserUpgradeTestSuite, proposerConfig *RoleConfig) { +func executeMCMSSelfOwnershipTransfer(t *testing.T, s *MCMSUserUpgradeTestSuite, proposerConfig *RoleConfig) { t.Helper() + ctx := t.Context() gasBudget := DefaultGasBudget tx, err := s.mcmsAccount.TransferOwnershipToSelf( @@ -165,7 +166,7 @@ func executeMCMSSelfOwnershipTransfer(t *testing.T, ctx context.Context, s *MCMS s.Require().NoError(err, "Failed to transfer MCMS ownership to self") s.Require().NotEmpty(tx, "Transaction should not be empty") - executeMCMSSelfOwnershipAcceptanceProposal(t, ctx, s, proposerConfig) + executeMCMSSelfOwnershipAcceptanceProposal(t, s, proposerConfig) tx, err = s.mcmsAccount.ExecuteOwnershipTransfer( ctx, @@ -183,8 +184,9 @@ func executeMCMSSelfOwnershipTransfer(t *testing.T, ctx context.Context, s *MCMS s.Require().NotEmpty(tx, "Transaction should not be empty") } -func executeMCMSSelfOwnershipAcceptanceProposal(t *testing.T, ctx context.Context, s *MCMSUserUpgradeTestSuite, proposerConfig *RoleConfig) { +func executeMCMSSelfOwnershipAcceptanceProposal(t *testing.T, s *MCMSUserUpgradeTestSuite, proposerConfig *RoleConfig) { t.Helper() + ctx := t.Context() transaction, err := createMCMSAcceptOwnershipTransaction(s) s.Require().NoError(err) @@ -282,8 +284,9 @@ func executeMCMSSelfOwnershipAcceptanceProposal(t *testing.T, ctx context.Contex // 1. MCMS timelock execution → produces UpgradeTicket // 2. Package upgrade using the UpgradeTicket → produces UpgradeReceipt // 3. Commit upgrade using the UpgradeReceipt -func executeUpgradePTB(t *testing.T, ctx context.Context, s *MCMSUserUpgradeTestSuite, compiledPackage bind.PackageArtifact, proposerConfig *RoleConfig) string { +func executeUpgradePTB(t *testing.T, s *MCMSUserUpgradeTestSuite, compiledPackage bind.PackageArtifact, proposerConfig *RoleConfig) string { t.Helper() + ctx := t.Context() tx, err := suisdk.CreateUpgradeTransaction(compiledPackage, s.mcmsPackageID, s.depStateObj, s.registryObj, s.ownerCapObj, s.mcmsUserPackageID) s.Require().NoError(err) @@ -390,7 +393,7 @@ func getUpgradedAddress(t *testing.T, result *models.SuiTransactionBlockResponse t.Helper() if result == nil || result.Events == nil { - return "", fmt.Errorf("result is nil or events are nil") + return "", errors.New("result is nil or events are nil") } for _, event := range result.Events { @@ -399,7 +402,7 @@ func getUpgradedAddress(t *testing.T, result *models.SuiTransactionBlockResponse } } - return "", fmt.Errorf("upgrade receipt committed event not found") + return "", errors.New("upgrade receipt committed event not found") } // isUpgradeEvent checks if the event is an upgrade receipt committed event @@ -417,7 +420,7 @@ func processUpgradeEvent(t *testing.T, event models.SuiEventResponse) (string, e event.PackageId, event.TransactionModule, event.Type) if event.ParsedJson == nil { - return "", fmt.Errorf("parsed json is nil") + return "", errors.New("parsed json is nil") } t.Log("MCMS User Package Upgrade Details:") @@ -445,7 +448,7 @@ func validateAddressChange(t *testing.T, oldAddr, newAddr any) (string, error) { t.Helper() if oldAddr == nil || newAddr == nil { - return "", fmt.Errorf("package addresses are nil") + return "", errors.New("package addresses are nil") } oldAddrStr := fmt.Sprintf("%v", oldAddr) @@ -453,7 +456,7 @@ func validateAddressChange(t *testing.T, oldAddr, newAddr any) (string, error) { if oldAddrStr == newAddrStr { t.Errorf("ERROR: Package address did not change! Old: %v, New: %v", oldAddr, newAddr) - return "", fmt.Errorf("package address did not change") + return "", errors.New("package address did not change") } t.Logf("✅ MCMS User package address changed successfully: %s → %s", oldAddrStr, newAddrStr) @@ -481,7 +484,7 @@ func validateVersionIncrement(t *testing.T, oldVer, newVer any) error { t.Errorf("ERROR: Version did not increment correctly! Old: %.0f, New: %.0f (expected %.0f)", oldVersion, newVersion, expectedVersion) - return fmt.Errorf("version did not increment correctly") + return errors.New("version did not increment correctly") } t.Logf("✅ MCMS User version incremented correctly: %.0f → %.0f", oldVersion, newVersion) diff --git a/e2e/tests/sui/proposal_helpers.go b/e2e/tests/sui/proposal_helpers.go index d93f01d90..ee6e6a79f 100644 --- a/e2e/tests/sui/proposal_helpers.go +++ b/e2e/tests/sui/proposal_helpers.go @@ -65,6 +65,7 @@ type ProposalBuilderConfig struct { func CreateTimelockProposalBuilder(t *testing.T, config ProposalBuilderConfig, operations []types.BatchOperation) *mcms.TimelockProposalBuilder { t.Helper() + validUntilMs := uint32(time.Now().Add(time.Hour * 24).Unix()) metadata, err := suisdk.NewChainMetadata(config.CurrentOpCount, config.Role, config.McmsPackageID, config.McmsObjID, config.AccountObjID, config.RegistryObjID, config.TimelockObjID, config.DeployerStateObjID) diff --git a/e2e/tests/sui/set_config.go b/e2e/tests/sui/set_config.go index 3c0502c5f..7d52bc77c 100644 --- a/e2e/tests/sui/set_config.go +++ b/e2e/tests/sui/set_config.go @@ -14,7 +14,7 @@ import ( "github.com/smartcontractkit/mcms/types" ) -func (s *SuiTestSuite) Test_Sui_SetConfig() { +func (s *TestSuite) TestSetConfig() { // Setup the test suite and deploy contracts s.SetupSuite() s.DeployMCMSContract() diff --git a/e2e/tests/sui/set_root.go b/e2e/tests/sui/set_root.go index 69273ba77..bce3e1847 100644 --- a/e2e/tests/sui/set_root.go +++ b/e2e/tests/sui/set_root.go @@ -18,12 +18,12 @@ import ( // SetRootTestSuite defines the test suite for Sui SetRoot tests type SetRootTestSuite struct { - SuiTestSuite + TestSuite } // SetupSuite runs before the test suite func (s *SetRootTestSuite) SetupSuite() { - s.SuiTestSuite.SetupSuite() + s.TestSuite.SetupSuite() s.DeployMCMSContract() } @@ -119,7 +119,7 @@ func (s *SetRootTestSuite) TestSetRoot() { // Root should not be empty after setting s.Require().NotEqual(common.Hash{}, root, "Root should not be empty after SetRoot") - s.Require().Greater(validUntilActual, uint32(0), "ValidUntil should be greater than 0 after SetRoot") + s.Require().Positive(validUntilActual, "ValidUntil should be greater than 0 after SetRoot") // Verify root metadata rootMetadata, err := inspector.GetRootMetadata(ctx, s.mcmsObj) @@ -230,6 +230,6 @@ func (s *SetRootTestSuite) TestSetRootMultipleSigners() { root, validUntilActual, err := multiInspector.GetRoot(ctx, s.mcmsObj) s.Require().NoError(err, "Failed to get root after multi-signer SetRoot") s.Require().NotEqual(common.Hash{}, root, "Root should not be empty after multi-signer SetRoot") - s.Require().Greater(validUntilActual, uint32(0), "ValidUntil should be greater than 0 after multi-signer SetRoot") + s.Require().Positive(validUntilActual, "ValidUntil should be greater than 0 after multi-signer SetRoot") }) } diff --git a/e2e/tests/sui/timelock_cancel.go b/e2e/tests/sui/timelock_cancel.go index a03b4d55b..b318b85db 100644 --- a/e2e/tests/sui/timelock_cancel.go +++ b/e2e/tests/sui/timelock_cancel.go @@ -15,10 +15,10 @@ import ( // TimelockProposalTestSuite defines the test suite for Sui timelock proposal tests type TimelockCancelProposalTestSuite struct { - SuiTestSuite + TestSuite } -func (s *TimelockCancelProposalTestSuite) Test_Sui_TimelockCancelProposal() { +func (s *TimelockCancelProposalTestSuite) TestTimelock_CancelProposal() { s.DeployMCMSContract() proposerCount := 3 @@ -228,7 +228,7 @@ func (s *TimelockCancelProposalTestSuite) Test_Sui_TimelockCancelProposal() { }) s.Require().NoError(err, "Failed to derive cancellation proposal") - cancelProposal, opId, err := cancelTimelockProposal.Convert(s.T().Context(), convertersMap) + cancelProposal, opID, err := cancelTimelockProposal.Convert(s.T().Context(), convertersMap) s.Require().NoError(err, "Failed to convert cancellation proposal") // Sign the cancellation proposal @@ -311,5 +311,5 @@ func (s *TimelockCancelProposalTestSuite) Test_Sui_TimelockCancelProposal() { _, execErr = timelockExecutable.Execute(s.T().Context(), 0, mcms.WithCallProxy(s.timelockObj)) s.Require().Error(execErr, "Executing canceled operation should fail") - s.T().Logf("✅ Successfully canceled timelock operation with ID: %s", opId) + s.T().Logf("✅ Successfully canceled timelock operation with ID: %s", opID) } diff --git a/e2e/tests/sui/timelock_inspection.go b/e2e/tests/sui/timelock_inspection.go index a8a855794..bc0529087 100644 --- a/e2e/tests/sui/timelock_inspection.go +++ b/e2e/tests/sui/timelock_inspection.go @@ -13,12 +13,12 @@ import ( // TimelockInspectionTestSuite defines the test suite for Sui timelock inspection tests type TimelockInspectionTestSuite struct { - SuiTestSuite + TestSuite } // SetupSuite runs before the test suite func (s *TimelockInspectionTestSuite) SetupSuite() { - s.SuiTestSuite.SetupSuite() + s.TestSuite.SetupSuite() s.DeployMCMSContract() } diff --git a/e2e/tests/sui/timelock_proposal.go b/e2e/tests/sui/timelock_proposal.go index 590fdba19..3f63ce4fc 100644 --- a/e2e/tests/sui/timelock_proposal.go +++ b/e2e/tests/sui/timelock_proposal.go @@ -4,7 +4,6 @@ package sui import ( "crypto/ecdsa" - "testing" "time" "github.com/smartcontractkit/mcms" @@ -17,15 +16,15 @@ import ( // TimelockProposalTestSuite defines the test suite for Sui timelock proposal tests type TimelockProposalTestSuite struct { - SuiTestSuite + TestSuite } -func (s *TimelockProposalTestSuite) Test_Sui_TimelockProposal() { - s.T().Run("TimelockProposal - MCMSAccount Accept Ownership through Bypass", func(t *testing.T) { +func (s *TimelockProposalTestSuite) TestTimelockProposal() { + s.Run("TimelockProposal - MCMSAccount Accept Ownership through Bypass", func() { RunAcceptOwnershipProposal(s, suisdk.TimelockRoleBypasser) }) - s.T().Run("TimelockProposal - MCMSAccount Accept Ownership through Schedule", func(t *testing.T) { + s.Run("TimelockProposal - MCMSAccount Accept Ownership through Schedule", func() { RunAcceptOwnershipProposal(s, suisdk.TimelockRoleProposer) }) } diff --git a/e2e/utils/solana/testutils.go b/e2e/utils/solana/testutils.go index 359a2a532..f9607515c 100644 --- a/e2e/utils/solana/testutils.go +++ b/e2e/utils/solana/testutils.go @@ -2,7 +2,7 @@ package solana import ( "context" - "fmt" + "errors" "testing" "time" @@ -16,10 +16,9 @@ const pollInterval = 50 * time.Millisecond // FundAccounts funds the given accounts with 100 SOL each. // It waits for the transactions to be confirmed. -func FundAccounts( - t *testing.T, - ctx context.Context, accounts []solana.PublicKey, solAmount uint64, solanaGoClient *rpc.Client) { +func FundAccounts(t *testing.T, accounts []solana.PublicKey, solAmount uint64, solanaGoClient *rpc.Client) { t.Helper() + ctx := t.Context() var sigs = make([]solana.Signature, 0, len(accounts)) for _, v := range accounts { @@ -38,7 +37,7 @@ func FundAccounts( for remaining > 0 { select { case <-timeoutCtx.Done(): - require.NoError(t, fmt.Errorf("unable to find transaction within timeout")) + require.NoError(t, errors.New("unable to find transaction within timeout")) case <-ticker.C: statusRes, sigErr := solanaGoClient.GetSignatureStatuses(ctx, true, sigs...) require.NoError(t, sigErr) diff --git a/e2e/utils/testutils.go b/e2e/utils/testutils.go index 29a8fd2df..09522d76d 100644 --- a/e2e/utils/testutils.go +++ b/e2e/utils/testutils.go @@ -67,7 +67,7 @@ func WaitMinedWithTxHash(ctx context.Context, b bind.DeployBackend, txHash commo func ReadFixture(path string) (*os.File, error) { _, filename, _, ok := runtime.Caller(0) if !ok { - return nil, fmt.Errorf("failed to get current file path") + return nil, errors.New("failed to get current file path") } projectRoot := filepath.Dir(filepath.Dir(filepath.Dir(filename))) fixturePath := filepath.Join(projectRoot, "e2e", "fixtures", path) diff --git a/errors.go b/errors.go index 26eb187b7..2ce62bd39 100644 --- a/errors.go +++ b/errors.go @@ -172,5 +172,5 @@ type DuplicateSignersError struct { } func (e *DuplicateSignersError) Error() string { - return fmt.Sprintf("duplicate signer detected: %s", e.signer) + return "duplicate signer detected: " + e.signer } diff --git a/executable_test.go b/executable_test.go index c9ad7fa55..4d1881470 100644 --- a/executable_test.go +++ b/executable_test.go @@ -6,11 +6,13 @@ import ( "math/big" "testing" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/mcms/internal/testutils/chaintest" "github.com/smartcontractkit/mcms/internal/testutils/evmsim" "github.com/smartcontractkit/mcms/sdk" @@ -20,7 +22,7 @@ import ( "github.com/smartcontractkit/mcms/types" ) -func Test_NewExecutable(t *testing.T) { +func TestNewExecutable(t *testing.T) { t.Parallel() executor := mocks.NewExecutor(t) // We only need this to fulfill the interface argument requirements diff --git a/factory_test.go b/factory_test.go index 9cf8c6b84..5e57e85a9 100644 --- a/factory_test.go +++ b/factory_test.go @@ -8,14 +8,15 @@ import ( "github.com/smartcontractkit/mcms/internal/testutils/chaintest" "github.com/smartcontractkit/mcms/sdk" - aptossdk "github.com/smartcontractkit/mcms/sdk/aptos" - evmsdk "github.com/smartcontractkit/mcms/sdk/evm" - solanasdk "github.com/smartcontractkit/mcms/sdk/solana" - suisdk "github.com/smartcontractkit/mcms/sdk/sui" "github.com/smartcontractkit/mcms/types" + + "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/sdk/evm" + "github.com/smartcontractkit/mcms/sdk/solana" + "github.com/smartcontractkit/mcms/sdk/sui" ) -func Test_NewEncoder(t *testing.T) { +func TestNewEncoder(t *testing.T) { t.Parallel() // Static inputs @@ -35,7 +36,7 @@ func Test_NewEncoder(t *testing.T) { name: "success: returns an EVM encoder (not simulated)", giveSelector: chaintest.Chain2Selector, giveIsSim: false, - want: &evmsdk.Encoder{ + want: &evm.Encoder{ TxCount: giveTxCount, ChainSelector: chaintest.Chain2Selector, OverridePreviousRoot: false, @@ -46,7 +47,7 @@ func Test_NewEncoder(t *testing.T) { name: "success: returns an EVM encoder (simulated)", giveSelector: chaintest.Chain2Selector, giveIsSim: true, - want: &evmsdk.Encoder{ + want: &evm.Encoder{ ChainSelector: chaintest.Chain2Selector, TxCount: giveTxCount, OverridePreviousRoot: false, @@ -57,7 +58,7 @@ func Test_NewEncoder(t *testing.T) { name: "success: returns a Solana encoder (not simulated)", giveSelector: chaintest.Chain4Selector, giveIsSim: false, - want: &solanasdk.Encoder{ + want: &solana.Encoder{ TxCount: giveTxCount, ChainSelector: chaintest.Chain4Selector, OverridePreviousRoot: false, @@ -67,7 +68,7 @@ func Test_NewEncoder(t *testing.T) { name: "success: returns an Aptos encoder (not simulated)", giveSelector: chaintest.Chain5Selector, giveIsSim: false, - want: &aptossdk.Encoder{ + want: &aptos.Encoder{ TxCount: giveTxCount, ChainSelector: chaintest.Chain5Selector, OverridePreviousRoot: false, @@ -77,7 +78,7 @@ func Test_NewEncoder(t *testing.T) { name: "success: returns a Sui encoder", giveSelector: chaintest.Chain6Selector, giveIsSim: false, - want: &suisdk.Encoder{ + want: &sui.Encoder{ TxCount: giveTxCount, ChainSelector: chaintest.Chain6Selector, OverridePreviousRoot: false, @@ -112,7 +113,7 @@ func Test_NewEncoder(t *testing.T) { } } -func Test_newTimelockConverter(t *testing.T) { +func TestNewTimelockConverter(t *testing.T) { t.Parallel() tests := []struct { @@ -124,17 +125,17 @@ func Test_newTimelockConverter(t *testing.T) { { name: "success: EVM executor", chainSelector: chaintest.Chain1Selector, - want: &evmsdk.TimelockConverter{}, + want: &evm.TimelockConverter{}, }, { name: "success: Solana executor", chainSelector: chaintest.Chain4Selector, - want: &solanasdk.TimelockConverter{}, + want: &solana.TimelockConverter{}, }, { name: "success: Sui executor", chainSelector: chaintest.Chain6Selector, - want: &suisdk.TimelockConverter{}, + want: &sui.TimelockConverter{}, }, { name: "failure: unknown selector", diff --git a/go.mod b/go.mod index 9b8dd31a5..f1556fe53 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,14 @@ module github.com/smartcontractkit/mcms -go 1.24.4 - -toolchain go1.24.7 +go 1.25.3 +//nolint:gomoddirectives // allow replace directive replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 require ( github.com/aptos-labs/aptos-go-sdk v1.11.0 github.com/block-vision/sui-go-sdk v1.1.2 - github.com/ethereum/go-ethereum v1.15.7 + github.com/ethereum/go-ethereum v1.16.2 github.com/gagliardetto/binary v0.8.0 github.com/gagliardetto/solana-go v1.13.0 github.com/go-playground/validator/v10 v10.28.0 @@ -23,10 +22,10 @@ require ( github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a github.com/smartcontractkit/chainlink-sui v0.0.0-20251104205009-00bd79b81471 github.com/smartcontractkit/chainlink-testing-framework/framework v0.12.1 - github.com/smartcontractkit/freeport v0.1.2 - github.com/spf13/cast v1.7.1 + github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e + github.com/spf13/cast v1.10.0 github.com/stretchr/testify v1.11.1 - github.com/zksync-sdk/zksync2-go v1.1.0 + github.com/zksync-sdk/zksync2-go v1.1.1-0.20250620124214-2c742ee399c6 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.43.0 golang.org/x/tools v0.37.0 @@ -38,7 +37,7 @@ require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/BurntSushi/toml v1.5.0 // indirect - github.com/DataDog/zstd v1.5.2 // indirect + github.com/DataDog/zstd v1.5.6 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/VictoriaMetrics/fastcache v1.13.0 // indirect github.com/XSAM/otelsql v0.37.0 // indirect @@ -54,11 +53,12 @@ require ( github.com/btcsuite/btcutil v1.0.2 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.16.1 // indirect github.com/cloudevents/sdk-go/v2 v2.16.1 // indirect github.com/cockroachdb/errors v1.11.3 // indirect - github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect + github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v1.1.5 // indirect github.com/cockroachdb/redact v1.1.5 // indirect @@ -72,22 +72,23 @@ require ( github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect + github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect - github.com/crate-crypto/go-kzg-4844 v1.1.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v28.5.1+incompatible // indirect - github.com/docker/go-connections v0.6.0 // indirect + github.com/docker/docker v28.3.3+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/ebitengine/purego v0.9.0 // indirect - github.com/ethereum/c-kzg-4844 v1.0.3 // indirect + github.com/ebitengine/purego v0.8.4 // indirect + github.com/emicklei/dot v1.6.2 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect github.com/ethereum/go-verkle v0.2.2 // indirect github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/ferranbt/fastssz v0.1.4 // indirect - github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.10 // indirect github.com/gagliardetto/treeout v0.1.4 // indirect @@ -98,7 +99,7 @@ require ( github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-resty/resty/v2 v2.16.5 // indirect + github.com/go-resty/resty/v2 v2.16.3 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/gofrs/flock v0.12.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -108,8 +109,9 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/gorilla/rpc v1.2.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect + github.com/graph-gophers/graphql-go v1.5.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect @@ -135,18 +137,20 @@ require ( github.com/jmoiron/sqlx v1.4.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.18.1 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect - github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 // indirect + github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect github.com/magiconair/properties v1.8.10 // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect @@ -163,48 +167,48 @@ require ( github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oklog/run v1.1.0 // indirect + github.com/oklog/run v1.2.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/onsi/gomega v1.34.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/pion/dtls/v2 v2.2.7 // indirect + github.com/pion/dtls/v2 v2.2.12 // indirect github.com/pion/logging v0.2.2 // indirect github.com/pion/stun/v2 v2.0.0 // indirect - github.com/pion/transport/v2 v2.2.1 // indirect + github.com/pion/transport/v2 v2.2.10 // indirect github.com/pion/transport/v3 v3.0.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.63.0 // indirect - github.com/prometheus/procfs v0.16.0 // indirect + github.com/prometheus/client_golang v1.23.0 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.65.0 // indirect + github.com/prometheus/procfs v0.16.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/rogpeppe/go-internal v1.14.1 // indirect - github.com/rs/cors v1.7.0 // indirect - github.com/rs/zerolog v1.34.0 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/rs/cors v1.11.1 // indirect + github.com/rs/zerolog v1.33.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect - github.com/shirou/gopsutil/v4 v4.25.9 // indirect + github.com/shirou/gopsutil/v4 v4.25.5 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250805210128-7f8a0f403c3a // indirect - github.com/smartcontractkit/chainlink-common v0.9.1-0.20250815142532-64e0a7965958 // indirect - github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.1 // indirect - github.com/smartcontractkit/chainlink-common/pkg/values v0.0.0-20250806152407-159881c7589c // indirect + github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20251024142759-093ed1b4017f // indirect + github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142 // indirect + github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4 // indirect + github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect - github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 // indirect + github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d // indirect github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863 // indirect github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect - github.com/testcontainers/testcontainers-go v0.39.0 // indirect + github.com/testcontainers/testcontainers-go v0.38.0 // indirect github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect @@ -217,28 +221,28 @@ require ( github.com/x448/float16 v0.8.4 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.mongodb.org/mongo-driver v1.17.0 // indirect - go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.mongodb.org/mongo-driver v1.17.2 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.13.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.36.0 // indirect go.opentelemetry.io/otel/log v0.13.0 // indirect go.opentelemetry.io/otel/metric v1.38.0 // indirect go.opentelemetry.io/otel/sdk v1.38.0 // indirect go.opentelemetry.io/otel/sdk/log v0.13.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect go.opentelemetry.io/otel/trace v1.38.0 // indirect - go.opentelemetry.io/proto/otlp v1.5.0 // indirect + go.opentelemetry.io/proto/otlp v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.3.1 // indirect golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc // indirect @@ -249,9 +253,10 @@ require ( golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.12.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/grpc v1.74.2 // indirect google.golang.org/protobuf v1.36.7 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index bc4c62054..efbd71199 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg6 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= -github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY= +github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= @@ -26,8 +26,8 @@ github.com/XSAM/otelsql v0.37.0/go.mod h1:LHbCu49iU8p255nCn1oi04oX2UjSoRcUMiKEHo github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/apache/arrow-go/v18 v18.3.0 h1:Xq4A6dZj9Nu33sqZibzn012LNnewkTUlfKVUFD/RX/I= -github.com/apache/arrow-go/v18 v18.3.0/go.mod h1:eEM1DnUTHhgGAjf/ChvOAQbUQ+EPohtDrArffvUjPg8= +github.com/apache/arrow-go/v18 v18.3.1 h1:oYZT8FqONiK74JhlH3WKVv+2NKYoyZ7C2ioD4Dj3ixk= +github.com/apache/arrow-go/v18 v18.3.1/go.mod h1:12QBya5JZT6PnBihi5NJTzbACrDGXYkrgjujz3MRQXU= github.com/aptos-labs/aptos-go-sdk v1.11.0 h1:vIL1hpjECUiu7zMl9Wz6VV8ttXsrDqKUj0HxoeaIER4= github.com/aptos-labs/aptos-go-sdk v1.11.0/go.mod h1:8YvYwRg93UcG6pTStCpZdYiscCtKh51sYfeLgIy/41c= github.com/avast/retry-go/v4 v4.6.1 h1:VkOLRubHdisGrHnTu89g08aQEWEgRU7LVEop3GbIcMk= @@ -79,6 +79,8 @@ github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMU github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= +github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= @@ -100,8 +102,8 @@ github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaY github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= -github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= -github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 h1:pU88SPhIFid6/k0egdR5V6eALQYq2qbSmukrkgIh/0A= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/pebble v1.1.5 h1:5AAWCBWbat0uE0blr8qzufZP5tBjkRyy/jWe1QWLnvw= @@ -131,10 +133,10 @@ github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GK github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/crate-crypto/go-eth-kzg v1.3.0 h1:05GrhASN9kDAidaFJOda6A4BEvgvuXbazXg/0E3OOdI= +github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= -github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4= -github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= @@ -163,14 +165,14 @@ github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbz github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.5.1+incompatible h1:Bm8DchhSD2J6PsFzxC35TZo4TLGR2PdW/E69rU45NhM= -github.com/docker/docker v28.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= -github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= +github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= +github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/ebitengine/purego v0.9.0 h1:mh0zpKBIXDceC63hpvPuGLiJ8ZAa3DfrFTudmfi8A4k= -github.com/ebitengine/purego v0.9.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -178,10 +180,10 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/c-kzg-4844 v1.0.3 h1:IEnbOHwjixW2cTvKRUlAAUOeleV7nNM/umJR+qy4WDs= -github.com/ethereum/c-kzg-4844 v1.0.3/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.15.7 h1:vm1XXruZVnqtODBgqFaTclzP0xAvCvQIDKyFNUA1JpY= -github.com/ethereum/go-ethereum v1.15.7/go.mod h1:+S9k+jFzlyVTNcYGvqFhzN/SFhI6vA+aOY4T5tLSPL0= +github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w= +github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E= +github.com/ethereum/go-ethereum v1.16.2 h1:VDHqj86DaQiMpnMgc7l0rwZTg0FRmlz74yupSG5SnzI= +github.com/ethereum/go-ethereum v1.16.2/go.mod h1:X5CIOyo8SuK1Q5GnaEizQVLHT/DfsiGWuNeVdQcEMNA= github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= @@ -196,8 +198,8 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= -github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0= @@ -221,6 +223,7 @@ github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874/go.mod h1: github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -236,8 +239,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688= github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU= -github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM= -github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= +github.com/go-resty/resty/v2 v2.16.3 h1:zacNT7lt4b8M/io2Ahj6yPypL7bqx9n1iprfQuodV+E= +github.com/go-resty/resty/v2 v2.16.3/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -283,6 +286,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -298,12 +302,12 @@ github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36j github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= -github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= +github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1 h1:KcFzXwzM/kGhIRHvc8jdixfIJjVzuUJdnv+5xsPutog= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= @@ -397,8 +401,8 @@ github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7Bd github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= -github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= +github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= +github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= @@ -416,8 +420,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co= -github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -445,8 +449,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 h1:PwQumkgq4/acIiZhtifTV5OUqqiP82UAl0h87xj/l9k= -github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= @@ -474,8 +478,8 @@ github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -515,8 +519,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= +github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -539,8 +543,7 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= -github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= @@ -551,14 +554,17 @@ github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= +github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= +github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0= github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ= -github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= +github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -570,15 +576,17 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc= +github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= -github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= -github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM= -github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= +github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/prysmaticlabs/gohashtree v0.0.4-beta h1:H/EbCuXPeTV3lpKeXGPpEV9gsUpkqOOVnWapUyeWro4= +github.com/prysmaticlabs/gohashtree v0.0.4-beta/go.mod h1:BFdtALS+Ffhg3lGQIHv9HDWuHS8cTvHZzrHWxwOtGOs= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -586,16 +594,16 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= -github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= @@ -607,8 +615,8 @@ github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cj github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil/v4 v4.25.9 h1:JImNpf6gCVhKgZhtaAHJ0serfFGtlfIlSC08eaKdTrU= -github.com/shirou/gopsutil/v4 v4.25.9/go.mod h1:gxIxoC+7nQRwUl/xNhutXlD8lq+jxTgpIkEf3rADHL8= +github.com/shirou/gopsutil/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQUJAsc= +github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -622,30 +630,30 @@ github.com/smartcontractkit/chain-selectors v1.0.85 h1:A7eyN7KIACxmngn1MJJ0giVtf github.com/smartcontractkit/chain-selectors v1.0.85/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20251024142440-51f2ad2652a2 h1:vGdeMwHO3ow88HvxfhA4DDPYNY0X9jmdux7L83UF/W8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20251024142440-51f2ad2652a2/go.mod h1:iteU0WORHkArACVh/HoY/1bipV4TcNcJdTmom9uIT0E= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250805210128-7f8a0f403c3a h1:EqR0TWzpsIDhu28xromfL3/dfzx398rhUtucT4XLNGc= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250805210128-7f8a0f403c3a/go.mod h1:4e+IBu7TJVlmL31sTDYyYEbwJXjFDbv0jot7QQmBZ9E= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20251024142759-093ed1b4017f h1:jP2BHA7+QSp5IzWykT8KunThNbSwEM9j6lCXwEoxTIc= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20251024142759-093ed1b4017f/go.mod h1:pETrvAF8uvkZgtDgI/oRllZZaC4IpPO26tMxh1u9LC4= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a h1:kQ8Zs6OzXizScIK8PEb8THxDUziGttGT9D6tTTAwmZk= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a/go.mod h1:Ve1xD71bl193YIZQEoJMmBqLGQJdNs29bwbuObwvbhQ= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a h1:38dAlTPRUQHZus5dCnBnQyf/V4oYn0p2svWlbPgHDQ4= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a/go.mod h1:xtZNi6pOKdC3sLvokDvXOhgHzT+cyBqH/gWwvxTxqrg= -github.com/smartcontractkit/chainlink-common v0.9.1-0.20250815142532-64e0a7965958 h1:pfzvL8n8f4ygUe4pIBjHgM2Tzct6qG8Q/jxJjfHThMY= -github.com/smartcontractkit/chainlink-common v0.9.1-0.20250815142532-64e0a7965958/go.mod h1:OYfK10oQCJVQEdBmA2J1FC9gq+bp9497LcD88T0q+lw= -github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.1 h1:ca2z5OXgnbBPQRxpwXwBLJsUA1+cAp5ncfW4Ssvd6eY= -github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.1/go.mod h1:NZv/qKYGFRnkjOYBouajnDfFoZ+WDa6H2KNmSf1dnKc= -github.com/smartcontractkit/chainlink-common/pkg/values v0.0.0-20250806152407-159881c7589c h1:QaImySzrLcGzQc4wCF2yDqqb73jA3+9EIqybgx8zT4w= -github.com/smartcontractkit/chainlink-common/pkg/values v0.0.0-20250806152407-159881c7589c/go.mod h1:U1UAbPhy6D7Qz0wHKGPoQO+dpR0hsYjgUz8xwRrmKwI= +github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142 h1:xyGWWEwIwZv4wflEA12TDBGKEa86tDEECzl3n1Az2m0= +github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142/go.mod h1:1r3aM96KHAESfnayJ3BTHCkP1qJS1BEG1r4czeoaXlA= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4 h1:hvqATtrZ0iMRTI80cpBot/3JFbjz2j+2tvpfooVhRHw= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4/go.mod h1:eKGyfTKzr0/PeR7qKN4l2FcW9p+HzyKUwAfGhm/5YZc= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2 h1:1/KdO5AbUr3CmpLjMPuJXPo2wHMbfB8mldKLsg7D4M8= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2/go.mod h1:jUC52kZzEnWF9tddHh85zolKybmLpbQ1oNA4FjOHt1Q= github.com/smartcontractkit/chainlink-sui v0.0.0-20251104205009-00bd79b81471 h1:EaLuGs7jZ6Vm2iv6rNK3bQ3XN5CRbFd4knjjvaD1zFc= github.com/smartcontractkit/chainlink-sui v0.0.0-20251104205009-00bd79b81471/go.mod h1:VlyZhVw+a93Sk8rVHOIH6tpiXrMzuWLZrjs1eTIExW8= github.com/smartcontractkit/chainlink-testing-framework/framework v0.12.1 h1:Ld3OrOQfLubJ+os0/oau2V6RISgsEdBg+Q002zkgXpQ= github.com/smartcontractkit/chainlink-testing-framework/framework v0.12.1/go.mod h1:r6KXRM1u9ch5KFR2jspkgtyWEC1X+gxPCL8mR63U990= -github.com/smartcontractkit/freeport v0.1.2 h1:xMZ0UFHmjfB4MwbDANae3RS7UKt7OJ0JVqhjPSXdKVk= -github.com/smartcontractkit/freeport v0.1.2/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= +github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e h1:Hv9Mww35LrufCdM9wtS9yVi/rEWGI1UnjHbcKKU0nVY= +github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 h1:yGD0bRNoIQ9vOILzlYg4AiGKMKpJNqi7eIMpW7QIO9Y= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= -github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= -github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d h1:/0/80Ic6wpKH5F1nwDoRj9+70IxXunvCyNcCkA+9ik0= +github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d/go.mod h1:Acy3BTBxou83ooMESLO90s8PKSu7RvLCzwSTbxxfOK0= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863 h1:ba4VRWSkRzgdP5hB5OxexIzBXZbSwgcw8bEu06ivGQI= @@ -680,8 +688,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= -github.com/testcontainers/testcontainers-go v0.39.0 h1:uCUJ5tA+fcxbFAB0uP3pIK3EJ2IjjDUHFSZ1H1UxAts= -github.com/testcontainers/testcontainers-go v0.39.0/go.mod h1:qmHpkG7H5uPf/EvOORKvS6EuDkBUPE3zpVGaH9NL7f8= +github.com/testcontainers/testcontainers-go v0.38.0 h1:d7uEapLcv2P8AvH8ahLqDMMxda2W9gQN1nRbHS28HBw= +github.com/testcontainers/testcontainers-go v0.38.0/go.mod h1:C52c9MoHpWO+C4aqmgSU+hxlR5jlEayWtgYrb8Pzz1w= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -703,6 +711,7 @@ github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXV github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= +github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= @@ -716,38 +725,39 @@ github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -github.com/zksync-sdk/zksync2-go v1.1.0 h1:cRA1GlNrBEwLqvBLq5Xu22YCpbBeUBb4LKx5Wvwy25w= -github.com/zksync-sdk/zksync2-go v1.1.0/go.mod h1:NWNlQS21isOsSsn+hLRAPpiuv+3P+LcdaZNuRt2T5Yo= -go.mongodb.org/mongo-driver v1.17.0 h1:Hp4q2MCjvY19ViwimTs00wHi7G4yzxh4/2+nTx8r40k= -go.mongodb.org/mongo-driver v1.17.0/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4= -go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= -go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +github.com/zksync-sdk/zksync2-go v1.1.1-0.20250620124214-2c742ee399c6 h1:VRdX3Gn/I7ITbzUY4ZNfgn65tdQM9Zhf2b7KP0HZllk= +github.com/zksync-sdk/zksync2-go v1.1.1-0.20250620124214-2c742ee399c6/go.mod h1:NWNlQS21isOsSsn+hLRAPpiuv+3P+LcdaZNuRt2T5Yo= +go.mongodb.org/mongo-driver v1.17.2 h1:gvZyk8352qSfzyZ2UMWcpDpMSGEr1eqE4T793SqyhzM= +go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= +go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0 h1:HMUytBT3uGhPKYY/u/G5MR9itrlSO2SMOsSD3Tk3k7A= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0/go.mod h1:hdDXsiNLmdW/9BF2jQpnHHlhFajpWCEYfM6e5m2OAZg= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0 h1:C/Wi2F8wEmbxJ9Kuzw/nhP+Z9XaHYMkyDmXy6yR2cjw= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0/go.mod h1:0Lr9vmGKzadCTgsiBydxr6GEZ8SsZ7Ks53LzjWG5Ar4= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 h1:0NIXxOCFx+SKbhCVxwl3ETG8ClLPAa0KuKV6p3yhxP8= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0/go.mod h1:ChZSJbbfbl/DcRZNc9Gqh6DYGlfjw4PvO1pEOZH1ZsE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 h1:06ZeJRe5BnYXceSM9Vya83XXVaNGe3H1QqsvqRANQq8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2/go.mod h1:DvPtKE63knkDVP88qpatBj81JxN+w1bqfVbsbCbj1WY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 h1:tPLwQlXbJ8NSOfZc4OkgU5h2A38M4c9kfHSVc4PFQGs= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2/go.mod h1:QTnxBwT/1rBIgAG1goq6xMydfYOBKU6KTiYF4fp5zL8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.36.0 h1:zwdo1gS2eH26Rg+CoqVQpEK1h8gvt5qyU5Kk5Bixvow= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.36.0/go.mod h1:rUKCPscaRWWcqGT6HnEmYrK+YNe5+Sw64xgQTOJ5b30= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0 h1:gAU726w9J8fwr4qRDqu1GYMNNs4gXrU+Pv20/N1UpB4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0/go.mod h1:RboSDkp7N292rgu+T0MgVt2qgFGu6qa1RpZDOtpL76w= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 h1:JgtbA0xkWHnTmYk7YusopJFX6uleBmAuZ8n05NEh8nQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0/go.mod h1:179AK5aar5R3eS9FucPy6rggvU0g52cvKId8pv4+v0c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.13.0 h1:yEX3aC9KDgvYPhuKECHbOlr5GLwH6KTjLJ1sBSkkxkc= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.13.0/go.mod h1:/GXR0tBmmkxDaCUGahvksvp66mx4yh5+cFXgSlhg0vQ= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 h1:PB3Zrjs1sG1GBX51SXyTSoOTqcDglmsk7nT6tkKPb/k= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0/go.mod h1:U2R3XyVPzn0WX7wOIypPuptulsMcPDPs/oiSVOMVnHY= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgTNQVet8iTDW7oIk03tXHq+wkwIDnE= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 h1:rixTyDGXFxRy1xzhKrotaHy3/KXdPhlWARrCgK+eqUY= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0/go.mod h1:dowW6UsM9MKbJq5JTz2AMVp3/5iW5I/TStsk8S+CfHw= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.36.0 h1:G8Xec/SgZQricwWBJF/mHZc7A02YHedfFDENwJEdRA0= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.36.0/go.mod h1:PD57idA/AiFD5aqoxGxCvT/ILJPeHy3MjqU/NS7KogY= go.opentelemetry.io/otel/log v0.13.0 h1:yoxRoIZcohB6Xf0lNv9QIyCzQvrtGZklVbdCoyb7dls= go.opentelemetry.io/otel/log v0.13.0/go.mod h1:INKfG4k1O9CL25BaM1qLe0zIedOpvlS5Z7XgSbmN83E= go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= @@ -760,10 +770,11 @@ go.opentelemetry.io/otel/sdk/log/logtest v0.13.0 h1:9yio6AFZ3QD9j9oqshV1Ibm9gPLl go.opentelemetry.io/otel/sdk/log/logtest v0.13.0/go.mod h1:QOGiAJHl+fob8Nu85ifXfuQYmJTFAvcrxL6w5/tu168= go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs= go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= -go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= -go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= +go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -805,6 +816,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= @@ -853,6 +865,7 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= @@ -916,6 +929,7 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= @@ -928,6 +942,7 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= @@ -988,8 +1003,8 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ= google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= diff --git a/internal/testutils/signer.go b/internal/testutils/signer.go new file mode 100644 index 000000000..a54b8e2ad --- /dev/null +++ b/internal/testutils/signer.go @@ -0,0 +1,37 @@ +package testutils + +import ( + "crypto/ecdsa" + "slices" + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +// Note: should only be used for testing purposes +type ECDSASigner struct { + Key *ecdsa.PrivateKey +} + +func NewECDSASigner() *ECDSASigner { + key, _ := crypto.GenerateKey() + return &ECDSASigner{Key: key} +} + +func (s *ECDSASigner) Address() common.Address { + return crypto.PubkeyToAddress(s.Key.PublicKey) +} + +func MakeNewECDSASigners(n int) []ECDSASigner { + signers := make([]ECDSASigner, n) + for i := range n { + signers[i] = *NewECDSASigner() + } + // Signers need to be sorted alphabetically + slices.SortFunc(signers[:], func(a, b ECDSASigner) int { + return strings.Compare(strings.ToLower(a.Address().Hex()), strings.ToLower(b.Address().Hex())) + }) + + return signers +} diff --git a/internal/utils/abi/encoding.go b/internal/utils/abi/encoding.go index 23be4369f..eb16026bf 100644 --- a/internal/utils/abi/encoding.go +++ b/internal/utils/abi/encoding.go @@ -7,10 +7,10 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" ) -// ABIEncode is the equivalent of abi.encode. +// Encode is the equivalent of abi.encode. // We are using this as a global util because the signing process requires encoding / decoding the data. // See a full set of examples https://github.com/ethereum/go-ethereum/blob/420b78659bef661a83c5c442121b13f13288c09f/accounts/abi/packing_test.go#L31 -func ABIEncode(abiStr string, values ...any) ([]byte, error) { +func Encode(abiStr string, values ...any) ([]byte, error) { // Create a dummy method with arguments inDef := fmt.Sprintf(`[{ "name" : "method", "type": "function", "inputs": %s}]`, abiStr) inAbi, err := abi.JSON(strings.NewReader(inDef)) @@ -26,10 +26,10 @@ func ABIEncode(abiStr string, values ...any) ([]byte, error) { return res[4:], nil } -// ABIDecode is the equivalent of abi.decode. +// Decode is the equivalent of abi.decode. // We are using this as a global util because the signing process requires encoding / decoding the data. // See a full set of examples https://github.com/ethereum/go-ethereum/blob/420b78659bef661a83c5c442121b13f13288c09f/accounts/abi/packing_test.go#L31 -func ABIDecode(abiStr string, data []byte) ([]any, error) { +func Decode(abiStr string, data []byte) ([]any, error) { inDef := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, abiStr) inAbi, err := abi.JSON(strings.NewReader(inDef)) if err != nil { diff --git a/internal/utils/abi/encoding_test.go b/internal/utils/abi/encoding_test.go index fbd6111ed..03f208797 100644 --- a/internal/utils/abi/encoding_test.go +++ b/internal/utils/abi/encoding_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" ) -func Test_ABIEncode(t *testing.T) { +func TestEncode(t *testing.T) { t.Parallel() tests := []struct { @@ -59,7 +59,7 @@ func Test_ABIEncode(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - got, err := ABIEncode(tt.giveABI, tt.giveValues...) + got, err := Encode(tt.giveABI, tt.giveValues...) if tt.wantError { require.Error(t, err) @@ -74,7 +74,7 @@ func Test_ABIEncode(t *testing.T) { } } -func Test_ABIDecode(t *testing.T) { +func TestDecode(t *testing.T) { t.Parallel() tests := []struct { @@ -128,7 +128,7 @@ func Test_ABIDecode(t *testing.T) { data, err := hex.DecodeString(tt.giveData) require.NoError(t, err) - got, err := ABIDecode(tt.giveABI, data) + got, err := Decode(tt.giveABI, data) if tt.wantError { require.Error(t, err) diff --git a/internal/utils/safecast/safecast.go b/internal/utils/safecast/safecast.go index d8916c999..6a2bc5bf3 100644 --- a/internal/utils/safecast/safecast.go +++ b/internal/utils/safecast/safecast.go @@ -1,5 +1,4 @@ // Package safecast implements functions to safely cast types to avoid panics - package safecast import ( diff --git a/internal/utils/safecast/safecast_test.go b/internal/utils/safecast/safecast_test.go index 79e2df9a4..d42be63c9 100644 --- a/internal/utils/safecast/safecast_test.go +++ b/internal/utils/safecast/safecast_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" ) -func Test_IntToUint8(t *testing.T) { +func TestIntToUint8(t *testing.T) { t.Parallel() tests := []struct { @@ -38,7 +38,7 @@ func Test_IntToUint8(t *testing.T) { } } -func Test_IntToUint32(t *testing.T) { +func TestIntToUint32(t *testing.T) { t.Parallel() tests := []struct { @@ -68,7 +68,7 @@ func Test_IntToUint32(t *testing.T) { } } -func Test_Uint64ToUint8(t *testing.T) { +func TestUint64ToUint8(t *testing.T) { t.Parallel() tests := []struct { @@ -97,7 +97,7 @@ func Test_Uint64ToUint8(t *testing.T) { } } -func Test_UInt64ToUint32(t *testing.T) { +func TestUInt64ToUint32(t *testing.T) { t.Parallel() tests := []struct { @@ -126,7 +126,7 @@ func Test_UInt64ToUint32(t *testing.T) { } } -func Test_Int64ToUint32(t *testing.T) { +func TestInt64ToUint32(t *testing.T) { t.Parallel() tests := []struct { @@ -155,7 +155,7 @@ func Test_Int64ToUint32(t *testing.T) { } } -func Test_Uint64ToInt64(t *testing.T) { +func TestUint64ToInt64(t *testing.T) { t.Parallel() tests := []struct { @@ -188,7 +188,7 @@ func Test_Uint64ToInt64(t *testing.T) { } } -func Test_Int64ToUint64(t *testing.T) { +func TestInt64ToUint64(t *testing.T) { t.Parallel() tests := []struct { @@ -221,7 +221,7 @@ func Test_Int64ToUint64(t *testing.T) { } } -func Test_Float64ToUint64(t *testing.T) { +func TestFloat64ToUint64(t *testing.T) { t.Parallel() tests := []struct { diff --git a/proposal.go b/proposal.go index 83d27d803..6768d695b 100644 --- a/proposal.go +++ b/proposal.go @@ -185,11 +185,7 @@ func (p *Proposal) Validate() error { } } - if err := proposalValidateBasic(*p); err != nil { - return err - } - - return nil + return proposalValidateBasic(*p) } // UseSimulatedBackend indicates whether the proposal should be run against a simulated backend. @@ -286,7 +282,7 @@ func (p *Proposal) SigningMessage() (common.Hash, error) { if err != nil { return common.Hash{}, err } - msg, err := abi.ABIEncode(SignMsgABI, tree.Root, p.ValidUntil) + msg, err := abi.Encode(SignMsgABI, tree.Root, p.ValidUntil) if err != nil { return [32]byte{}, err } diff --git a/proposal_test.go b/proposal_test.go index 9b75186da..4a91eda4e 100644 --- a/proposal_test.go +++ b/proposal_test.go @@ -50,7 +50,7 @@ var ( }` ) -func Test_BaseProposal_AppendSignature(t *testing.T) { +func TestBaseProposal_AppendSignature(t *testing.T) { t.Parallel() signature := types.Signature{} @@ -64,7 +64,7 @@ func Test_BaseProposal_AppendSignature(t *testing.T) { assert.Equal(t, []types.Signature{signature}, proposal.Signatures) } -func Test_BaseProposal_GetChainMetadata(t *testing.T) { +func TestBaseProposal_GetChainMetadata(t *testing.T) { t.Parallel() chainMetadata := map[types.ChainSelector]types.ChainMetadata{ @@ -78,7 +78,7 @@ func Test_BaseProposal_GetChainMetadata(t *testing.T) { assert.Equal(t, chainMetadata, proposal.ChainMetadatas()) } -func Test_BaseProposal_SetChainMetadata(t *testing.T) { +func TestBaseProposal_SetChainMetadata(t *testing.T) { t.Parallel() proposal := BaseProposal{ @@ -98,7 +98,7 @@ func Test_BaseProposal_SetChainMetadata(t *testing.T) { assert.Empty(t, proposal.ChainMetadata[chaintest.Chain1Selector].MCMAddress) } -func Test_NewProposal(t *testing.T) { +func TestNewProposal(t *testing.T) { t.Parallel() tests := []struct { @@ -231,7 +231,7 @@ func Test_NewProposal(t *testing.T) { } } -func Test_WriteProposal(t *testing.T) { +func TestWriteProposal(t *testing.T) { t.Parallel() tests := []struct { @@ -380,7 +380,7 @@ func TestLoadProposal(t *testing.T) { }) } -func Test_Proposal_Validate(t *testing.T) { +func TestProposalValidate(t *testing.T) { t.Parallel() tests := []struct { @@ -540,7 +540,7 @@ func Test_Proposal_Validate(t *testing.T) { } } -func Test_Proposal_GetEncoders(t *testing.T) { +func TestProposal_GetEncoders(t *testing.T) { t.Parallel() tests := []struct { @@ -620,7 +620,7 @@ func Test_Proposal_GetEncoders(t *testing.T) { } } -func Test_Proposal_UseSimulatedBackend(t *testing.T) { +func TestProposal_UseSimulatedBackend(t *testing.T) { t.Parallel() proposal := Proposal{ @@ -633,7 +633,7 @@ func Test_Proposal_UseSimulatedBackend(t *testing.T) { assert.True(t, proposal.useSimulatedBackend) } -func Test_Proposal_ChainSelectors(t *testing.T) { +func TestProposal_ChainSelectors(t *testing.T) { t.Parallel() builder := NewProposalBuilder() builder.SetVersion("v1"). @@ -663,7 +663,7 @@ func Test_Proposal_ChainSelectors(t *testing.T) { assert.Equal(t, want, proposal.ChainSelectors()) } -func Test_Proposal_MerkleTree(t *testing.T) { +func TestProposal_MerkleTree(t *testing.T) { t.Parallel() tests := []struct { @@ -775,7 +775,7 @@ func Test_Proposal_MerkleTree(t *testing.T) { } } -func Test_Proposal_TransactionCounts(t *testing.T) { +func TestProposal_TransactionCounts(t *testing.T) { t.Parallel() builder := NewProposalBuilder() builder.SetVersion("v1"). @@ -818,7 +818,7 @@ func Test_Proposal_TransactionCounts(t *testing.T) { }, got) } -func Test_Proposal_Decode(t *testing.T) { +func TestProposal_Decode(t *testing.T) { t.Parallel() // Get ABI @@ -965,7 +965,7 @@ func Test_Proposal_Decode(t *testing.T) { } } -func Test_Proposal_TransactionNonces(t *testing.T) { +func TestProposal_TransactionNonces(t *testing.T) { t.Parallel() tests := []struct { diff --git a/sdk/aptos/configurer.go b/sdk/aptos/configurer.go index 243a522bb..b54c5a39c 100644 --- a/sdk/aptos/configurer.go +++ b/sdk/aptos/configurer.go @@ -4,8 +4,10 @@ import ( "context" "fmt" - "github.com/aptos-labs/aptos-go-sdk" chain_selectors "github.com/smartcontractkit/chain-selectors" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" diff --git a/sdk/aptos/decoded_operation.go b/sdk/aptos/decoded_operation.go index 933a599e4..375f7ae18 100644 --- a/sdk/aptos/decoded_operation.go +++ b/sdk/aptos/decoded_operation.go @@ -2,6 +2,7 @@ package aptos import ( "encoding/json" + "errors" "fmt" "github.com/smartcontractkit/mcms/sdk" @@ -20,7 +21,7 @@ var _ sdk.DecodedOperation = &DecodedOperation{} func NewDecodedOperation(packageName, moduleName, functionName string, inputKeys []string, inputArgs []any) (*DecodedOperation, error) { if len(inputKeys) != len(inputArgs) { - return nil, fmt.Errorf("input keys and input args must have the same length") + return nil, errors.New("input keys and input args must have the same length") } return &DecodedOperation{ diff --git a/sdk/aptos/decoder.go b/sdk/aptos/decoder.go index 6b3236bf3..248d24243 100644 --- a/sdk/aptos/decoder.go +++ b/sdk/aptos/decoder.go @@ -4,12 +4,13 @@ import ( "encoding/json" "fmt" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" "github.com/smartcontractkit/chainlink-aptos/relayer/txm" - - "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/types" ) type Decoder struct{} diff --git a/sdk/aptos/encoder.go b/sdk/aptos/encoder.go index d8564063b..4caed209f 100644 --- a/sdk/aptos/encoder.go +++ b/sdk/aptos/encoder.go @@ -55,12 +55,12 @@ func (e *Encoder) HashOperation(opCount uint32, metadata types.ChainMetadata, op return common.Hash{}, fmt.Errorf("failed to parse To address %q: %w", op.Transaction.To, err) } additionalFields := AdditionalFields{} - if err := json.Unmarshal(op.Transaction.AdditionalFields, &additionalFields); err != nil { + if err = json.Unmarshal(op.Transaction.AdditionalFields, &additionalFields); err != nil { return common.Hash{}, fmt.Errorf("failed to unmarshal additional fields: %w", err) } var additionalFieldsMetadata AdditionalFieldsMetadata if len(metadata.AdditionalFields) > 0 { - if err := json.Unmarshal(metadata.AdditionalFields, &additionalFieldsMetadata); err != nil { + if err = json.Unmarshal(metadata.AdditionalFields, &additionalFieldsMetadata); err != nil { return common.Hash{}, fmt.Errorf("failed to unmarshal additional fields metadata: %w", err) } } diff --git a/sdk/aptos/inspector.go b/sdk/aptos/inspector.go index 55a435c20..81fdcf3f8 100644 --- a/sdk/aptos/inspector.go +++ b/sdk/aptos/inspector.go @@ -4,12 +4,14 @@ import ( "context" "fmt" - "github.com/aptos-labs/aptos-go-sdk" "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/types" + + "github.com/aptos-labs/aptos-go-sdk" + + "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" ) var _ sdk.Inspector = &Inspector{} diff --git a/sdk/aptos/timelock_converter.go b/sdk/aptos/timelock_converter.go index 4770fa49c..4c2aa1190 100644 --- a/sdk/aptos/timelock_converter.go +++ b/sdk/aptos/timelock_converter.go @@ -5,15 +5,17 @@ import ( "encoding/json" "fmt" - "github.com/aptos-labs/aptos-go-sdk" - "github.com/aptos-labs/aptos-go-sdk/bcs" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - "github.com/smartcontractkit/chainlink-aptos/bindings/bind" - "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/types" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/bcs" + + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" + "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" ) var _ sdk.TimelockConverter = (*TimelockConverter)(nil) diff --git a/sdk/aptos/timelock_converter_test.go b/sdk/aptos/timelock_converter_test.go index c65042cb0..fbb63ba7f 100644 --- a/sdk/aptos/timelock_converter_test.go +++ b/sdk/aptos/timelock_converter_test.go @@ -7,18 +7,22 @@ import ( "testing" "time" - "github.com/aptos-labs/aptos-go-sdk" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-aptos/bindings/bind" - "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms/internal/testutils/chaintest" + "github.com/smartcontractkit/mcms/types" + + "github.com/ethereum/go-ethereum/common" + + "github.com/aptos-labs/aptos-go-sdk" + + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" + "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + mock_mcms "github.com/smartcontractkit/mcms/sdk/aptos/mocks/mcms" mock_module_mcms "github.com/smartcontractkit/mcms/sdk/aptos/mocks/mcms/mcms" - "github.com/smartcontractkit/mcms/types" ) func TestNewTimelockConverter(t *testing.T) { diff --git a/sdk/aptos/timelock_executor.go b/sdk/aptos/timelock_executor.go index 588c956db..2464b43f8 100644 --- a/sdk/aptos/timelock_executor.go +++ b/sdk/aptos/timelock_executor.go @@ -5,15 +5,17 @@ import ( "encoding/json" "fmt" - "github.com/aptos-labs/aptos-go-sdk" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-aptos/bindings/bind" - "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/types" + "github.com/ethereum/go-ethereum/common" + + "github.com/aptos-labs/aptos-go-sdk" + + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" + "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" ) var _ sdk.TimelockExecutor = (*TimelockExecutor)(nil) diff --git a/sdk/aptos/timelock_executor_test.go b/sdk/aptos/timelock_executor_test.go index 54b1a3b87..5c5006eb5 100644 --- a/sdk/aptos/timelock_executor_test.go +++ b/sdk/aptos/timelock_executor_test.go @@ -6,19 +6,24 @@ import ( "fmt" "testing" - "github.com/aptos-labs/aptos-go-sdk" - "github.com/aptos-labs/aptos-go-sdk/api" - "github.com/ethereum/go-ethereum/common" - cselectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/mcms/internal/testutils/chaintest" + "github.com/smartcontractkit/mcms/types" + + "github.com/ethereum/go-ethereum/common" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/api" + + "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + mock_aptossdk "github.com/smartcontractkit/mcms/sdk/aptos/mocks/aptos" mock_mcms "github.com/smartcontractkit/mcms/sdk/aptos/mocks/mcms" mock_module_mcms "github.com/smartcontractkit/mcms/sdk/aptos/mocks/mcms/mcms" - "github.com/smartcontractkit/mcms/types" ) func TestNewTimelockExecutor(t *testing.T) { diff --git a/sdk/aptos/timelock_inspector.go b/sdk/aptos/timelock_inspector.go index 1bbfb629e..350436f88 100644 --- a/sdk/aptos/timelock_inspector.go +++ b/sdk/aptos/timelock_inspector.go @@ -5,10 +5,11 @@ import ( "errors" "fmt" + "github.com/smartcontractkit/mcms/sdk" + "github.com/aptos-labs/aptos-go-sdk" - "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" - "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" ) var _ sdk.TimelockInspector = (*TimelockInspector)(nil) diff --git a/sdk/aptos/timelock_inspector_test.go b/sdk/aptos/timelock_inspector_test.go index 5eaa301d8..7b5cc759e 100644 --- a/sdk/aptos/timelock_inspector_test.go +++ b/sdk/aptos/timelock_inspector_test.go @@ -5,12 +5,14 @@ import ( "fmt" "testing" - "github.com/aptos-labs/aptos-go-sdk" - "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/aptos-labs/aptos-go-sdk" + + "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + mock_aptossdk "github.com/smartcontractkit/mcms/sdk/aptos/mocks/aptos" mock_mcms "github.com/smartcontractkit/mcms/sdk/aptos/mocks/mcms" mock_module_mcms "github.com/smartcontractkit/mcms/sdk/aptos/mocks/mcms/mcms" diff --git a/sdk/aptos/transaction.go b/sdk/aptos/transaction.go index 5a9112720..2d5080b7e 100644 --- a/sdk/aptos/transaction.go +++ b/sdk/aptos/transaction.go @@ -17,11 +17,7 @@ func ValidateAdditionalFields(additionalFields json.RawMessage) error { return fmt.Errorf("failed to unmarshal Aptos additional fields: %w", err) } - if err := fields.Validate(); err != nil { - return err - } - - return nil + return fields.Validate() } type AdditionalFields struct { diff --git a/sdk/errors/errors.go b/sdk/errors/errors.go index ed417f9ac..89fa1d4fe 100644 --- a/sdk/errors/errors.go +++ b/sdk/errors/errors.go @@ -37,7 +37,7 @@ type InvalidTimelockOperationError struct { // Error returns the error message. func (e *InvalidTimelockOperationError) Error() string { - return fmt.Sprintf("invalid timelock operation: %s", e.ReceivedTimelockOperation) + return "invalid timelock operation: " + e.ReceivedTimelockOperation } func NewInvalidTimelockOperationError(op string) *InvalidTimelockOperationError { diff --git a/sdk/evm/bindings/abigen.go b/sdk/evm/bindings/abigen.go index 31ad09ff7..ff0973438 100644 --- a/sdk/evm/bindings/abigen.go +++ b/sdk/evm/bindings/abigen.go @@ -2,6 +2,7 @@ package bindings import ( "bytes" + "context" "fmt" "go/ast" "go/format" @@ -37,7 +38,7 @@ type AbigenArgs struct { // // Check whether native abigen is installed, and has correct version func Abigen(a AbigenArgs) { - abigenPackagePath := fmt.Sprintf("github.com/ethereum/go-ethereum/cmd/abigen@v%s", abigenVersion) + abigenPackagePath := "github.com/ethereum/go-ethereum/cmd/abigen@v" + abigenVersion args := []string{ "run", abigenPackagePath, @@ -47,7 +48,7 @@ func Abigen(a AbigenArgs) { "--out", a.Out, "--type", a.Type, } - buildCommand := exec.Command("go", args...) + buildCommand := exec.CommandContext(context.Background(), "go", args...) var buildResponse bytes.Buffer buildCommand.Stderr = &buildResponse if err := buildCommand.Run(); err != nil { @@ -366,6 +367,7 @@ func writeAdditionalMethods(contractName string, logNames []string, abi abi.ABI, if len(logNames) > 0 { var logSwitchBody string for _, logName := range logNames { + //nolint:perfsprint // allow fmt.Sprintf in loop logSwitchBody += fmt.Sprintf(`case _%v.abi.Events["%v"].ID: return _%v.Parse%v(log) `, contractName, logName, contractName, logName) diff --git a/sdk/evm/bindings/generate/wrap.go b/sdk/evm/bindings/generate/wrap.go index b1bac25f4..f830f2bc7 100644 --- a/sdk/evm/bindings/generate/wrap.go +++ b/sdk/evm/bindings/generate/wrap.go @@ -13,7 +13,7 @@ func main() { className := os.Args[3] pkgName := os.Args[4] fmt.Println("Generating", className, "contract wrapper") - out := fmt.Sprintf("%s.go", className) + out := className + ".go" bindings.Abigen(bindings.AbigenArgs{ Bin: binPath, ABI: abiPath, Out: out, Type: className, Pkg: pkgName, diff --git a/sdk/evm/config_transformer.go b/sdk/evm/config_transformer.go index 78a4d3870..bffec74fb 100644 --- a/sdk/evm/config_transformer.go +++ b/sdk/evm/config_transformer.go @@ -88,7 +88,7 @@ func (e *ConfigTransformer) ToChainConfig( Group: signerGroups[i], Index: idx, } - idx += 1 + idx++ } return bindings.ManyChainMultiSigConfig{ diff --git a/sdk/evm/config_transformer_test.go b/sdk/evm/config_transformer_test.go index 19556d956..9bb20a512 100644 --- a/sdk/evm/config_transformer_test.go +++ b/sdk/evm/config_transformer_test.go @@ -12,7 +12,7 @@ import ( "github.com/smartcontractkit/mcms/types" ) -func Test_ConfigTransformer_ToConfig(t *testing.T) { +func TestConfigTransformer_ToConfig(t *testing.T) { t.Parallel() var ( @@ -160,7 +160,7 @@ func Test_ConfigTransformer_ToConfig(t *testing.T) { } } -func Test_SetConfigInputs(t *testing.T) { +func TestSetConfigInputs(t *testing.T) { t.Parallel() var ( diff --git a/sdk/evm/decoded_operation.go b/sdk/evm/decoded_operation.go index 9974901e5..1d8e0e3d9 100644 --- a/sdk/evm/decoded_operation.go +++ b/sdk/evm/decoded_operation.go @@ -2,7 +2,7 @@ package evm import ( "encoding/json" - "fmt" + "errors" "github.com/smartcontractkit/mcms/sdk" ) @@ -17,7 +17,7 @@ var _ sdk.DecodedOperation = &DecodedOperation{} func NewDecodedOperation(functionName string, inputKeys []string, inputArgs []any) (*DecodedOperation, error) { if len(inputKeys) != len(inputArgs) { - return nil, fmt.Errorf("input keys and input args must have the same length") + return nil, errors.New("input keys and input args must have the same length") } return &DecodedOperation{ diff --git a/sdk/evm/encoder.go b/sdk/evm/encoder.go index 8d97e4b65..778baacea 100644 --- a/sdk/evm/encoder.go +++ b/sdk/evm/encoder.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - abiUtils "github.com/smartcontractkit/mcms/internal/utils/abi" + "github.com/smartcontractkit/mcms/internal/utils/abi" "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/sdk/evm/bindings" "github.com/smartcontractkit/mcms/types" @@ -62,8 +62,8 @@ func (e *Encoder) HashOperation( return common.Hash{}, err } - abi := `[{"type":"bytes32"},{"type":"tuple","components":[{"name":"chainId","type":"uint256"},{"name":"multiSig","type":"address"},{"name":"nonce","type":"uint40"},{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"}]}]` - encoded, err := abiUtils.ABIEncode(abi, mcmDomainSeparatorOp, bindOp) + _abi := `[{"type":"bytes32"},{"type":"tuple","components":[{"name":"chainId","type":"uint256"},{"name":"multiSig","type":"address"},{"name":"nonce","type":"uint40"},{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"}]}]` + encoded, err := abi.Encode(_abi, mcmDomainSeparatorOp, bindOp) if err != nil { return common.Hash{}, err } @@ -79,8 +79,8 @@ func (e *Encoder) HashMetadata(metadata types.ChainMetadata) (common.Hash, error return common.Hash{}, err } - abi := `[{"type":"bytes32"},{"type":"tuple","components":[{"name":"chainId","type":"uint256"},{"name":"multiSig","type":"address"},{"name":"preOpCount","type":"uint40"},{"name":"postOpCount","type":"uint40"},{"name":"overridePreviousRoot","type":"bool"}]}]` - encoded, err := abiUtils.ABIEncode(abi, mcmDomainSeparatorMetadata, bindMeta) + _abi := `[{"type":"bytes32"},{"type":"tuple","components":[{"name":"chainId","type":"uint256"},{"name":"multiSig","type":"address"},{"name":"preOpCount","type":"uint40"},{"name":"postOpCount","type":"uint40"},{"name":"overridePreviousRoot","type":"bool"}]}]` + encoded, err := abi.Encode(_abi, mcmDomainSeparatorMetadata, bindMeta) if err != nil { return common.Hash{}, err } @@ -102,7 +102,7 @@ func (e *Encoder) ToGethOperation( // Unmarshal the AdditionalFields from the operation var additionalFields AdditionalFields - if err := json.Unmarshal(op.Transaction.AdditionalFields, &additionalFields); err != nil { + if err = json.Unmarshal(op.Transaction.AdditionalFields, &additionalFields); err != nil { return bindings.ManyChainMultiSigOp{}, err } diff --git a/sdk/evm/encoder_test.go b/sdk/evm/encoder_test.go index ec9ca7be1..0583fcee8 100644 --- a/sdk/evm/encoder_test.go +++ b/sdk/evm/encoder_test.go @@ -4,11 +4,13 @@ import ( "math/big" "testing" - "github.com/ethereum/go-ethereum/common" - cselectors "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/mcms/internal/testutils/chaintest" "github.com/smartcontractkit/mcms/sdk/evm/bindings" "github.com/smartcontractkit/mcms/types" diff --git a/sdk/evm/executor.go b/sdk/evm/executor.go index 3d0d0cec0..c9318cf6b 100644 --- a/sdk/evm/executor.go +++ b/sdk/evm/executor.go @@ -41,7 +41,7 @@ func (e *Executor) ExecuteOperation( op types.Operation, ) (types.TransactionResult, error) { if e.Encoder == nil { - return types.TransactionResult{}, errors.New("Executor was created without an encoder") + return types.TransactionResult{}, errors.New("failed to create sdk.Executor - encoder (sdk.Encoder) is nil") } bindOp, err := e.ToGethOperation(nonce, metadata, op) @@ -93,7 +93,7 @@ func (e *Executor) SetRoot( sortedSignatures []types.Signature, ) (types.TransactionResult, error) { if e.Encoder == nil { - return types.TransactionResult{}, errors.New("Executor was created without an encoder") + return types.TransactionResult{}, errors.New("failed to create sdk.Executor - encoder (sdk.Encoder) is nil") } bindMeta, err := e.ToGethRootMetadata(metadata) diff --git a/sdk/evm/executor_test.go b/sdk/evm/executor_test.go index 431425da2..828a8e22a 100644 --- a/sdk/evm/executor_test.go +++ b/sdk/evm/executor_test.go @@ -4,16 +4,15 @@ import ( "context" "encoding/json" "errors" - "fmt" "math/big" "testing" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" evmTypes "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" chain_selectors "github.com/smartcontractkit/chain-selectors" @@ -39,11 +38,11 @@ func TestNewExecutor(t *testing.T) { executor := evm.NewExecutor(mockEncoder, mockClient, mockAuth) - assert.Equal(t, mockEncoder, executor.Encoder, "expected Encoder to be set correctly") - assert.NotNil(t, executor.Inspector, "expected Inspector to be initialized") + require.Equal(t, mockEncoder, executor.Encoder, "expected Encoder to be set correctly") + require.NotNil(t, executor.Inspector, "expected Inspector to be initialized") } -func TestExecutorExecuteOperation(t *testing.T) { +func TestExecutor_ExecuteOperation(t *testing.T) { t.Parallel() ctx := context.Background() @@ -162,7 +161,7 @@ func TestExecutorExecuteOperation(t *testing.T) { encoder: nil, mockSetup: func(m *evm_mocks.ContractDeployBackend) {}, wantTxHash: "", - wantErr: errors.New("Executor was created without an encoder"), + wantErr: errors.New("failed to create sdk.Executor - encoder (sdk.Encoder) is nil"), }, { name: "failure in geth operation conversion due to invalid chain ID", @@ -195,7 +194,6 @@ func TestExecutorExecuteOperation(t *testing.T) { executor := evm.NewExecutor(tt.encoder, client, tt.auth) tx, err := executor.ExecuteOperation(ctx, tt.metadata, tt.nonce, tt.proof, tt.op) - require.Equal(t, tt.wantTxHash, tx.Hash) if tt.wantErr != nil { require.Error(t, err) // When error occurs after tx sending, check for ExecutionError with transaction data @@ -212,12 +210,13 @@ func TestExecutorExecuteOperation(t *testing.T) { } } else { require.NoError(t, err) + require.Equal(t, tt.wantTxHash, tx.Hash) } }) } } -func TestExecutorExecuteOperationWithEIP1559GasFees(t *testing.T) { +func TestExecutor_ExecuteOperationWithEIP1559GasFees(t *testing.T) { t.Parallel() ctx := context.Background() @@ -282,7 +281,7 @@ func TestExecutorExecuteOperationWithEIP1559GasFees(t *testing.T) { require.Equal(t, uint8(2), execErr.Transaction.Type(), "transaction should be EIP-1559 type") } -func TestExecutorSetRootWithEIP1559GasFees(t *testing.T) { +func TestExecutor_SetRootWithEIP1559GasFees(t *testing.T) { t.Parallel() ctx := context.Background() @@ -342,7 +341,7 @@ func TestExecutorSetRootWithEIP1559GasFees(t *testing.T) { require.Equal(t, uint8(2), execErr.Transaction.Type(), "transaction should be EIP-1559 type") } -func TestExecutorExecuteOperationWithLegacyGasPrice(t *testing.T) { +func TestExecutor_ExecuteOperationWithLegacyGasPrice(t *testing.T) { t.Parallel() ctx := context.Background() @@ -406,7 +405,7 @@ func TestExecutorExecuteOperationWithLegacyGasPrice(t *testing.T) { require.Equal(t, uint8(0), execErr.Transaction.Type(), "transaction should be legacy type") } -func TestExecutorSetRootWithLegacyGasPrice(t *testing.T) { +func TestExecutor_SetRootWithLegacyGasPrice(t *testing.T) { t.Parallel() ctx := context.Background() @@ -465,7 +464,7 @@ func TestExecutorSetRootWithLegacyGasPrice(t *testing.T) { require.Equal(t, uint8(0), execErr.Transaction.Type(), "transaction should be legacy type") } -func TestExecutorExecuteOperationRBACTimelockUnderlyingRevert(t *testing.T) { +func TestExecutor_ExecuteOperationRBACTimelockUnderlyingRevert(t *testing.T) { t.Parallel() ctx := context.Background() @@ -503,7 +502,7 @@ func TestExecutorExecuteOperationRBACTimelockUnderlyingRevert(t *testing.T) { client := evm_mocks.NewContractDeployBackend(t) // Mock the Execute call to return RBACTimelock error client.EXPECT().SendTransaction(mock.Anything, mock.Anything). - Return(fmt.Errorf("contract error: error -`CallReverted` args [[8 195 121 160 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 82 66 65 67 84 105 109 101 108 111 99 107 58 32 117 110 100 101 114 108 121 105 110 103 32 116 114 97 110 115 97 99 116 105 111 110 32 114 101 118 101 114 116 101 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]")) + Return(errors.New("contract error: error -`CallReverted` args [[8 195 121 160 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 82 66 65 67 84 105 109 101 108 111 99 107 58 32 117 110 100 101 114 108 121 105 110 103 32 116 114 97 110 115 97 99 116 105 111 110 32 114 101 118 101 114 116 101 100 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]")) client.EXPECT().HeaderByNumber(mock.Anything, mock.Anything). Return(&evmTypes.Header{}, nil).Maybe() client.EXPECT().SuggestGasPrice(mock.Anything). @@ -517,7 +516,7 @@ func TestExecutorExecuteOperationRBACTimelockUnderlyingRevert(t *testing.T) { // Mock CallContract to return the underlying revert reason client.EXPECT().CallContract(mock.Anything, mock.Anything, mock.Anything). - Return(nil, fmt.Errorf("execution reverted: 0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a496e73756666696369656e742062616c616e636520746f2073656e6400000000000000000000000000000000000000000000000000000000")). + Return(nil, errors.New("execution reverted: 0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a496e73756666696369656e742062616c616e636520746f2073656e6400000000000000000000000000000000000000000000000000000000")). Maybe() executor := evm.NewExecutor(encoder, client, auth) @@ -654,7 +653,7 @@ func TestExecutor_SetRoot(t *testing.T) { encoder: nil, mockSetup: func(m *evm_mocks.ContractDeployBackend) {}, wantTxHash: "", - wantErr: errors.New("Executor was created without an encoder"), + wantErr: errors.New("failed to create sdk.Executor - encoder (sdk.Encoder) is nil"), }, { name: "failure in geth operation conversion due to invalid chain ID", diff --git a/sdk/evm/inspector_test.go b/sdk/evm/inspector_test.go index a05c7bb7e..319342fda 100644 --- a/sdk/evm/inspector_test.go +++ b/sdk/evm/inspector_test.go @@ -3,13 +3,13 @@ package evm import ( "context" "errors" - "fmt" "math/big" "testing" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -70,14 +70,14 @@ func TestInspector_GetConfig(t *testing.T) { address: "0x1234567890abcdef1234567890abcdef12345678", mockError: errors.New("CallContract failed"), want: nil, - wantErr: fmt.Errorf("CallContract failed"), + wantErr: errors.New("CallContract failed"), }, { name: "Empty Signers list", address: "0x1234567890abcdef1234567890abcdef12345678", mockResult: bindings.ManyChainMultiSigConfig{Signers: []bindings.ManyChainMultiSigSigner{}, GroupQuorums: [32]uint8{3, 2}, GroupParents: [32]uint8{0, 0}}, want: nil, - wantErr: fmt.Errorf("invalid MCMS config: Quorum must be less than or equal to the number of signers and groups"), + wantErr: errors.New("invalid MCMS config: Quorum must be less than or equal to the number of signers and groups"), }, } @@ -151,7 +151,7 @@ func TestInspector_GetOpCount(t *testing.T) { address: "0x1234567890abcdef1234567890abcdef12345678", mockError: errors.New("CallContract failed"), want: 0, - wantErr: fmt.Errorf("CallContract failed"), + wantErr: errors.New("CallContract failed"), }, } @@ -224,7 +224,7 @@ func TestInspector_GetRoot(t *testing.T) { name: "CallContract error", address: "0x1234567890abcdef1234567890abcdef12345678", mockError: errors.New("CallContract failed"), - wantErr: fmt.Errorf("CallContract failed"), + wantErr: errors.New("CallContract failed"), }, } @@ -305,7 +305,7 @@ func TestInspector_GetRootMetadata(t *testing.T) { name: "CallContract error", address: "0x1234567890abcdef1234567890abcdef12345678", mockError: errors.New("CallContract failed"), - wantErr: fmt.Errorf("CallContract failed"), + wantErr: errors.New("CallContract failed"), }, } diff --git a/sdk/evm/timelock_converter.go b/sdk/evm/timelock_converter.go index 30855f19f..ab412ead5 100644 --- a/sdk/evm/timelock_converter.go +++ b/sdk/evm/timelock_converter.go @@ -8,14 +8,14 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - abiUtils "github.com/smartcontractkit/mcms/internal/utils/abi" + "github.com/smartcontractkit/mcms/internal/utils/abi" "github.com/smartcontractkit/mcms/sdk" sdkerrors "github.com/smartcontractkit/mcms/sdk/errors" "github.com/smartcontractkit/mcms/sdk/evm/bindings" "github.com/smartcontractkit/mcms/types" ) -var ZERO_HASH = common.Hash{} +var ZeroHash = common.Hash{} var _ sdk.TimelockConverter = (*TimelockConverter)(nil) @@ -55,12 +55,12 @@ func (t TimelockConverter) ConvertBatchToChainOperations( tags = append(tags, tx.Tags...) } - abi, errAbi := bindings.RBACTimelockMetaData.GetAbi() + _abi, errAbi := bindings.RBACTimelockMetaData.GetAbi() if errAbi != nil { return []types.Operation{}, common.Hash{}, errAbi } - operationId, errHash := HashOperationBatch(calls, predecessor, salt) + operationID, errHash := HashOperationBatch(calls, predecessor, salt) if errHash != nil { return []types.Operation{}, common.Hash{}, errHash @@ -71,11 +71,11 @@ func (t TimelockConverter) ConvertBatchToChainOperations( var err error switch action { case types.TimelockActionSchedule: - data, err = abi.Pack("scheduleBatch", calls, predecessor, salt, big.NewInt(int64(delay.Seconds()))) + data, err = _abi.Pack("scheduleBatch", calls, predecessor, salt, big.NewInt(int64(delay.Seconds()))) case types.TimelockActionCancel: - data, err = abi.Pack("cancel", operationId) + data, err = _abi.Pack("cancel", operationID) case types.TimelockActionBypass: - data, err = abi.Pack("bypasserExecuteBatch", calls) + data, err = _abi.Pack("bypasserExecuteBatch", calls) default: return []types.Operation{}, common.Hash{}, sdkerrors.NewInvalidTimelockOperationError(string(action)) } @@ -95,14 +95,14 @@ func (t TimelockConverter) ConvertBatchToChainOperations( ), } - return []types.Operation{op}, operationId, nil + return []types.Operation{op}, operationID, nil } // HashOperationBatch replicates the hash calculation from Solidity // TODO: see if there's an easier way to do this using the gethwrappers func HashOperationBatch(calls []bindings.RBACTimelockCall, predecessor, salt [32]byte) (common.Hash, error) { - const abi = `[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Call[]","name":"calls","type":"tuple[]"},{"internalType":"bytes32","name":"predecessor","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"}]` - encoded, err := abiUtils.ABIEncode(abi, calls, predecessor, salt) + const _abi = `[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Call[]","name":"calls","type":"tuple[]"},{"internalType":"bytes32","name":"predecessor","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"}]` + encoded, err := abi.Encode(_abi, calls, predecessor, salt) if err != nil { return common.Hash{}, err } diff --git a/sdk/evm/timelock_converter_test.go b/sdk/evm/timelock_converter_test.go index bc987a73f..ed2277d85 100644 --- a/sdk/evm/timelock_converter_test.go +++ b/sdk/evm/timelock_converter_test.go @@ -6,11 +6,12 @@ import ( "math/big" "testing" - "github.com/ethereum/go-ethereum/common" - cselectors "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/ethereum/go-ethereum/common" + sdkerrors "github.com/smartcontractkit/mcms/sdk/errors" "github.com/smartcontractkit/mcms/types" ) @@ -134,13 +135,14 @@ func TestTimelockConverter_ConvertBatchToChainOperation(t *testing.T) { if tc.expectedError != nil { require.Error(t, err) - assert.IsType(t, tc.expectedError, err) + //nolint:testifylint // Allow IsType for error type checking + require.IsType(t, tc.expectedError, err) } else { require.NoError(t, err) - assert.NotEqual(t, common.Hash{}, operationID) - assert.Len(t, chainOperations, 1) - assert.Equal(t, timelockAddress, chainOperations[0].Transaction.To) - assert.Equal(t, tc.op.ChainSelector, chainOperations[0].ChainSelector) + require.NotEqual(t, common.Hash{}, operationID) + require.Len(t, chainOperations, 1) + require.Equal(t, timelockAddress, chainOperations[0].Transaction.To) + require.Equal(t, tc.op.ChainSelector, chainOperations[0].ChainSelector) } }) } diff --git a/sdk/evm/timelock_executor_test.go b/sdk/evm/timelock_executor_test.go index 1901dad43..9f16abe77 100644 --- a/sdk/evm/timelock_executor_test.go +++ b/sdk/evm/timelock_executor_test.go @@ -3,7 +3,7 @@ package evm import ( "context" "encoding/json" - "fmt" + "errors" "math/big" "testing" @@ -113,11 +113,11 @@ func TestTimelockExecutor_Execute(t *testing.T) { mockSetup: func(m *evm_mocks.ContractDeployBackend) { // Successful tx send m.EXPECT().SendTransaction(mock.Anything, mock.Anything). - Return(fmt.Errorf("error during tx send")) + Return(errors.New("error during tx send")) sharedMockSetup(m) }, wantTxHash: "", - wantErr: fmt.Errorf("execution failed: error during tx send"), + wantErr: errors.New("execution failed: error during tx send"), }, } diff --git a/sdk/evm/timelock_inspector_test.go b/sdk/evm/timelock_inspector_test.go index 0d27dea6c..4db670a15 100644 --- a/sdk/evm/timelock_inspector_test.go +++ b/sdk/evm/timelock_inspector_test.go @@ -241,7 +241,7 @@ func TestTimelockInspector_IsOperation(t *testing.T) { tests := []struct { name string address string - opId [32]byte + opID [32]byte mockError error want bool wantErr error @@ -249,13 +249,13 @@ func TestTimelockInspector_IsOperation(t *testing.T) { { name: "IsOperation success", address: "0x1234567890abcdef1234567890abcdef12345678", - opId: [32]byte{0x01}, + opID: [32]byte{0x01}, want: true, }, { name: "IsOperation call contract failure error", address: "0x1234567890abcdef1234567890abcdef12345678", - opId: [32]byte{0x02}, + opID: [32]byte{0x02}, mockError: errors.New("call to contract failed"), want: false, wantErr: errors.New("call to contract failed"), @@ -289,7 +289,7 @@ func TestTimelockInspector_IsOperation(t *testing.T) { } // Call the `IsOperation` method - got, err := inspector.IsOperation(ctx, tt.address, tt.opId) + got, err := inspector.IsOperation(ctx, tt.address, tt.opID) // Assertions for expected error or successful result if tt.wantErr != nil { @@ -311,7 +311,7 @@ func testIsOperationState( t *testing.T, methodName string, address string, - opId [32]byte, + opID [32]byte, want bool, mockError error, wantErr error, @@ -346,11 +346,11 @@ func testIsOperationState( var got bool switch methodName { case "isOperationPending": - got, err = inspector.IsOperationPending(ctx, address, opId) + got, err = inspector.IsOperationPending(ctx, address, opID) case "isOperationReady": - got, err = inspector.IsOperationReady(ctx, address, opId) + got, err = inspector.IsOperationReady(ctx, address, opID) case "isOperationDone": - got, err = inspector.IsOperationDone(ctx, address, opId) + got, err = inspector.IsOperationDone(ctx, address, opID) default: t.Fatalf("unsupported methodName: %s", methodName) } @@ -375,7 +375,7 @@ func TestTimelockInspector_IsOperationPending(t *testing.T) { tests := []struct { name string address string - opId [32]byte + opID [32]byte want bool mockError error wantErr error @@ -383,13 +383,13 @@ func TestTimelockInspector_IsOperationPending(t *testing.T) { { name: "IsOperationPending success", address: "0x1234567890abcdef1234567890abcdef12345678", - opId: [32]byte{0x01}, + opID: [32]byte{0x01}, want: true, }, { name: "IsOperationPending call contract failure error", address: "0x1234567890abcdef1234567890abcdef12345678", - opId: [32]byte{0x02}, + opID: [32]byte{0x02}, mockError: errors.New("call to contract failed"), want: false, wantErr: errors.New("call to contract failed"), @@ -399,7 +399,7 @@ func TestTimelockInspector_IsOperationPending(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() - testIsOperationState(t, "isOperationPending", tt.address, tt.opId, tt.want, tt.mockError, tt.wantErr) + testIsOperationState(t, "isOperationPending", tt.address, tt.opID, tt.want, tt.mockError, tt.wantErr) }) } } @@ -410,7 +410,7 @@ func TestTimelockInspector_IsOperationReady(t *testing.T) { tests := []struct { name string address string - opId [32]byte + opID [32]byte want bool mockError error wantErr error @@ -418,13 +418,13 @@ func TestTimelockInspector_IsOperationReady(t *testing.T) { { name: "IsOperationReady success", address: "0x1234567890abcdef1234567890abcdef12345678", - opId: [32]byte{0x01}, + opID: [32]byte{0x01}, want: true, }, { name: "IsOperationReady call contract failure error", address: "0x1234567890abcdef1234567890abcdef12345678", - opId: [32]byte{0x02}, + opID: [32]byte{0x02}, mockError: errors.New("call to contract failed"), want: false, wantErr: errors.New("call to contract failed"), @@ -434,7 +434,7 @@ func TestTimelockInspector_IsOperationReady(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() - testIsOperationState(t, "isOperationReady", tt.address, tt.opId, tt.want, tt.mockError, tt.wantErr) + testIsOperationState(t, "isOperationReady", tt.address, tt.opID, tt.want, tt.mockError, tt.wantErr) }) } } @@ -445,7 +445,7 @@ func TestTimelockInspector_IsOperationDone(t *testing.T) { tests := []struct { name string address string - opId [32]byte + opID [32]byte want bool mockError error wantErr error @@ -453,13 +453,13 @@ func TestTimelockInspector_IsOperationDone(t *testing.T) { { name: "IsOperationDone success", address: "0x1234567890abcdef1234567890abcdef12345678", - opId: [32]byte{0x01}, + opID: [32]byte{0x01}, want: true, }, { name: "IsOperationDone call contract failure error", address: "0x1234567890abcdef1234567890abcdef12345678", - opId: [32]byte{0x02}, + opID: [32]byte{0x02}, mockError: errors.New("call to contract failed"), want: false, wantErr: errors.New("call to contract failed"), @@ -469,7 +469,7 @@ func TestTimelockInspector_IsOperationDone(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() - testIsOperationState(t, "isOperationDone", tt.address, tt.opId, tt.want, tt.mockError, tt.wantErr) + testIsOperationState(t, "isOperationDone", tt.address, tt.opID, tt.want, tt.mockError, tt.wantErr) }) } } diff --git a/sdk/evm/transaction.go b/sdk/evm/transaction.go index f4b2bad3f..dad5f7ca0 100644 --- a/sdk/evm/transaction.go +++ b/sdk/evm/transaction.go @@ -20,11 +20,7 @@ func ValidateAdditionalFields(additionalFields json.RawMessage) error { } } - if err := fields.Validate(); err != nil { - return err - } - - return nil + return fields.Validate() } type AdditionalFields struct { diff --git a/sdk/evm/transaction_test.go b/sdk/evm/transaction_test.go index a9e1709b9..e455ac15f 100644 --- a/sdk/evm/transaction_test.go +++ b/sdk/evm/transaction_test.go @@ -55,7 +55,7 @@ func TestValidateAdditionalFields(t *testing.T) { }) } } -func TestOperationFields_Validate(t *testing.T) { +func TestOperationFieldsValidate(t *testing.T) { t.Parallel() tests := []struct { diff --git a/sdk/evm/utils.go b/sdk/evm/utils.go index 3bb28721b..2fb0928a2 100644 --- a/sdk/evm/utils.go +++ b/sdk/evm/utils.go @@ -1,12 +1,15 @@ 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/sdk/evm/bindings" "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" ) const ( diff --git a/sdk/evm/utils_test.go b/sdk/evm/utils_test.go index 64f86f9dc..582bc459b 100644 --- a/sdk/evm/utils_test.go +++ b/sdk/evm/utils_test.go @@ -12,7 +12,7 @@ import ( "github.com/smartcontractkit/mcms/types" ) -func Test_transformHashes(t *testing.T) { +func TestTransformHashes(t *testing.T) { t.Parallel() hashes := []common.Hash{ @@ -39,7 +39,7 @@ func Test_transformHashes(t *testing.T) { assert.Equal(t, want, got) } -func Test_transformSignatures(t *testing.T) { +func TestTransformSignatures(t *testing.T) { t.Parallel() got := transformSignatures([]types.Signature{ @@ -66,7 +66,7 @@ func Test_transformSignatures(t *testing.T) { }, got) } -func Test_toGethSignature(t *testing.T) { +func TestToGethSignature(t *testing.T) { t.Parallel() tests := []struct { @@ -126,7 +126,7 @@ func Test_toGethSignature(t *testing.T) { } } -func Test_getEVMChainID(t *testing.T) { +func TestGetEVMChainID(t *testing.T) { t.Parallel() tests := []struct { diff --git a/sdk/solana/chain_metadata_test.go b/sdk/solana/chain_metadata_test.go index 5304fa1c1..819e4fb23 100644 --- a/sdk/solana/chain_metadata_test.go +++ b/sdk/solana/chain_metadata_test.go @@ -6,15 +6,20 @@ import ( "errors" "testing" + "github.com/stretchr/testify/require" + + "gotest.tools/v3/assert" + + "github.com/google/go-cmp/cmp" + + "github.com/smartcontractkit/mcms/types" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" - "github.com/google/go-cmp/cmp" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" - "github.com/stretchr/testify/require" - "gotest.tools/v3/assert" "github.com/smartcontractkit/mcms/sdk/solana/mocks" - "github.com/smartcontractkit/mcms/types" ) func TestNewChainMetadataFromTimelock(t *testing.T) { @@ -81,9 +86,9 @@ func TestNewChainMetadataFromTimelock(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - jsonRpc := mocks.NewJSONRPCClient(t) - tt.setupMock(jsonRpc) - client := rpc.NewWithCustomRPCClient(jsonRpc) + jsonRPC := mocks.NewJSONRPCClient(t) + tt.setupMock(jsonRPC) + client := rpc.NewWithCustomRPCClient(jsonRPC) metadata, err := NewChainMetadataFromTimelock( context.Background(), client, diff --git a/sdk/solana/common.go b/sdk/solana/common.go index f0e6d9707..fcb2bdeca 100644 --- a/sdk/solana/common.go +++ b/sdk/solana/common.go @@ -3,16 +3,19 @@ package solana import ( "context" "encoding/binary" + "errors" "fmt" "os" "strconv" "time" "github.com/ethereum/go-ethereum/common" + + "go.uber.org/zap" + "github.com/gagliardetto/solana-go" computebudget "github.com/gagliardetto/solana-go/programs/compute-budget" "github.com/gagliardetto/solana-go/rpc" - "go.uber.org/zap" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" @@ -188,7 +191,7 @@ func sendAndConfirmInstructions( return "", nil, fmt.Errorf("unable to send instruction: %w", err) } if result.Transaction == nil { - return "", nil, fmt.Errorf("nil transaction in instruction result") + return "", nil, errors.New("nil transaction in instruction result") } transaction, err := result.Transaction.GetTransaction() diff --git a/sdk/solana/common_test.go b/sdk/solana/common_test.go index e25a3fa3b..11d5dd83e 100644 --- a/sdk/solana/common_test.go +++ b/sdk/solana/common_test.go @@ -2,21 +2,26 @@ package solana import ( "context" - "fmt" + "errors" "testing" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/mcms/types" + + cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/ethereum/go-ethereum/common" + "github.com/google/go-cmp/cmp" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" - "github.com/google/go-cmp/cmp" - cselectors "github.com/smartcontractkit/chain-selectors" + cpiStubBindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/external_program_cpi_stub" mcmBindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" timelockBindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms/sdk/solana/mocks" - "github.com/smartcontractkit/mcms/types" ) var ( @@ -30,42 +35,42 @@ var ( testRoot = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000") ) -func Test_FindSignerPDA(t *testing.T) { +func TestFindSignerPDA(t *testing.T) { t.Parallel() pda, err := FindSignerPDA(testMCMProgramID, testPDASeed) require.NoError(t, err) require.Empty(t, cmp.Diff(pda, solana.MustPublicKeyFromBase58("62gDM6BRLf2w1yXfmpePUTsuvbeBbu4QqdjV32wcc4UG"))) } -func Test_FindConfigPDA(t *testing.T) { +func TestFindConfigPDA(t *testing.T) { t.Parallel() pda, err := FindConfigPDA(testMCMProgramID, testPDASeed) require.NoError(t, err) require.Empty(t, cmp.Diff(pda, solana.MustPublicKeyFromBase58("CiPYshUKNDV9i4p4MLaqXSRqYWtnMtW6b1aYjh4Lw9nP"))) } -func Test_getConfigSignersPDA(t *testing.T) { +func TestGetConfigSignersPDA(t *testing.T) { t.Parallel() pda, err := FindConfigSignersPDA(testMCMProgramID, testPDASeed) require.NoError(t, err) require.Empty(t, cmp.Diff(pda, solana.MustPublicKeyFromBase58("EZJdMB7TCRcSTP6KMp1HPnzwNtW6wvqKXHLAZh1Jn81w"))) } -func Test_FindRootMetadataPDA(t *testing.T) { +func TestFindRootMetadataPDA(t *testing.T) { t.Parallel() pda, err := FindRootMetadataPDA(testMCMProgramID, testPDASeed) require.NoError(t, err) require.Empty(t, cmp.Diff(pda, solana.MustPublicKeyFromBase58("H45XH8Z1zpcLUHLLQzUwEgB1s3mZQcRvCYfcHriRcMxN"))) } -func Test_FindExpiringRootAndOpCountPDA(t *testing.T) { +func TestFindExpiringRootAndOpCountPDA(t *testing.T) { t.Parallel() pda, err := FindExpiringRootAndOpCountPDA(testMCMProgramID, testPDASeed) require.NoError(t, err) require.Empty(t, cmp.Diff(pda, solana.MustPublicKeyFromBase58("7nh2qGybwNRxL3zKpiSUzk2yc9CjCb5MhrB61B98hYZu"))) } -func Test_FindRootSignaturesPDA(t *testing.T) { +func TestFindRootSignaturesPDA(t *testing.T) { t.Parallel() authority, err := solana.PublicKeyFromBase58("LoCoNsJFuhTkSQjfdDfn3yuwqhSYoPujmviRHVCzsqn") require.NoError(t, err) @@ -75,42 +80,42 @@ func Test_FindRootSignaturesPDA(t *testing.T) { require.Empty(t, cmp.Diff(pda, solana.MustPublicKeyFromBase58("98m4KuqTruBS7oXDm4Kzq43TmF1Lih3J6pHHZ6Lo9hty"))) } -func Test_FindSeenSignedHashesPDA(t *testing.T) { +func TestFindSeenSignedHashesPDA(t *testing.T) { t.Parallel() pda, err := FindSeenSignedHashesPDA(testMCMProgramID, testPDASeed, testRoot, 1735689600) require.NoError(t, err) require.Empty(t, cmp.Diff(pda, solana.MustPublicKeyFromBase58("FxPYSHG9tm35T43zpAuVDdNY8uMPQfaaVBftxVrLyXVq"))) } -func Test_FindTimelockConfigPDA(t *testing.T) { +func TestFindTimelockConfigPDA(t *testing.T) { t.Parallel() pda, err := FindTimelockConfigPDA(testTimelockProgramID, testPDASeed) require.NoError(t, err) require.Empty(t, cmp.Diff(pda, solana.MustPublicKeyFromBase58("GYWcPzXkdzY9DJLcbFs67phqyYzmJxeEKSTtqEoo8oKz"))) } -func Test_FindTimelockOperationPDA(t *testing.T) { +func TestFindTimelockOperationPDA(t *testing.T) { t.Parallel() pda, err := FindTimelockOperationPDA(testTimelockProgramID, testPDASeed, testOpID) require.NoError(t, err) require.Empty(t, cmp.Diff(pda, solana.MustPublicKeyFromBase58("9kmDgWeckKVoW44YEp4MByUJXxxwjjxK52o1HyqSPTru"))) } -func Test_FindTimelockBypasserOperationPDA(t *testing.T) { +func TestFindTimelockBypasserOperationPDA(t *testing.T) { t.Parallel() pda, err := FindTimelockBypasserOperationPDA(testTimelockProgramID, testPDASeed, testOpID) require.NoError(t, err) require.Empty(t, cmp.Diff(pda, solana.MustPublicKeyFromBase58("5mDicsfmjcDDUuaMkrBvWVf9fgDGmA9ahUdebSAM1Aid"))) } -func Test_FindTimelockSignerPDA(t *testing.T) { +func TestFindTimelockSignerPDA(t *testing.T) { t.Parallel() pda, err := FindTimelockSignerPDA(testTimelockProgramID, testPDASeed) require.NoError(t, err) require.Empty(t, cmp.Diff(pda, solana.MustPublicKeyFromBase58("2g4vS5Y9g5FKoBakfNTEQcoyuPxuqgiXhribGxE1Vrsb"))) } -func Test_sendAndConfirm(t *testing.T) { +func TestSendAndConfirm(t *testing.T) { t.Parallel() ctx := context.Background() @@ -183,7 +188,7 @@ func Test_sendAndConfirm(t *testing.T) { setup: func(mockJSONRPCClient *mocks.JSONRPCClient) { mockSolanaTransaction(t, mockJSONRPCClient, 10, 20, "NyH6sKKEbAMjxzG9qLTcwd1yEmv46Z94XmH5Pp9AXJps8EofvpPdUn5bp7rzKnztWmxskBiVRnp4DwaHujhHvFh", - nil, fmt.Errorf("send and confirm error")) + nil, errors.New("send and confirm error")) }, opts: []sendTransactionOption{WithRetries(1)}, wantErr: "unable to send instruction: send and confirm error", @@ -204,7 +209,7 @@ func Test_sendAndConfirm(t *testing.T) { builder: mcmBindings.NewAcceptOwnershipInstruction(testPDASeed, mcmConfigPDA, auth.PublicKey()), setup: func(mockJSONRPCClient *mocks.JSONRPCClient) { txMeta := &rpc.TransactionMeta{ - Err: fmt.Errorf("solana transaction meta error"), + Err: errors.New("solana transaction meta error"), } mockSolanaTransaction(t, mockJSONRPCClient, 10, 20, @@ -243,7 +248,7 @@ func Test_sendAndConfirm(t *testing.T) { type invalidTestInstruction struct{} func (*invalidTestInstruction) ValidateAndBuild() (*mcmBindings.Instruction, error) { - return nil, fmt.Errorf("validate and build error ") + return nil, errors.New("validate and build error ") } func buildTransactionEnvelope(t *testing.T, signature string) *rpc.TransactionResultEnvelope { diff --git a/sdk/solana/config_transformer.go b/sdk/solana/config_transformer.go index 99050589a..ceee25cac 100644 --- a/sdk/solana/config_transformer.go +++ b/sdk/solana/config_transformer.go @@ -2,12 +2,14 @@ package solana import ( "github.com/ethereum/go-ethereum/common" - "github.com/gagliardetto/solana-go" - bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" sdkerrors "github.com/smartcontractkit/mcms/sdk/errors" "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/types" + + "github.com/gagliardetto/solana-go" + + bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" ) type AdditionalConfig struct { @@ -92,7 +94,7 @@ func (e *ConfigTransformer) ToChainConfig(cfg types.Config, solanaConfig Additio Group: signerGroups[i], Index: idx, } - idx += 1 + idx++ } result.Signers = bindSigners // Set group quorums and group parents. diff --git a/sdk/solana/config_transformer_test.go b/sdk/solana/config_transformer_test.go index 7bab48a10..f5cb9d3c2 100644 --- a/sdk/solana/config_transformer_test.go +++ b/sdk/solana/config_transformer_test.go @@ -3,17 +3,19 @@ package solana import ( "testing" + "github.com/stretchr/testify/require" + "gotest.tools/v3/assert" + "github.com/ethereum/go-ethereum/common" "github.com/gagliardetto/solana-go" "github.com/google/go-cmp/cmp" + bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" - "github.com/stretchr/testify/require" - "gotest.tools/v3/assert" "github.com/smartcontractkit/mcms/types" ) -func Test_ConfigTransformer_ToConfig(t *testing.T) { +func TestConfigTransformer_ToConfig(t *testing.T) { t.Parallel() var ( @@ -161,7 +163,7 @@ func Test_ConfigTransformer_ToConfig(t *testing.T) { } } -func Test_ConfigTransformer_ToChainConfig(t *testing.T) { +func TestConfigTransformer_ToChainConfig(t *testing.T) { t.Parallel() var ( diff --git a/sdk/solana/configurer.go b/sdk/solana/configurer.go index 8599317e5..0a94feef6 100644 --- a/sdk/solana/configurer.go +++ b/sdk/solana/configurer.go @@ -4,16 +4,19 @@ import ( "context" "fmt" - evmCommon "github.com/ethereum/go-ethereum/common" - "github.com/gagliardetto/solana-go" - "github.com/gagliardetto/solana-go/rpc" chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/config" - bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" + + evmCommon "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/mcms/sdk" evmsdk "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/types" + + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + + "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/config" + bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" ) var _ sdk.Configurer = &Configurer{} diff --git a/sdk/solana/configurer_test.go b/sdk/solana/configurer_test.go index 1def82b7d..033e20030 100644 --- a/sdk/solana/configurer_test.go +++ b/sdk/solana/configurer_test.go @@ -2,24 +2,30 @@ package solana import ( "context" - "fmt" + "errors" "testing" + "github.com/stretchr/testify/require" + + cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/ethereum/go-ethereum/common" + ag_binary "github.com/gagliardetto/binary" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - cselectors "github.com/smartcontractkit/chain-selectors" + bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms/sdk/solana/mocks" "github.com/smartcontractkit/mcms/types" ) -func Test_NewConfigurer(t *testing.T) { +func TestNewConfigurer(t *testing.T) { t.Parallel() client := &rpc.Client{} @@ -161,7 +167,7 @@ func TestConfigurer_SetConfig(t *testing.T) { //nolint:paralleltest // https://g mockSolanaTransaction(t, mockJSONRPCClient, 10, 20, "4PQcRHQJT4cRQZooAhZMAP9ZXJsAka9DeKvXeYvXAvPpHb4Qkc5rmTSHDA2SZSh9aKPBguBx4kmcyHHbkytoAiRr", - nil, fmt.Errorf("initialize signers error")) + nil, errors.New("initialize signers error")) }, wantErr: "unable to set config: unable to send instruction 0 - initSigners: unable to send instruction: initialize signers error", }, @@ -180,7 +186,7 @@ func TestConfigurer_SetConfig(t *testing.T) { //nolint:paralleltest // https://g // append signers mockSolanaTransaction(t, mockJSONRPCClient, 10, 20, "7D9XEYRnCn1D5JFrrYMPUaHfog7Vnj5rbPdj7kbULa4hKq7GsnA7Q8KNQfLEgfCawBsW4dcH2MQAp4km1dnjr6V", - nil, fmt.Errorf("append signers error")) + nil, errors.New("append signers error")) }, wantErr: "unable to set config: unable to send instruction 1 - appendSigners0: unable to send instruction: append signers error", }, @@ -201,7 +207,7 @@ func TestConfigurer_SetConfig(t *testing.T) { //nolint:paralleltest // https://g // finalize signers mockSolanaTransaction(t, mockJSONRPCClient, 12, 22, "2iEeniu3QUgXNsjau8r7fZ7XLb2g1F3q9VJJKvRyyFz4hHgVvhGkLgSUdmRumfXKWv8spJ9ihudGFyPZsPGdp4Ya", - nil, fmt.Errorf("finalize signers error")) + nil, errors.New("finalize signers error")) }, wantErr: "unable to set config: unable to send instruction 2 - finalizeSigners: unable to send instruction: finalize signers error", }, @@ -224,7 +230,7 @@ func TestConfigurer_SetConfig(t *testing.T) { //nolint:paralleltest // https://g // set config mockSolanaTransaction(t, mockJSONRPCClient, 13, 23, "52f3VmvW7m9uTQu3PtyibgxnAvEuXDmm9umuHherGjS4pzRR7QXRDKnZhh6b95P7pQxzTgvE1muMNKYEY7YWsS3G", - nil, fmt.Errorf("set config error")) + nil, errors.New("set config error")) }, wantErr: "unable to set config: unable to send instruction 3 - setConfig: unable to send instruction: set config error", }, diff --git a/sdk/solana/contract_address_test.go b/sdk/solana/contract_address_test.go index d231948b1..28d657d9e 100644 --- a/sdk/solana/contract_address_test.go +++ b/sdk/solana/contract_address_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" ) -func Test_parseContractAddress(t *testing.T) { +func TestParseContractAddress(t *testing.T) { t.Parallel() tests := []struct { diff --git a/sdk/solana/encoder.go b/sdk/solana/encoder.go index f792d3508..b1ee1d75b 100644 --- a/sdk/solana/encoder.go +++ b/sdk/solana/encoder.go @@ -64,7 +64,7 @@ func (e *Encoder) HashOperation( // Parse Additional fields to get the ix accounts var additionalFields AdditionalFields if op.Transaction.AdditionalFields != nil { - if err := json.Unmarshal(op.Transaction.AdditionalFields, &additionalFields); err != nil { + if err = json.Unmarshal(op.Transaction.AdditionalFields, &additionalFields); err != nil { return common.Hash{}, fmt.Errorf("unable to unmarshal additional fields: %w", err) } } diff --git a/sdk/solana/executor.go b/sdk/solana/executor.go index 035a0dccc..b201b39df 100644 --- a/sdk/solana/executor.go +++ b/sdk/solana/executor.go @@ -7,15 +7,18 @@ import ( "math" "regexp" + chain_selectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + "github.com/ethereum/go-ethereum/common" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" - chain_selectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/config" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" - - "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/types" ) var _ sdk.Executor = (*Executor)(nil) diff --git a/sdk/solana/executor_test.go b/sdk/solana/executor_test.go index c6b7b6b71..e66face6b 100644 --- a/sdk/solana/executor_test.go +++ b/sdk/solana/executor_test.go @@ -7,14 +7,18 @@ import ( "math/big" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/ethereum/go-ethereum/common" + "github.com/google/go-cmp/cmp" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" - "github.com/google/go-cmp/cmp" - cselectors "github.com/smartcontractkit/chain-selectors" + bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms/sdk/solana/mocks" "github.com/smartcontractkit/mcms/types" @@ -340,7 +344,7 @@ func TestExecutor_SetRoot(t *testing.T) { //nolint:paralleltest // init-signatures mockSolanaTransaction(t, mockJSONRPCClient, 10, 20, "AxzwxQ2DLR4zEFxEPGaafR4z3MY4CP1CAdSs1ZZhArtgS3G4F9oYSy3Nx1HyA1Macb4bYEi4jU6F1CL4SRrZz1v", - nil, fmt.Errorf("initialize signatures error")) + nil, errors.New("initialize signatures error")) }, wantErr: "unable to initialize signatures: unable to send instruction: initialize signatures error", }, @@ -364,7 +368,7 @@ func TestExecutor_SetRoot(t *testing.T) { //nolint:paralleltest // append-signatures mockSolanaTransaction(t, mockJSONRPCClient, 10, 20, "3DqeyZzb7PJmQ31M1qdXfP7iACr5AiEXcKeLUNmVvDoYM23JJK5ZvermxsDy8eiQKzpagc69MKRtrpzK7tRcLGgr", - nil, fmt.Errorf("append signatures error")) + nil, errors.New("append signatures error")) }, wantErr: "unable to append signatures (0): unable to send instruction: append signatures error", }, @@ -390,7 +394,7 @@ func TestExecutor_SetRoot(t *testing.T) { //nolint:paralleltest // finalize-signatures mockSolanaTransaction(t, mockJSONRPCClient, 52, 62, "GHR9z23oUJnS2aV5HZ9zEpUpEe4qoBLFMzuBjNA3xJcQuc6JjDmuUq2VVmxqwPeFzfs8V7nfjqc1wRviEb82bRu", - nil, fmt.Errorf("finalize signatures error")) + nil, errors.New("finalize signatures error")) }, wantErr: "unable to finalize signatures: unable to send instruction: finalize signatures error", }, @@ -418,7 +422,7 @@ func TestExecutor_SetRoot(t *testing.T) { //nolint:paralleltest // set-root mockSolanaTransaction(t, mockJSONRPCClient, 53, 63, "oaV9FKKPDVneUANQ9hJqEuhgwfUgbxucUC4TmzpgGJhuSxBueapWc9HJ4cJQMqT2PPQX6rhTbKnXkebsaravnLo", - nil, fmt.Errorf("set root error")) + nil, errors.New("set root error")) }, wantErr: "unable to set root: unable to send instruction: set root error", }, @@ -454,7 +458,7 @@ func newTestExecutor(t *testing.T, auth solana.PrivateKey, chainSelector types.C return NewExecutor(encoder, client, auth), mockJSONRPCClient } -func Test_isAccountAlreadyInUseError(t *testing.T) { +func TestIsAccountAlreadyInUseError(t *testing.T) { t.Parallel() tests := []struct { diff --git a/sdk/solana/inspector.go b/sdk/solana/inspector.go index 4bc037a5a..fbe5109a4 100644 --- a/sdk/solana/inspector.go +++ b/sdk/solana/inspector.go @@ -4,14 +4,16 @@ import ( "context" "fmt" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + "github.com/ethereum/go-ethereum/common" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" + bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" solanaCommon "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" - - "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/types" ) var _ sdk.Inspector = (*Inspector)(nil) diff --git a/sdk/solana/inspector_test.go b/sdk/solana/inspector_test.go index aefd2c9c9..d29907724 100644 --- a/sdk/solana/inspector_test.go +++ b/sdk/solana/inspector_test.go @@ -2,22 +2,26 @@ package solana import ( "context" - "fmt" + "errors" "testing" + "github.com/stretchr/testify/require" + + cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/ethereum/go-ethereum/common" + "github.com/google/go-cmp/cmp" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" - "github.com/google/go-cmp/cmp" - cselectors "github.com/smartcontractkit/chain-selectors" + bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms/sdk/solana/mocks" "github.com/smartcontractkit/mcms/types" ) -func Test_NewInspector(t *testing.T) { +func TestNewInspector(t *testing.T) { t.Parallel() inspector := NewInspector(&rpc.Client{}) @@ -82,7 +86,7 @@ func TestInspector_GetConfig(t *testing.T) { { name: "error: rpc error", setup: func(mockJSONRPCClient *mocks.JSONRPCClient) { - err := fmt.Errorf("json rpc call failed") + err := errors.New("json rpc call failed") mockGetAccountInfo(t, mockJSONRPCClient, configPDA, &bindings.MultisigConfig{}, err) }, want: nil, @@ -146,7 +150,7 @@ func TestInspector_GetOpCount(t *testing.T) { { name: "error: rpc error", setup: func(mockJSONRPCClient *mocks.JSONRPCClient) { - err := fmt.Errorf("json rpc call failed") + err := errors.New("json rpc call failed") newRootAndOpCount := &bindings.ExpiringRootAndOpCount{OpCount: 123} mockGetAccountInfo(t, mockJSONRPCClient, opCountPDA, newRootAndOpCount, err) }, @@ -204,7 +208,7 @@ func TestInspector_GetRoot(t *testing.T) { { name: "error: rpc error", setup: func(mockJSONRPCClient *mocks.JSONRPCClient) { - err := fmt.Errorf("json rpc call failed") + err := errors.New("json rpc call failed") newRootAndOpCount := &bindings.ExpiringRootAndOpCount{ Root: hash, ValidUntil: 123, @@ -263,7 +267,7 @@ func TestInspector_GetRootMetadata(t *testing.T) { { name: "error: rpc error", setup: func(mockJSONRPCClient *mocks.JSONRPCClient) { - err := fmt.Errorf("json rpc call failed") + err := errors.New("json rpc call failed") newRootMetadata := &bindings.RootMetadata{PreOpCount: 123} mockGetAccountInfo(t, mockJSONRPCClient, rootMetadataPDA, newRootMetadata, err) }, diff --git a/sdk/solana/simulator.go b/sdk/solana/simulator.go index 83edcf259..72d78fb73 100644 --- a/sdk/solana/simulator.go +++ b/sdk/solana/simulator.go @@ -6,13 +6,15 @@ import ( "fmt" "time" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + "github.com/ethereum/go-ethereum/common" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" - solanaCommon "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" - "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/types" + solanaCommon "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" ) var _ sdk.Simulator = &Simulator{} diff --git a/sdk/solana/simulator_test.go b/sdk/solana/simulator_test.go index 78a93d5ca..6fbe12dd2 100644 --- a/sdk/solana/simulator_test.go +++ b/sdk/solana/simulator_test.go @@ -6,12 +6,16 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" + + cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/programs/system" - cselectors "github.com/smartcontractkit/chain-selectors" + bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/mcm" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms/sdk/solana/mocks" "github.com/smartcontractkit/mcms/types" diff --git a/sdk/solana/timelock_converter.go b/sdk/solana/timelock_converter.go index d8ef65015..04b387116 100644 --- a/sdk/solana/timelock_converter.go +++ b/sdk/solana/timelock_converter.go @@ -10,13 +10,15 @@ import ( "strconv" "time" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/gagliardetto/solana-go" - bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" - "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/types" + bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" ) var _ sdk.TimelockConverter = (*TimelockConverter)(nil) @@ -505,7 +507,7 @@ const ( recentBlockHashBytes = 32 numInstructions = 2 numInstructionsBytes = 1 - programIdIndexBytes = 1 * numInstructions + programIDIndexBytes = 1 * numInstructions numInstructionAccountsBytes = 1 * numInstructions accountIndexesBytes = 1 * numAccounts numSignatures = 1 @@ -542,7 +544,7 @@ func AppendIxDataChunkSize() int { accountsBytes - recentBlockHashBytes - numInstructionsBytes - - programIdIndexBytes - + programIDIndexBytes - numInstructionAccountsBytes - accountIndexesBytes - numSignaturesBytes - diff --git a/sdk/solana/timelock_converter_test.go b/sdk/solana/timelock_converter_test.go index 2f74327f2..e16f3fbb3 100644 --- a/sdk/solana/timelock_converter_test.go +++ b/sdk/solana/timelock_converter_test.go @@ -16,7 +16,7 @@ import ( "github.com/smartcontractkit/mcms/types" ) -func Test_TimelockConverter_ConvertBatchToChainOperations(t *testing.T) { +func TestTimelockConverter_ConvertBatchToChainOperations(t *testing.T) { t.Parallel() ctx := context.Background() diff --git a/sdk/solana/timelock_executor.go b/sdk/solana/timelock_executor.go index 8dd9ea84d..837b7d60e 100644 --- a/sdk/solana/timelock_executor.go +++ b/sdk/solana/timelock_executor.go @@ -4,14 +4,17 @@ import ( "context" "fmt" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + + chain_selectors "github.com/smartcontractkit/chain-selectors" + "github.com/ethereum/go-ethereum/common" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" - chain_selectors "github.com/smartcontractkit/chain-selectors" - bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" - "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/types" + bindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" ) var _ sdk.TimelockExecutor = (*TimelockExecutor)(nil) diff --git a/sdk/solana/timelock_executor_test.go b/sdk/solana/timelock_executor_test.go index c999c1972..44525e94a 100644 --- a/sdk/solana/timelock_executor_test.go +++ b/sdk/solana/timelock_executor_test.go @@ -3,15 +3,18 @@ package solana import ( "bytes" "context" + "errors" "fmt" "math/big" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" + cselectors "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms/sdk/solana/mocks" "github.com/smartcontractkit/mcms/types" @@ -29,7 +32,7 @@ func TestNewTimelockExecutor(t *testing.T) { require.Equal(t, executor.auth, auth) } -func Test_TimelockExecutor_Execute(t *testing.T) { //nolint:paralleltest +func TestTimelockExecutor_Execute(t *testing.T) { //nolint:paralleltest type args struct { bop types.BatchOperation salt [32]byte @@ -145,7 +148,7 @@ func Test_TimelockExecutor_Execute(t *testing.T) { //nolint:paralleltest }, setup: func(t *testing.T, e *TimelockExecutor, m *mocks.JSONRPCClient) { t.Helper() - mockGetAccountInfo(t, m, configPDA, config, fmt.Errorf("GetAccountInfo error")) + mockGetAccountInfo(t, m, configPDA, config, errors.New("GetAccountInfo error")) }, assertion: assertErrorEquals("unable to read config pda: GetAccountInfo error"), }, @@ -165,7 +168,7 @@ func Test_TimelockExecutor_Execute(t *testing.T) { //nolint:paralleltest mockGetAccountInfo(t, m, configPDA, config, nil) mockSolanaTransaction(t, m, 20, 5, "2QUBE2GqS8PxnGP1EBrWpLw3La4XkEUz5NKXJTdTHoA43ANkf5fqKwZ8YPJVAi3ApefbbbCYJipMVzUa7kg3a7v6", - nil, fmt.Errorf("invalid tx")) + nil, errors.New("invalid tx")) }, assertion: func(t assert.TestingT, err error, i ...any) bool { return assert.EqualError(t, err, "unable to call execute operation instruction: unable to send instruction: invalid tx") diff --git a/sdk/solana/timelock_inspector.go b/sdk/solana/timelock_inspector.go index 918f9363c..d359c65d3 100644 --- a/sdk/solana/timelock_inspector.go +++ b/sdk/solana/timelock_inspector.go @@ -7,12 +7,14 @@ import ( "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/access_controller" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" - solanaCommon "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" "github.com/smartcontractkit/mcms/internal/utils/safecast" "github.com/smartcontractkit/mcms/sdk" + + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/access_controller" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" + + solanaCommon "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" ) var _ sdk.TimelockInspector = (*TimelockInspector)(nil) @@ -231,6 +233,6 @@ func getRoleAccessController(config timelock.Config, role timelock.Role) (solana case timelock.Admin_Role: return solana.PublicKey{}, fmt.Errorf("not supported role: %v", role) default: - return solana.PublicKey{}, fmt.Errorf("unknown role") + return solana.PublicKey{}, errors.New("unknown role") } } diff --git a/sdk/solana/timelock_inspector_test.go b/sdk/solana/timelock_inspector_test.go index a7f99917c..6be38145b 100644 --- a/sdk/solana/timelock_inspector_test.go +++ b/sdk/solana/timelock_inspector_test.go @@ -5,11 +5,13 @@ import ( "errors" "testing" + "github.com/stretchr/testify/require" + "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/access_controller" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/timelock" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms/sdk/solana/mocks" ) diff --git a/sdk/solana/transaction.go b/sdk/solana/transaction.go index 566a0548e..c723314e6 100644 --- a/sdk/solana/transaction.go +++ b/sdk/solana/transaction.go @@ -21,11 +21,7 @@ func ValidateAdditionalFields(additionalFields json.RawMessage) error { } } - if err := fields.Validate(); err != nil { - return err - } - - return nil + return fields.Validate() } type AdditionalFields struct { @@ -35,12 +31,7 @@ type AdditionalFields struct { // Validate ensures the solana-specific fields are correct func (f AdditionalFields) Validate() error { - var validate = validator.New() - if err := validate.Struct(f); err != nil { - return err - } - - return nil + return validator.New().Struct(f) } func NewTransaction( diff --git a/sdk/solana/transaction_test.go b/sdk/solana/transaction_test.go index 050ffd131..0ccd2d393 100644 --- a/sdk/solana/transaction_test.go +++ b/sdk/solana/transaction_test.go @@ -5,9 +5,11 @@ import ( "math/big" "testing" + "github.com/stretchr/testify/require" + "github.com/gagliardetto/solana-go" + cpistub "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/external_program_cpi_stub" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms/types" ) @@ -126,7 +128,7 @@ func TestValidateAdditionalFields(t *testing.T) { } } -func TestAdditionalFieldsValidate(t *testing.T) { +func TestAdditionalFields_Validate(t *testing.T) { t.Parallel() validAccount := &solana.AccountMeta{ diff --git a/sdk/sui/configurer.go b/sdk/sui/configurer.go index 6e5d0c135..df95fb8f2 100644 --- a/sdk/sui/configurer.go +++ b/sdk/sui/configurer.go @@ -6,10 +6,11 @@ import ( "math/big" cselectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-sui/bindings/bind" - modulemcms "github.com/smartcontractkit/chainlink-sui/bindings/generated/mcms/mcms" "github.com/block-vision/sui-go-sdk/sui" + + "github.com/smartcontractkit/chainlink-sui/bindings/bind" + modulemcms "github.com/smartcontractkit/chainlink-sui/bindings/generated/mcms/mcms" bindutils "github.com/smartcontractkit/chainlink-sui/bindings/utils" "github.com/smartcontractkit/mcms/sdk" diff --git a/sdk/sui/decoded_operation.go b/sdk/sui/decoded_operation.go index fdd15d905..745ed2fab 100644 --- a/sdk/sui/decoded_operation.go +++ b/sdk/sui/decoded_operation.go @@ -2,6 +2,7 @@ package sui import ( "encoding/json" + "errors" "fmt" "github.com/smartcontractkit/mcms/sdk" @@ -19,7 +20,7 @@ var _ sdk.DecodedOperation = &DecodedOperation{} func NewDecodedOperation(moduleName, functionName string, inputKeys []string, inputArgs []any) (*DecodedOperation, error) { if len(inputKeys) != len(inputArgs) { - return nil, fmt.Errorf("input keys and input args must have the same length") + return nil, errors.New("input keys and input args must have the same length") } return &DecodedOperation{ diff --git a/sdk/sui/decoder.go b/sdk/sui/decoder.go index 714e08e2a..47ee707fe 100644 --- a/sdk/sui/decoder.go +++ b/sdk/sui/decoder.go @@ -6,6 +6,7 @@ import ( "github.com/aptos-labs/aptos-go-sdk/bcs" "github.com/block-vision/sui-go-sdk/models" + "github.com/smartcontractkit/chainlink-sui/bindgen/function" "github.com/smartcontractkit/chainlink-sui/bindings/bind" diff --git a/sdk/sui/decoder_test.go b/sdk/sui/decoder_test.go index 6fe198bf5..378769d29 100644 --- a/sdk/sui/decoder_test.go +++ b/sdk/sui/decoder_test.go @@ -3,15 +3,17 @@ package sui import ( "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/mcms/internal/utils/safecast" + "github.com/aptos-labs/aptos-go-sdk/bcs" "github.com/block-vision/sui-go-sdk/models" + "github.com/smartcontractkit/chainlink-sui/bindings/bind" "github.com/smartcontractkit/chainlink-sui/bindings/generated" mcmsuser "github.com/smartcontractkit/chainlink-sui/bindings/generated/mcms/mcms_user" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/mcms/internal/utils/safecast" ) func TestDecoder(t *testing.T) { diff --git a/sdk/sui/encoder.go b/sdk/sui/encoder.go index da57f45f6..2d440d273 100644 --- a/sdk/sui/encoder.go +++ b/sdk/sui/encoder.go @@ -3,6 +3,7 @@ package sui import ( "encoding/hex" "encoding/json" + "errors" "fmt" "math/big" "strings" @@ -67,13 +68,13 @@ func (e *Encoder) HashOperation(opCount uint32, metadata types.ChainMetadata, op return common.Hash{}, fmt.Errorf("failed to parse To address %q: %w", op.Transaction.To, err) } additionalFields := AdditionalFields{} - if unmarshalErr := json.Unmarshal(op.Transaction.AdditionalFields, &additionalFields); unmarshalErr != nil { - return common.Hash{}, fmt.Errorf("failed to unmarshal additional fields: %w", unmarshalErr) + if err = json.Unmarshal(op.Transaction.AdditionalFields, &additionalFields); err != nil { + return common.Hash{}, fmt.Errorf("failed to unmarshal additional fields: %w", err) } var additionalFieldsMetadata AdditionalFieldsMetadata if len(metadata.AdditionalFields) > 0 { - if unmarshalErr := json.Unmarshal(metadata.AdditionalFields, &additionalFieldsMetadata); unmarshalErr != nil { - return common.Hash{}, fmt.Errorf("failed to unmarshal additional fields metadata: %w", unmarshalErr) + if err = json.Unmarshal(metadata.AdditionalFields, &additionalFieldsMetadata); err != nil { + return common.Hash{}, fmt.Errorf("failed to unmarshal additional fields metadata: %w", err) } } @@ -104,7 +105,7 @@ func (e *Encoder) HashMetadata(metadata types.ChainMetadata) (common.Hash, error chainIDBig := (&big.Int{}).SetUint64(chainID) if len(metadata.AdditionalFields) == 0 { - return common.Hash{}, fmt.Errorf("additional fields metadata is empty") + return common.Hash{}, errors.New("additional fields metadata is empty") } var additionalFieldsMetadata AdditionalFieldsMetadata if unmarshalErr := json.Unmarshal(metadata.AdditionalFields, &additionalFieldsMetadata); unmarshalErr != nil { diff --git a/sdk/sui/executing_callback.go b/sdk/sui/executing_callback.go index 1c5aee175..d2769a9a0 100644 --- a/sdk/sui/executing_callback.go +++ b/sdk/sui/executing_callback.go @@ -82,7 +82,7 @@ func (e *ExecutingCallbackParams) processCall(ctx context.Context, ptb *transact } func (e *ExecutingCallbackParams) formatTargetAddress(target []byte) string { - return fmt.Sprintf("0x%s", strings.ToLower(hex.EncodeToString(target))) + return "0x" + strings.ToLower(hex.EncodeToString(target)) } func (e *ExecutingCallbackParams) isTargetMCMSPackage(targetString string) bool { @@ -200,7 +200,7 @@ func (e *ExecutingCallbackParams) processMCMSMainModuleCall(ctx context.Context, } // Adjust function name to match mcms_ prefix - executeDispatchCall.Function = fmt.Sprintf("mcms_%s", strings.TrimPrefix(call.FunctionName, "mcms_")) + executeDispatchCall.Function = "mcms_" + strings.TrimPrefix(call.FunctionName, "mcms_") _, err = e.mcms.Bound().AppendPTB(ctx, opts, ptb, executeDispatchCall) if err != nil { @@ -234,7 +234,7 @@ func (e *ExecutingCallbackParams) processDestinationContractCall(ctx context.Con func extractExecutingCallbackParams(mcmsPackageID string, ptb *transaction.Transaction, vectorExecutingCallback *transaction.Argument) (*transaction.Argument, error) { // Convert the type string to TypeTag - executingCallbackParamsType := fmt.Sprintf("%s::mcms_registry::ExecutingCallbackParams", mcmsPackageID) + executingCallbackParamsType := mcmsPackageID + "::mcms_registry::ExecutingCallbackParams" typeTag, err := bindutils.ConvertTypeStringToTypeTag(executingCallbackParamsType) if err != nil { return nil, fmt.Errorf("failed to convert type string to TypeTag: %w", err) @@ -255,7 +255,7 @@ func extractExecutingCallbackParams(mcmsPackageID string, ptb *transaction.Trans func closeExecutingCallbackParams(mcmsPackageID string, ptb *transaction.Transaction, vectorExecutingCallback *transaction.Argument) error { // Get the type tag for ExecutingCallbackParams - executingCallbackParamsType := fmt.Sprintf("%s::mcms_registry::ExecutingCallbackParams", mcmsPackageID) + executingCallbackParamsType := mcmsPackageID + "::mcms_registry::ExecutingCallbackParams" typeTag, err := bindutils.ConvertTypeStringToTypeTag(executingCallbackParamsType) if err != nil { return fmt.Errorf("failed to convert type string to TypeTag: %w", err) diff --git a/sdk/sui/executing_callback_test.go b/sdk/sui/executing_callback_test.go index 7ad1ee148..27088e569 100644 --- a/sdk/sui/executing_callback_test.go +++ b/sdk/sui/executing_callback_test.go @@ -3,18 +3,20 @@ package sui import ( "context" "encoding/hex" - "fmt" + "errors" "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/block-vision/sui-go-sdk/models" "github.com/block-vision/sui-go-sdk/sui" "github.com/block-vision/sui-go-sdk/transaction" + "github.com/smartcontractkit/chainlink-sui/bindings/bind" module_mcms_deployer "github.com/smartcontractkit/chainlink-sui/bindings/generated/mcms/mcms_deployer" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" mockbindutils "github.com/smartcontractkit/mcms/sdk/sui/mocks/bindutils" mockfeequoter "github.com/smartcontractkit/mcms/sdk/sui/mocks/feequoter" @@ -333,7 +335,7 @@ func TestExecutingCallbackParams_AppendPTB_ExtractError(t *testing.T) { // Mock the helper functions to return errors params.extractExecutingCallbackParams = func(mcmsPackageID string, ptb *transaction.Transaction, vectorExecutingCallback *transaction.Argument) (*transaction.Argument, error) { - return nil, fmt.Errorf("mock extract error") + return nil, errors.New("mock extract error") } params.closeExecutingCallbackParams = func(mcmsPackageID string, ptb *transaction.Transaction, vectorExecutingCallback *transaction.Argument) error { return nil @@ -579,7 +581,7 @@ func TestExecutingCallbackParams_AppendPTB_WithMCMSDeployerTarget_ExecuteDispatc "0xregistry", "0xdeployerstate", mock.AnythingOfType("*transaction.Argument"), - ).Return(nil, fmt.Errorf("mock dispatch error")) + ).Return(nil, errors.New("mock dispatch error")) mcmsPackageIDHex := "123456789abcdef0" + strings.Repeat("0", 48) mcmsPackageIDBytes, err := hex.DecodeString(mcmsPackageIDHex) @@ -650,7 +652,7 @@ func TestExecutingCallbackParams_AppendPTB_WithMCMSDeployerTarget_AppendPTBError mock.AnythingOfType("*bind.CallOpts"), mock.AnythingOfType("*transaction.Transaction"), expectedDispatchCall, - ).Return(nil, fmt.Errorf("mock append error")) + ).Return(nil, errors.New("mock append error")) mcmsPackageIDHex := "123456789abcdef0" + strings.Repeat("0", 48) mcmsPackageIDBytes, err := hex.DecodeString(mcmsPackageIDHex) diff --git a/sdk/sui/executor.go b/sdk/sui/executor.go index 9b5038aec..31b8628a2 100644 --- a/sdk/sui/executor.go +++ b/sdk/sui/executor.go @@ -3,6 +3,7 @@ package sui import ( "context" "encoding/json" + "errors" "fmt" "math/big" @@ -191,7 +192,7 @@ func (e Executor) ExecuteOperation( return types.TransactionResult{}, fmt.Errorf("failed to deserialize timelock bypasser execute batch: %w", err) } if len(calls) != len(additionalFields.InternalStateObjects) { - return types.TransactionResult{}, fmt.Errorf("mismatched call and state object count") + return types.TransactionResult{}, errors.New("mismatched call and state object count") } for i, call := range calls { calls[i] = Call{ diff --git a/sdk/sui/inspector.go b/sdk/sui/inspector.go index 47bb3e4a9..e6a4193f4 100644 --- a/sdk/sui/inspector.go +++ b/sdk/sui/inspector.go @@ -2,10 +2,12 @@ package sui import ( "context" + "errors" "fmt" "github.com/block-vision/sui-go-sdk/sui" "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink-sui/bindings/bind" modulemcms "github.com/smartcontractkit/chainlink-sui/bindings/generated/mcms/mcms" bindutils "github.com/smartcontractkit/chainlink-sui/bindings/utils" @@ -137,12 +139,12 @@ func (i Inspector) GetRoot(ctx context.Context, mcmsAddr string) (common.Hash, u root, ok := result[0].([]byte) if !ok { - return common.Hash{}, 0, fmt.Errorf("invalid root type: expected []byte") + return common.Hash{}, 0, errors.New("invalid root type: expected []byte") } validUntil, ok := result[1].(uint64) if !ok { - return common.Hash{}, 0, fmt.Errorf("invalid validUntil type: expected uint64") + return common.Hash{}, 0, errors.New("invalid validUntil type: expected uint64") } //nolint:gosec diff --git a/sdk/sui/inspector_test.go b/sdk/sui/inspector_test.go index 7ff2f6615..355e3f355 100644 --- a/sdk/sui/inspector_test.go +++ b/sdk/sui/inspector_test.go @@ -5,13 +5,15 @@ import ( "fmt" "testing" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-sui/bindings/bind" - modulemcms "github.com/smartcontractkit/chainlink-sui/bindings/generated/mcms/mcms" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-sui/bindings/bind" + modulemcms "github.com/smartcontractkit/chainlink-sui/bindings/generated/mcms/mcms" + mockbindutils "github.com/smartcontractkit/mcms/sdk/sui/mocks/bindutils" mockmodulemcms "github.com/smartcontractkit/mcms/sdk/sui/mocks/mcms" mocksui "github.com/smartcontractkit/mcms/sdk/sui/mocks/sui" diff --git a/sdk/sui/timelock_executor_test.go b/sdk/sui/timelock_executor_test.go index 8a094b9e7..768e50100 100644 --- a/sdk/sui/timelock_executor_test.go +++ b/sdk/sui/timelock_executor_test.go @@ -185,7 +185,7 @@ func TestTimelockExecutor_Execute_Success(t *testing.T) { mockBound.On("AppendPTB", ctx, mock.MatchedBy(func(opts *bind.CallOpts) bool { - return opts.Signer == mockSigner && opts.WaitForExecution == true + return opts.Signer == mockSigner && opts.WaitForExecution }), mock.AnythingOfType("*transaction.Transaction"), mock.AnythingOfType("*bind.EncodedCall"), @@ -456,7 +456,7 @@ func TestTimelockExecutor_Execute_AppendPTBFailure(t *testing.T) { mockBound.On("AppendPTB", ctx, mock.MatchedBy(func(opts *bind.CallOpts) bool { - return opts.Signer == mockSigner && opts.WaitForExecution == true + return opts.Signer == mockSigner && opts.WaitForExecution }), mock.AnythingOfType("*transaction.Transaction"), mock.AnythingOfType("*bind.EncodedCall"), diff --git a/sdk/sui/timelock_inspector.go b/sdk/sui/timelock_inspector.go index 8d1918972..ee61371e4 100644 --- a/sdk/sui/timelock_inspector.go +++ b/sdk/sui/timelock_inspector.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/block-vision/sui-go-sdk/sui" + "github.com/smartcontractkit/chainlink-sui/bindings/bind" modulemcms "github.com/smartcontractkit/chainlink-sui/bindings/generated/mcms/mcms" bindutils "github.com/smartcontractkit/chainlink-sui/bindings/utils" diff --git a/sdk/sui/transaction.go b/sdk/sui/transaction.go index 16b20961b..a7e2ee7c7 100644 --- a/sdk/sui/transaction.go +++ b/sdk/sui/transaction.go @@ -19,11 +19,7 @@ func ValidateAdditionalFields(additionalFields json.RawMessage) error { return fmt.Errorf("failed to unmarshal Sui additional fields: %w", err) } - if err := fields.Validate(); err != nil { - return err - } - - return nil + return fields.Validate() } func (af AdditionalFields) Validate() error { @@ -97,9 +93,9 @@ func NewTransactionWithUpgradeData(moduleName, function string, to string, data } // CreateUpgradeTransaction creates a transaction for upgrading a package through MCMS -func CreateUpgradeTransaction(compiledPackage bind.PackageArtifact, mcmsPackageID, depStateObj, registryObj, ownerCapObj, mcmsUserPackageId string) (types.Transaction, error) { +func CreateUpgradeTransaction(compiledPackage bind.PackageArtifact, mcmsPackageID, depStateObj, registryObj, ownerCapObj, mcmsUserPackageID string) (types.Transaction, error) { upgradePolicy := uint8(0) // Compatible upgrade policy - data, err := serializeAuthorizeUpgradeParams(ownerCapObj, depStateObj, upgradePolicy, compiledPackage.Digest, mcmsUserPackageId) + data, err := serializeAuthorizeUpgradeParams(ownerCapObj, depStateObj, upgradePolicy, compiledPackage.Digest, mcmsUserPackageID) if err != nil { return types.Transaction{}, fmt.Errorf("serializing authorize upgrade params: %w", err) } @@ -131,6 +127,6 @@ func CreateUpgradeTransaction(compiledPackage bind.PackageArtifact, mcmsPackageI []string{registryObj}, // Internal objects (Registry for validation) moduleBytes, // Compiled modules for upgrade depAddresses, // Dependencies for upgrade - mcmsUserPackageId, // Package being upgraded + mcmsUserPackageID, // Package being upgraded ) } diff --git a/sdk/usbwallet/eip191.go b/sdk/usbwallet/eip191.go index 8f9ad5dc4..483be903f 100644 --- a/sdk/usbwallet/eip191.go +++ b/sdk/usbwallet/eip191.go @@ -3,6 +3,7 @@ package usbwallet import ( "encoding/binary" "fmt" + "math" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/crypto" @@ -60,7 +61,7 @@ func (w *ledgerDriver) SignPersonalMessage(path accounts.DerivationPath, message // Ensure the wallet is capable of signing the given transaction if w.version[0] < 1 && w.version[1] < 2 { //lint:ignore ST1005 brand name displayed on the console - return nil, fmt.Errorf("Ledger version >= 1.2.0 required for personal signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2]) + return nil, fmt.Errorf("version error: Ledger version >= 1.2.0 required for personal signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2]) } return w.ledgerSignPersonalMessage(path, message) } @@ -73,7 +74,12 @@ func (w *ledgerDriver) ledgerSignPersonalMessage(derivationPath []uint32, messag binary.BigEndian.PutUint32(path[1+4*i:], component) } var messageLength [4]byte - binary.BigEndian.PutUint32(messageLength[:], uint32(len(message))) + // G115 check + msgLen := len(message) + if msgLen > math.MaxUint32 { + return nil, fmt.Errorf("message length %d exceeds uint32 max", msgLen) + } + binary.BigEndian.PutUint32(messageLength[:], uint32(msgLen)) //nolint:gosec // G115: overflow checked above payload := append(path, messageLength[:]...) payload = append(payload, message...) // Send the request and wait for the response @@ -82,10 +88,11 @@ func (w *ledgerDriver) ledgerSignPersonalMessage(derivationPath []uint32, messag reply []byte err error ) - fmt.Println("Derivation path: ", path) + fmt.Println("Derivation path: " + string(path)) // Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app. // https://github.com/LedgerHQ/app-ethereum/issues/409 chunk := 255 + //nolint:revive // alow empty block for ; len(payload)%chunk <= ledgerEip155Size; chunk-- { } diff --git a/sdk/usbwallet/hub.go b/sdk/usbwallet/hub.go index aa3de7e3c..3275e6b04 100644 --- a/sdk/usbwallet/hub.go +++ b/sdk/usbwallet/hub.go @@ -186,7 +186,7 @@ func (hub *Hub) refreshWallets() { var ( wallets = make([]accounts.Wallet, 0, len(devices)) - events []accounts.WalletEvent + events = make([]accounts.WalletEvent, 0, len(devices)) ) for _, device := range devices { diff --git a/sdk/usbwallet/ledger.go b/sdk/usbwallet/ledger.go index 81836b371..6e98268bf 100644 --- a/sdk/usbwallet/ledger.go +++ b/sdk/usbwallet/ledger.go @@ -26,6 +26,7 @@ import ( "errors" "fmt" "io" + "math" "math/big" "github.com/ethereum/go-ethereum/accounts" @@ -119,7 +120,7 @@ func (w *ledgerDriver) Open(device io.ReadWriter, passphrase string) error { _, err := w.ledgerDerive(accounts.DefaultBaseDerivationPath) if err != nil { // Ethereum app is not running or in browser mode, nothing more to do, return - if err == errLedgerReplyInvalidHeader { + if errors.Is(err, errLedgerReplyInvalidHeader) { w.browser = true } return nil @@ -141,7 +142,7 @@ func (w *ledgerDriver) Close() error { // Heartbeat implements usbwallet.driver, performing a sanity check against the // Ledger to see if it's still online. func (w *ledgerDriver) Heartbeat() error { - if _, err := w.ledgerVersion(); err != nil && err != errLedgerInvalidVersionReply { + if _, err := w.ledgerVersion(); err != nil && !errors.Is(err, errLedgerInvalidVersionReply) { w.failure = err return err } @@ -168,7 +169,7 @@ func (w *ledgerDriver) SignTx(path accounts.DerivationPath, tx *types.Transactio // Ensure the wallet is capable of signing the given transaction if chainID != nil && w.version[0] <= 1 && w.version[1] <= 0 && w.version[2] <= 2 { //lint:ignore ST1005 brand name displayed on the console - return common.Address{}, nil, fmt.Errorf("Ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2]) + return common.Address{}, nil, fmt.Errorf("version error: Ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2]) } // All infos gathered and metadata checks out, request signing return w.ledgerSign(path, tx, chainID) @@ -186,7 +187,7 @@ func (w *ledgerDriver) SignTypedMessage(path accounts.DerivationPath, domainHash // Ensure the wallet is capable of signing the given transaction if w.version[0] < 1 && w.version[1] < 5 { //lint:ignore ST1005 brand name displayed on the console - return nil, fmt.Errorf("Ledger version >= 1.5.0 required for EIP-712 signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2]) + return nil, fmt.Errorf("version error: Ledger version >= 1.5.0 required for EIP-712 signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2]) } // All infos gathered and metadata checks out, request signing return w.ledgerSignTypedMessage(path, domainHash, messageHash) @@ -353,6 +354,7 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction // Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app. // https://github.com/LedgerHQ/app-ethereum/issues/409 chunk := 255 + //nolint:revive // alow empty block for ; len(payload)%chunk <= ledgerEip155Size; chunk-- { } @@ -492,7 +494,12 @@ func (w *ledgerDriver) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 l // Construct the message payload, possibly split into multiple chunks apdu := make([]byte, 2, 7+len(data)) - binary.BigEndian.PutUint16(apdu, uint16(5+len(data))) + // G115 check + apduLen := 5 + len(data) + if apduLen > math.MaxUint16 { + return nil, fmt.Errorf("APDU length %d exceeds uint16 max", apduLen) + } + binary.BigEndian.PutUint16(apdu, uint16(apduLen)) //nolint:gosec // G115: overflow checked above apdu = append(apdu, []byte{0xe0, byte(opcode), byte(p1), byte(p2), byte(len(data))}...) apdu = append(apdu, data...) @@ -504,7 +511,7 @@ func (w *ledgerDriver) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 l for i := 0; len(apdu) > 0; i++ { // Construct the new message to stream chunk = append(chunk[:0], header...) - binary.BigEndian.PutUint16(chunk[3:], uint16(i)) + binary.BigEndian.PutUint16(chunk[3:], uint16(i)) //nolint:gosec // G115 conversion safe if len(apdu) > space { chunk = append(chunk, apdu[:space]...) @@ -543,12 +550,12 @@ func (w *ledgerDriver) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 l payload = chunk[5:] } // Append to the reply and stop when filled up - if left := cap(reply) - len(reply); left > len(payload) { - reply = append(reply, payload...) - } else { + left := cap(reply) - len(reply) + if left <= len(payload) { reply = append(reply, payload[:left]...) break } + reply = append(reply, payload...) } return reply[:len(reply)-2], nil } diff --git a/sdk/usbwallet/wallet.go b/sdk/usbwallet/wallet.go index b91ddf81d..f676981c2 100644 --- a/sdk/usbwallet/wallet.go +++ b/sdk/usbwallet/wallet.go @@ -533,6 +533,7 @@ func (w *wallet) signHash(account accounts.Account, hash []byte) ([]byte, error) // SignData signs keccak256(data). The mimetype parameter describes the type of data being signed func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { // Unless we are doing 712 signing, simply dispatch to signHash + //nolint:staticcheck // TODO: fix - apply De Morgan's law (staticcheck) if !(mimeType == accounts.MimetypeTypedData && len(data) == 66 && data[0] == 0x19 && data[1] == 0x01) { return w.signHash(account, crypto.Keccak256(data)) } @@ -546,6 +547,7 @@ func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte return nil, accounts.ErrWalletClosed } // Make sure the requested account is contained within + // Make sure the requested account is contained within path, ok := w.paths[account.Address] if !ok { return nil, accounts.ErrUnknownAccount diff --git a/signable_test.go b/signable_test.go index 34eddb683..831463a99 100644 --- a/signable_test.go +++ b/signable_test.go @@ -32,7 +32,7 @@ type simulatorMocks struct { simulator2 *sdkmocks.Simulator } -func Test_NewSignable(t *testing.T) { +func TestNewSignable(t *testing.T) { t.Parallel() inspector := sdkmocks.NewInspector(t) // We only need this to fulfill the interface argument requirements @@ -460,6 +460,7 @@ func TestSignable_SingleChainMultipleSignerMultipleTX_FailureMissingQuorum(t *te // Validate the signatures quorumMet, err := signable.ValidateSignatures(ctx) require.Error(t, err) + //nolint:testifylint // Allow IsType for error type checking require.IsType(t, &QuorumNotReachedError{}, err) require.False(t, quorumMet) } @@ -556,7 +557,7 @@ func TestSignable_SingleChainMultipleSignerMultipleTX_FailureInvalidSigner(t *te require.False(t, quorumMet) } -func Test_Signable_Sign(t *testing.T) { +func TestSignable_Sign(t *testing.T) { t.Parallel() privKey, err := crypto.HexToECDSA(testPrivateKeyHex) @@ -649,7 +650,7 @@ func Test_Signable_Sign(t *testing.T) { } } -func Test_SignAndAppend(t *testing.T) { +func TestSignAndAppend(t *testing.T) { t.Parallel() privKey, err := crypto.HexToECDSA(testPrivateKeyHex) @@ -741,7 +742,7 @@ func Test_SignAndAppend(t *testing.T) { } } -func Test_Signable_GetConfigs(t *testing.T) { +func TestSignable_GetConfigs(t *testing.T) { t.Parallel() ctx := context.Background() @@ -852,7 +853,7 @@ func Test_Signable_GetConfigs(t *testing.T) { } } -func Test_Signable_Simulate(t *testing.T) { +func TestSignable_Simulate(t *testing.T) { t.Parallel() ctx := context.Background() @@ -978,7 +979,7 @@ func Test_Signable_Simulate(t *testing.T) { } } -func Test_Signable_ValidateConfigs(t *testing.T) { +func TestSignable_ValidateConfigs(t *testing.T) { t.Parallel() var ( @@ -1085,7 +1086,7 @@ func Test_Signable_ValidateConfigs(t *testing.T) { } } -func Test_Signable_getCurrentOpCounts(t *testing.T) { +func TestSignable_GetCurrentOpCounts(t *testing.T) { t.Parallel() ctx := context.Background() diff --git a/signer_test.go b/signer_test.go index 7ba1995f9..7be6c1ef3 100644 --- a/signer_test.go +++ b/signer_test.go @@ -11,7 +11,7 @@ import ( const testPrivateKeyHex = "b17c4c6a409cebce4b39977689180900d9009d5c55a57ff9fd9cb962b24ae99d" -func Test_PrivateKeySigner_Sign(t *testing.T) { +func TestPrivateKeySigner_Sign(t *testing.T) { t.Parallel() privKey, err := crypto.HexToECDSA(testPrivateKeyHex) @@ -49,7 +49,7 @@ func Test_PrivateKeySigner_Sign(t *testing.T) { } } -func Test_PrivateKeySigner_GetAddress(t *testing.T) { +func TestPrivateKeySigner_GetAddress(t *testing.T) { t.Parallel() privKey, err := crypto.HexToECDSA(testPrivateKeyHex) diff --git a/taskfiles/test/Taskfile.yml b/taskfiles/test/Taskfile.yml index 20bcc1901..8a0a50490 100644 --- a/taskfiles/test/Taskfile.yml +++ b/taskfiles/test/Taskfile.yml @@ -24,6 +24,13 @@ tasks: cmds: - CTF_CONFIGS=$CTF_CONFIGS go test -v -tags=e2e {{.CLI_ARGS}} ./e2e/tests... + e2e:evm: + desc: "Run EVM e2e tests" + env: + CTF_CONFIGS: '{{ .CTF_CONFIGS | default "../config.evm.toml" }}' + cmds: + - CTF_CONFIGS=$CTF_CONFIGS go test -v -tags=e2e -test.run TestEVMSuite {{.CLI_ARGS}} ./e2e/tests... + e2e:aptos: desc: "Run Aptos e2e tests" env: diff --git a/timelock_executable.go b/timelock_executable.go index d3593703f..d49e2b55e 100644 --- a/timelock_executable.go +++ b/timelock_executable.go @@ -2,6 +2,7 @@ package mcms import ( "context" + "errors" "fmt" "github.com/ethereum/go-ethereum/common" @@ -26,7 +27,7 @@ func NewTimelockExecutable( executors map[types.ChainSelector]sdk.TimelockExecutor, ) (*TimelockExecutable, error) { if proposal.Action != types.TimelockActionSchedule { - return nil, fmt.Errorf("TimelockExecutable can only be created from a TimelockProposal with action 'schedule'") + return nil, errors.New("TimelockExecutable can only be created from a TimelockProposal with action 'schedule'") } te := &TimelockExecutable{ diff --git a/timelock_executable_test.go b/timelock_executable_test.go index 1ce93b926..a8769b15f 100644 --- a/timelock_executable_test.go +++ b/timelock_executable_test.go @@ -3,7 +3,7 @@ package mcms import ( "context" "encoding/json" - "fmt" + "errors" "math/big" "testing" "time" @@ -34,7 +34,7 @@ var ( adminRole = crypto.Keccak256Hash([]byte("ADMIN_ROLE")) ) -func Test_NewTimelockExecutable(t *testing.T) { +func TestNewTimelockExecutable(t *testing.T) { t.Parallel() var ( @@ -151,7 +151,7 @@ func Test_NewTimelockExecutable(t *testing.T) { } } -func Test_TimelockExecutable_Execute(t *testing.T) { +func TestTimelockExecutable_Execute(t *testing.T) { t.Parallel() ctx := context.Background() @@ -242,7 +242,7 @@ func Test_TimelockExecutable_Execute(t *testing.T) { executor := mocks.NewTimelockExecutor(t) executor.EXPECT(). Execute(ctx, mock.Anything, "0x5678", mock.Anything, mock.Anything). - Return(types.TransactionResult{}, fmt.Errorf("execute error")).Once() + Return(types.TransactionResult{}, errors.New("execute error")).Once() executors := map[types.ChainSelector]sdk.TimelockExecutor{chaintest.Chain1Selector: executor} return defaultProposal(), executors @@ -275,11 +275,9 @@ func Test_TimelockExecutable_Execute(t *testing.T) { } } -func Test_ScheduleAndExecuteProposal(t *testing.T) { +func TestScheduleAndExecuteProposal(t *testing.T) { t.Parallel() - ctx := context.Background() - tests := []struct { name string targetRoles []common.Hash @@ -304,16 +302,14 @@ func Test_ScheduleAndExecuteProposal(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - scheduleAndExecuteGrantRolesProposal(t, ctx, tt.targetRoles) + scheduleAndExecuteGrantRolesProposal(t, tt.targetRoles) }) } } -func Test_ScheduleAndCancelProposal(t *testing.T) { +func TestScheduleAndCancelProposal(t *testing.T) { t.Parallel() - ctx := context.Background() - tests := []struct { name string targetRoles []common.Hash @@ -338,7 +334,7 @@ func Test_ScheduleAndCancelProposal(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - scheduleAndCancelGrantRolesProposal(t, ctx, tt.targetRoles) + scheduleAndCancelGrantRolesProposal(t, tt.targetRoles) }) } } @@ -434,8 +430,9 @@ func scheduleGrantRolesProposal( return sim, mcmC, timelockC, proposal, targetRoles } -func scheduleAndExecuteGrantRolesProposal(t *testing.T, ctx context.Context, targetRoles []common.Hash) { +func scheduleAndExecuteGrantRolesProposal(t *testing.T, targetRoles []common.Hash) { t.Helper() + ctx := t.Context() sim, mcmC, timelockC, proposal, _ := scheduleGrantRolesProposal(t, targetRoles, types.MustParseDuration("5s")) @@ -531,7 +528,7 @@ func scheduleAndExecuteGrantRolesProposal(t *testing.T, ctx context.Context, tar require.NoError(t, err) for i := range predecessors { - if i == 0 || predecessors[i] == ZERO_HASH { + if i == 0 || predecessors[i] == ZeroHash { continue } var isOperation, isOperationPending, isOperationReady bool @@ -547,26 +544,26 @@ func scheduleAndExecuteGrantRolesProposal(t *testing.T, ctx context.Context, tar } opIdx := 0 - requireOperationPending(t, ctx, tExecutable, &proposal, opIdx) - requireOperationNotReady(t, ctx, tExecutable, &proposal, opIdx) - requireOperationNotDone(t, ctx, tExecutable, &proposal, opIdx) + requireOperationPending(t, tExecutable, &proposal, opIdx) + requireOperationNotReady(t, tExecutable, &proposal, opIdx) + requireOperationNotDone(t, tExecutable, &proposal, opIdx) // sleep for 5 seconds and then mine a block require.NoError(t, sim.Backend.AdjustTime(5*time.Second)) sim.Backend.Commit() // Note < 1.14 geth needs a commit after adjusting time. - requireOperationPending(t, ctx, tExecutable, &proposal, opIdx) - requireOperationReady(t, ctx, tExecutable, &proposal, opIdx) - requireOperationNotDone(t, ctx, tExecutable, &proposal, opIdx) + requireOperationPending(t, tExecutable, &proposal, opIdx) + requireOperationReady(t, tExecutable, &proposal, opIdx) + requireOperationNotDone(t, tExecutable, &proposal, opIdx) // Execute the proposal _, err = tExecutable.Execute(ctx, opIdx) require.NoError(t, err) sim.Backend.Commit() - requireOperationNotPending(t, ctx, tExecutable, &proposal, opIdx) - requireOperationNotReady(t, ctx, tExecutable, &proposal, opIdx) - requireOperationDone(t, ctx, tExecutable, &proposal, opIdx) + requireOperationNotPending(t, tExecutable, &proposal, opIdx) + requireOperationNotReady(t, tExecutable, &proposal, opIdx) + requireOperationDone(t, tExecutable, &proposal, opIdx) // Check the state of the timelock contract for _, role := range targetRoles { @@ -579,8 +576,9 @@ func scheduleAndExecuteGrantRolesProposal(t *testing.T, ctx context.Context, tar } } -func scheduleAndCancelGrantRolesProposal(t *testing.T, ctx context.Context, targetRoles []common.Hash) { +func scheduleAndCancelGrantRolesProposal(t *testing.T, targetRoles []common.Hash) { t.Helper() + ctx := t.Context() sim, mcmC, timelockC, proposal, _ := scheduleGrantRolesProposal(t, targetRoles, types.MustParseDuration("5m")) @@ -677,7 +675,7 @@ func scheduleAndCancelGrantRolesProposal(t *testing.T, ctx context.Context, targ require.NoError(t, err) for i := range predecessors { - if i == 0 || predecessors[i] == ZERO_HASH { + if i == 0 || predecessors[i] == ZeroHash { continue } @@ -800,7 +798,7 @@ func scheduleAndCancelGrantRolesProposal(t *testing.T, ctx context.Context, targ } } -func Test_TimelockExecutable_GetChainSpecificIndex(t *testing.T) { +func TestTimelockExecutable_GetChainSpecificIndex(t *testing.T) { t.Parallel() ctx := context.Background() @@ -942,10 +940,9 @@ func Test_TimelockExecutable_GetChainSpecificIndex(t *testing.T) { }) } -func requireOperationPending( - t *testing.T, ctx context.Context, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int, -) { +func requireOperationPending(t *testing.T, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int) { t.Helper() + ctx := t.Context() err := tExecutable.IsOperationPending(ctx, opIdx) require.NoError(t, err) for chainSelector := range proposal.ChainMetadata { @@ -954,10 +951,9 @@ func requireOperationPending( } } -func requireOperationNotPending( - t *testing.T, ctx context.Context, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int, -) { +func requireOperationNotPending(t *testing.T, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int) { t.Helper() + ctx := t.Context() err := tExecutable.IsOperationPending(ctx, opIdx) require.ErrorContains(t, err, "operation 0 is not pending") for chainSelector := range proposal.ChainMetadata { @@ -966,10 +962,9 @@ func requireOperationNotPending( } } -func requireOperationReady( - t *testing.T, ctx context.Context, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int, -) { +func requireOperationReady(t *testing.T, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int) { t.Helper() + ctx := t.Context() err := tExecutable.IsOperationReady(ctx, opIdx) require.NoError(t, err) for chainSelector := range proposal.ChainMetadata { @@ -978,10 +973,9 @@ func requireOperationReady( } } -func requireOperationNotReady( - t *testing.T, ctx context.Context, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int, -) { +func requireOperationNotReady(t *testing.T, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int) { t.Helper() + ctx := t.Context() err := tExecutable.IsOperationReady(ctx, opIdx) require.ErrorContains(t, err, "operation 0 is not ready") for chainSelector := range proposal.ChainMetadata { @@ -990,10 +984,9 @@ func requireOperationNotReady( } } -func requireOperationDone( - t *testing.T, ctx context.Context, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int, -) { +func requireOperationDone(t *testing.T, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int) { t.Helper() + ctx := t.Context() err := tExecutable.IsOperationDone(ctx, opIdx) require.NoError(t, err) for chainSelector := range proposal.ChainMetadata { @@ -1002,10 +995,9 @@ func requireOperationDone( } } -func requireOperationNotDone( - t *testing.T, ctx context.Context, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int, -) { +func requireOperationNotDone(t *testing.T, tExecutable *TimelockExecutable, proposal *TimelockProposal, opIdx int) { t.Helper() + ctx := t.Context() err := tExecutable.IsOperationDone(ctx, opIdx) require.ErrorContains(t, err, "operation 0 is not done") for chainSelector := range proposal.ChainMetadata { diff --git a/timelock_proposal.go b/timelock_proposal.go index ff7a67c93..7d3905050 100644 --- a/timelock_proposal.go +++ b/timelock_proposal.go @@ -10,7 +10,9 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/go-playground/validator/v10" + chain_selectors "github.com/smartcontractkit/chain-selectors" inspectorsbuilder "github.com/smartcontractkit/mcms/inspectors" @@ -22,7 +24,7 @@ import ( "github.com/smartcontractkit/mcms/types" ) -var ZERO_HASH = common.Hash{} +var ZeroHash = common.Hash{} var DefaultValidUntil = 72 * time.Hour type TimelockProposal struct { @@ -106,11 +108,7 @@ func (m *TimelockProposal) Validate() error { } } - if err := timeLockProposalValidateBasic(*m); err != nil { - return err - } - - return nil + return timeLockProposalValidateBasic(*m) } func replaceChainMetadataWithAddresses(p *TimelockProposal, addresses map[types.ChainSelector]types.ChainMetadata) error { @@ -152,7 +150,7 @@ func (m *TimelockProposal) deriveNewProposal(action types.TimelockAction, metada // DeriveCancellationProposal derives a new proposal that cancels the current proposal. func (m *TimelockProposal) DeriveCancellationProposal(cancellerMetadata map[types.ChainSelector]types.ChainMetadata) (TimelockProposal, error) { if m.Action != types.TimelockActionSchedule { - return TimelockProposal{}, fmt.Errorf("cannot derive a cancellation proposal from a non-schedule proposal. Action needs to be of type 'schedule'") + return TimelockProposal{}, errors.New("cannot derive a cancellation proposal from a non-schedule proposal. Action needs to be of type 'schedule'") } return m.deriveNewProposal(types.TimelockActionCancel, cancellerMetadata) @@ -161,7 +159,7 @@ func (m *TimelockProposal) DeriveCancellationProposal(cancellerMetadata map[type // DeriveBypassProposal derives a new proposal that bypasses the current proposal. func (m *TimelockProposal) DeriveBypassProposal(bypasserAddresses map[types.ChainSelector]types.ChainMetadata) (TimelockProposal, error) { if m.Action != types.TimelockActionSchedule { - return TimelockProposal{}, fmt.Errorf("cannot derive a bypass proposal from a non-schedule proposal. Action needs to be of type 'schedule'") + return TimelockProposal{}, errors.New("cannot derive a bypass proposal from a non-schedule proposal. Action needs to be of type 'schedule'") } return m.deriveNewProposal(types.TimelockActionBypass, bypasserAddresses) @@ -182,9 +180,9 @@ func (m *TimelockProposal) Convert( // 3) Keep track of the last operation ID per chain lastOpID := make(map[types.ChainSelector]common.Hash) - // Initialize them to ZERO_HASH + // Initialize them to ZeroHash for sel := range m.ChainMetadata { - lastOpID[sel] = ZERO_HASH + lastOpID[sel] = ZeroHash } // 4) Rebuild chainMetadata in baseProposal diff --git a/timelock_proposal_test.go b/timelock_proposal_test.go index 7a4878463..41f0739ad 100644 --- a/timelock_proposal_test.go +++ b/timelock_proposal_test.go @@ -59,7 +59,7 @@ var ValidTimelockProposal = `{ ] }` -func Test_NewTimelockProposal(t *testing.T) { +func TestNewTimelockProposal(t *testing.T) { t.Parallel() tests := []struct { @@ -505,7 +505,7 @@ func Test_WriteTimelockProposal(t *testing.T) { } } -func Test_TimelockProposal_Validate(t *testing.T) { +func TestTimelockProposal_Validate(t *testing.T) { t.Parallel() tests := []struct { @@ -707,7 +707,7 @@ func Test_TimelockProposal_Validate(t *testing.T) { } } -func Test_TimelockProposal_Convert(t *testing.T) { +func TestTimelockProposal_Convert(t *testing.T) { t.Parallel() var ( @@ -814,12 +814,12 @@ func Test_TimelockProposal_Convert(t *testing.T) { require.Len(t, mcmsProposal.Operations, 3) require.Len(t, predecessors, 3) - require.Equal(t, predecessors[0], ZERO_HASH) - require.Equal(t, predecessors[1], ZERO_HASH) - require.NotEqual(t, predecessors[2], ZERO_HASH) + require.Equal(t, predecessors[0], ZeroHash) + require.Equal(t, predecessors[1], ZeroHash) + require.NotEqual(t, predecessors[2], ZeroHash) } -func TestProposal_WithSaltOverride(t *testing.T) { +func TestTimelockProposal_WithSaltOverride(t *testing.T) { t.Parallel() builder := NewTimelockProposalBuilder() builder.SetVersion("v1"). @@ -846,7 +846,7 @@ func TestProposal_WithSaltOverride(t *testing.T) { assert.Equal(t, salt, common.BytesToHash(saltBytes[:])) } -func Test_TimelockProposal_Decode(t *testing.T) { +func TestTimelockProposal_Decode(t *testing.T) { t.Parallel() // Get ABI @@ -1002,7 +1002,7 @@ func Test_TimelockProposal_Decode(t *testing.T) { } } -func Test_TimelockProposal_WithoutSaltOverride(t *testing.T) { +func TestTimelockProposal_WithoutSaltOverride(t *testing.T) { t.Parallel() builder := NewTimelockProposalBuilder() builder.SetVersion("v1"). @@ -1028,7 +1028,7 @@ func Test_TimelockProposal_WithoutSaltOverride(t *testing.T) { assert.NotEqual(t, common.Hash{}, saltBytes) } -func Test_TimelockProposal_DeriveBypassProposal(t *testing.T) { +func TestTimelockProposal_DeriveBypassProposal(t *testing.T) { t.Parallel() tests := []struct { @@ -1076,7 +1076,7 @@ func Test_TimelockProposal_DeriveBypassProposal(t *testing.T) { } } -func Test_TimelockProposal_DeriveCancellationProposal(t *testing.T) { +func TestTimelockProposal_DeriveCancellationProposal(t *testing.T) { t.Parallel() tests := []struct { @@ -1124,7 +1124,7 @@ func Test_TimelockProposal_DeriveCancellationProposal(t *testing.T) { } } -func Test_TimelockProposal_ConvertedOperationCounts(t *testing.T) { +func TestTimelockProposal_ConvertedOperationCounts(t *testing.T) { t.Parallel() ctx := context.Background() @@ -1223,7 +1223,7 @@ func Test_TimelockProposal_ConvertedOperationCounts(t *testing.T) { assert.Equal(t, uint64(4), counts[chaintest.Chain4Selector]) } -func Test_TimelockProposal_Merge(t *testing.T) { +func TestTimelockProposal_Merge(t *testing.T) { t.Parallel() sig1, err := types.NewSignatureFromBytes(common.Hex2Bytes("0000000000000000000000000000000000000000000000001111111111111111000000000000000000000000000000000000000000000000aaaaaaaaaaaaaaaa1b")) diff --git a/types/chain.go b/types/chain.go index 46851c51d..7e55e2c5f 100644 --- a/types/chain.go +++ b/types/chain.go @@ -1,4 +1,4 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' import ( "encoding/json" diff --git a/types/chain_selector.go b/types/chain_selector.go index 668bc7f74..f99ab50eb 100644 --- a/types/chain_selector.go +++ b/types/chain_selector.go @@ -1,4 +1,4 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' import ( "errors" diff --git a/types/chain_selector_test.go b/types/chain_selector_test.go index a19761603..ed49b555d 100644 --- a/types/chain_selector_test.go +++ b/types/chain_selector_test.go @@ -1,14 +1,15 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' import ( "testing" - cselectors "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + cselectors "github.com/smartcontractkit/chain-selectors" ) -func Test_GetChainSelectorFamily(t *testing.T) { +func TestGetChainSelectorFamily(t *testing.T) { t.Parallel() tests := []struct { diff --git a/types/config.go b/types/config.go index 81cc0dc8e..a02fa791d 100644 --- a/types/config.go +++ b/types/config.go @@ -1,4 +1,4 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' import ( "errors" diff --git a/types/config_test.go b/types/config_test.go index d317968e6..9b5d97b0b 100644 --- a/types/config_test.go +++ b/types/config_test.go @@ -1,4 +1,4 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' import ( "testing" @@ -16,7 +16,7 @@ var ( signer4 = common.HexToAddress("0x4") ) -func Test_NewConfig(t *testing.T) { +func TestNewConfig(t *testing.T) { t.Parallel() var ( @@ -41,7 +41,7 @@ func Test_NewConfig(t *testing.T) { assert.Equal(t, Config{}, got) } -func Test_Config_Validate(t *testing.T) { +func TestConfig_Validate(t *testing.T) { t.Parallel() tests := []struct { @@ -116,7 +116,7 @@ func Test_Config_Validate(t *testing.T) { } } -func Test_Config_Equals(t *testing.T) { +func TestConfig_Equals(t *testing.T) { t.Parallel() // The config that is being matched against. This is compared against the give field in @@ -198,7 +198,7 @@ func Test_Config_Equals(t *testing.T) { }) } } -func Test_Config_GetAllSigners(t *testing.T) { +func TestConfig_GetAllSigners(t *testing.T) { t.Parallel() tests := []struct { @@ -255,7 +255,7 @@ func Test_Config_GetAllSigners(t *testing.T) { } } -func Test_Config_CanSetRoot(t *testing.T) { +func TestConfig_CanSetRoot(t *testing.T) { t.Parallel() tests := []struct { @@ -348,7 +348,7 @@ func Test_Config_CanSetRoot(t *testing.T) { } } -func Test_unorderedArrayEquals(t *testing.T) { +func TestUnorderedArrayEquals(t *testing.T) { t.Parallel() tests := []struct { diff --git a/types/duration.go b/types/duration.go index 5330d8a02..ea6af8e4f 100644 --- a/types/duration.go +++ b/types/duration.go @@ -1,4 +1,4 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' import ( "encoding/json" diff --git a/types/duration_test.go b/types/duration_test.go index 82cf3d4b2..d88eef7c7 100644 --- a/types/duration_test.go +++ b/types/duration_test.go @@ -1,4 +1,4 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' import ( "testing" @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" ) -func Test_NewDuration(t *testing.T) { +func TestNewDuration(t *testing.T) { t.Parallel() d, err := time.ParseDuration("1h") @@ -17,7 +17,7 @@ func Test_NewDuration(t *testing.T) { assert.Equal(t, Duration{Duration: d}, NewDuration(d)) } -func Test_ParseDuration(t *testing.T) { +func TestParseDuration(t *testing.T) { t.Parallel() tests := []struct { @@ -55,7 +55,7 @@ func Test_ParseDuration(t *testing.T) { } } -func Test_MustParseDuration(t *testing.T) { +func TestMustParseDuration(t *testing.T) { t.Parallel() assert.NotPanics(t, func() { @@ -71,7 +71,7 @@ func Test_MustParseDuration(t *testing.T) { }) } -func Test_Duration_String(t *testing.T) { +func TestDuration_String(t *testing.T) { t.Parallel() d, err := time.ParseDuration("1h") @@ -80,7 +80,7 @@ func Test_Duration_String(t *testing.T) { assert.Equal(t, "1h0m0s", NewDuration(d).String()) } -func Test_Duration_MarshalJSON(t *testing.T) { +func TestDuration_MarshalJSON(t *testing.T) { t.Parallel() tests := []struct { @@ -113,7 +113,7 @@ func Test_Duration_MarshalJSON(t *testing.T) { } } -func Test_Duration_UnmarshalJSON(t *testing.T) { +func TestDuration_UnmarshalJSON(t *testing.T) { t.Parallel() tests := []struct { diff --git a/types/operation.go b/types/operation.go index 47c98808e..97fc2083d 100644 --- a/types/operation.go +++ b/types/operation.go @@ -1,4 +1,4 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' import "encoding/json" diff --git a/types/proposal_kind.go b/types/proposal_kind.go index 63abb5b9f..55c205fa9 100644 --- a/types/proposal_kind.go +++ b/types/proposal_kind.go @@ -1,4 +1,4 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' type ProposalKind string diff --git a/types/signature.go b/types/signature.go index bd456ea07..0cbe9dc6d 100644 --- a/types/signature.go +++ b/types/signature.go @@ -1,6 +1,8 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' import ( + "crypto/ecdsa" + "errors" "fmt" "slices" @@ -50,13 +52,25 @@ func (s Signature) ToBytes() []byte { ) } -// Recover returns the address of the hash that been recovered from the signature. +// Recover returns the address recovered from the signature and the message hash func (s Signature) Recover(hash common.Hash) (common.Address, error) { + // Recover the public key from the signature and the message hash + pubKey, err := s.RecoverPublicKey(hash) + if err != nil { + return common.Address{}, fmt.Errorf("failed to recover public key: %w", err) + } + + // Derive the (recovered) Ethereum address from the public key + return crypto.PubkeyToAddress(*pubKey), nil +} + +// Recover returns the public key recovered from the signature and the message hash +func (s Signature) RecoverPublicKey(hash common.Hash) (*ecdsa.PublicKey, error) { sig := s.ToBytes() // The signature should be 65 bytes, and the last byte is the recovery id (v). if len(sig) != SignatureBytesLength { - return common.Address{}, fmt.Errorf("invalid signature length") + return &ecdsa.PublicKey{}, errors.New("invalid signature length") } // Adjust the recovery id (v) if needed. Ethereum signatures expect 27 or 28. @@ -66,13 +80,5 @@ func (s Signature) Recover(hash common.Hash) (common.Address, error) { } // Recover the public key from the signature and the message hash - pubKey, err := crypto.SigToPub(hash.Bytes(), sig) - if err != nil { - return common.Address{}, err - } - - // Derive the Ethereum address from the public key - recoveredAddr := crypto.PubkeyToAddress(*pubKey) - - return recoveredAddr, nil + return crypto.SigToPub(hash.Bytes(), sig) } diff --git a/types/signature_test.go b/types/signature_test.go index 78c028e9e..fad31cfea 100644 --- a/types/signature_test.go +++ b/types/signature_test.go @@ -1,4 +1,4 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' import ( "testing" @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" ) -func Test_NewSignatureFromBytes(t *testing.T) { +func TestNewSignatureFromBytes(t *testing.T) { t.Parallel() tests := []struct { @@ -60,7 +60,7 @@ func Test_NewSignatureFromBytes(t *testing.T) { } } -func Test_ToBytes(t *testing.T) { +func TestToBytes(t *testing.T) { t.Parallel() sig := Signature{ @@ -85,7 +85,7 @@ func Test_ToBytes(t *testing.T) { assert.Equal(t, want, got) } -func Test_Recover(t *testing.T) { +func TestRecover(t *testing.T) { t.Parallel() // Private key to use for signing @@ -132,7 +132,7 @@ func Test_Recover(t *testing.T) { V: 1, }, giveHash: hash, - wantErr: "recovery failed", + wantErr: "failed to recover public key: recovery failed", }, } diff --git a/types/timelock.go b/types/timelock.go index 610330b3f..4383cdacb 100644 --- a/types/timelock.go +++ b/types/timelock.go @@ -1,4 +1,4 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' // TimelockAction is an enum for the different types of timelock actions that can be performed on // a timelock proposal. diff --git a/types/transaction.go b/types/transaction.go index 5568b0979..054dd262c 100644 --- a/types/transaction.go +++ b/types/transaction.go @@ -1,4 +1,4 @@ -package types +package types //nolint:revive,nolintlint // allow pkg name 'types' // TransactionResult represents a generic blockchain transaction. // It contains the hash of the transaction and the transaction itself. diff --git a/validation.go b/validation.go index 5f11cf85b..e8fe35076 100644 --- a/validation.go +++ b/validation.go @@ -6,11 +6,12 @@ import ( cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/sdk/solana" "github.com/smartcontractkit/mcms/sdk/sui" - "github.com/smartcontractkit/mcms/types" ) func validateAdditionalFields(additionalFields json.RawMessage, csel types.ChainSelector) error { diff --git a/validation_test.go b/validation_test.go index c2397284b..5b9851277 100644 --- a/validation_test.go +++ b/validation_test.go @@ -6,11 +6,13 @@ import ( "math/big" "testing" - solana2 "github.com/gagliardetto/solana-go" - cselectors "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + solana2 "github.com/gagliardetto/solana-go" + + cselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/mcms/internal/testutils/chaintest" "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/sdk/evm" From 0051860b1492b1c4fd1e2457b7c31bb6ac50e600 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Dec 2025 06:53:50 -0600 Subject: [PATCH 10/26] build(deps-dev): bump @changesets/changelog-github from 0.5.0 to 0.5.2 (#556) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@changesets/changelog-github](https://github.com/changesets/changesets) from 0.5.0 to 0.5.2.
Release notes

Sourced from @​changesets/changelog-github's releases.

@​changesets/changelog-github@​0.5.1

Patch Changes

  • Updated dependencies [84a4a1b]:
    • @​changesets/types@​6.1.0
Commits
  • 4f8d76c Version Packages (#670)
  • d8f0e68 Fixed an issue with parsing --json output when publishing (#676)
  • fe8db75 Upgrade @manypkg/get-packages dependencies to latest version (#667)
  • 9a993ba Add resolutions to the PackageJSON type (#668)
  • a8c8a03 Version Packages (#663)
  • 5413f3e Fixed an issue with adding [undefined] to the generated changelog (#660)
  • 74dda8c Add support for workspace:~ and workspace:^ (#585)
  • 2b49c39 Implement changeset tag and getAllTags (#634)
  • 09a7dab Make master branch rename suggestion more clear (#638)
  • a3628d5 Helpful note about status command (#639)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@changesets/changelog-github&package-manager=npm_and_yarn&previous-version=0.5.0&new-version=0.5.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- pnpm-lock.yaml | 25 ++++++++++--------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index b43b3e5ca..5932f6ff1 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "author": "@smartcontractkit", "devDependencies": { - "@changesets/changelog-github": "^0.5.0", + "@changesets/changelog-github": "^0.5.2", "@changesets/cli": "~2.29.7", "changeset": "^0.2.6" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0b8aa7cfc..e21810f7f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: devDependencies: '@changesets/changelog-github': - specifier: ^0.5.0 - version: 0.5.0 + specifier: ^0.5.2 + version: 0.5.2 '@changesets/cli': specifier: ~2.29.7 version: 2.29.7 @@ -33,8 +33,8 @@ packages: '@changesets/changelog-git@0.2.1': resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} - '@changesets/changelog-github@0.5.0': - resolution: {integrity: sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA==} + '@changesets/changelog-github@0.5.2': + resolution: {integrity: sha512-HeGeDl8HaIGj9fQHo/tv5XKQ2SNEi9+9yl1Bss1jttPqeiASRXhfi0A2wv8yFKCp07kR1gpOI5ge6+CWNm1jPw==} '@changesets/cli@2.29.7': resolution: {integrity: sha512-R7RqWoaksyyKXbKXBTbT4REdy22yH81mcFK6sWtqSanxUCbUi9Uf+6aqxZtDQouIqPdem2W56CdxXgsxdq7FLQ==} @@ -49,8 +49,8 @@ packages: '@changesets/get-dependents-graph@2.1.3': resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} - '@changesets/get-github-info@0.6.0': - resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} + '@changesets/get-github-info@0.7.0': + resolution: {integrity: sha512-+i67Bmhfj9V4KfDeS1+Tz3iF32btKZB2AAx+cYMqDSRFP7r3/ZdGbjCo+c6qkyViN9ygDuBjzageuPGJtKGe5A==} '@changesets/get-release-plan@4.0.13': resolution: {integrity: sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==} @@ -79,9 +79,6 @@ packages: '@changesets/types@4.1.0': resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} - '@changesets/types@6.0.0': - resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} - '@changesets/types@6.1.0': resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} @@ -464,10 +461,10 @@ snapshots: dependencies: '@changesets/types': 6.1.0 - '@changesets/changelog-github@0.5.0': + '@changesets/changelog-github@0.5.2': dependencies: - '@changesets/get-github-info': 0.6.0 - '@changesets/types': 6.0.0 + '@changesets/get-github-info': 0.7.0 + '@changesets/types': 6.1.0 dotenv: 8.6.0 transitivePeerDependencies: - encoding @@ -526,7 +523,7 @@ snapshots: picocolors: 1.1.1 semver: 7.7.2 - '@changesets/get-github-info@0.6.0': + '@changesets/get-github-info@0.7.0': dependencies: dataloader: 1.4.0 node-fetch: 2.7.0 @@ -585,8 +582,6 @@ snapshots: '@changesets/types@4.1.0': {} - '@changesets/types@6.0.0': {} - '@changesets/types@6.1.0': {} '@changesets/write@0.4.0': From 7e176583b1a1c504e91f3291d738488b24f1115a Mon Sep 17 00:00:00 2001 From: Rodrigo Soares <38868277+rodrigombsoares@users.noreply.github.com> Date: Mon, 12 Jan 2026 13:02:20 -0300 Subject: [PATCH 11/26] feat(sui): integrate timelock converter (#570) # Summary Sui Timelock converter existed, but wasn't integrated into `OperationCounts`. This PR fixes this. --- timelock_proposal.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/timelock_proposal.go b/timelock_proposal.go index 7d3905050..09562e1a0 100644 --- a/timelock_proposal.go +++ b/timelock_proposal.go @@ -21,6 +21,7 @@ import ( "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/sdk/solana" + "github.com/smartcontractkit/mcms/sdk/sui" "github.com/smartcontractkit/mcms/types" ) @@ -291,6 +292,11 @@ func (m *TimelockProposal) buildTimelockConverters() (map[types.ChainSelector]sd converter = solana.NewTimelockConverter() case chain_selectors.FamilyAptos: converter = aptos.NewTimelockConverter() + case chain_selectors.FamilySui: + converter, err = sui.NewTimelockConverter() + if err != nil { + return nil, fmt.Errorf("failed to create Sui timelock converter: %w", err) + } default: return nil, fmt.Errorf("unsupported chain family %s", fam) } From 8aad17cd8cb3f3c55097faa5159c15ccccc47f2e Mon Sep 17 00:00:00 2001 From: gustavogama-cll <165679773+gustavogama-cll@users.noreply.github.com> Date: Mon, 12 Jan 2026 14:52:29 -0300 Subject: [PATCH 12/26] chore: bump version (#571) --- .changeset/smooth-pugs-tease.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/smooth-pugs-tease.md diff --git a/.changeset/smooth-pugs-tease.md b/.changeset/smooth-pugs-tease.md new file mode 100644 index 000000000..e7a9c8175 --- /dev/null +++ b/.changeset/smooth-pugs-tease.md @@ -0,0 +1,5 @@ +--- +"@smartcontractkit/mcms": minor +--- + +chore: bump version From a5ab214ebd6136885ca68d858a12480f3c35ed96 Mon Sep 17 00:00:00 2001 From: "app-token-issuer-engops[bot]" <144731339+app-token-issuer-engops[bot]@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:13:46 -0300 Subject: [PATCH 13/26] Version Packages (#572) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @smartcontractkit/mcms@0.32.0 ### Minor Changes - [#571](https://github.com/smartcontractkit/mcms/pull/571) [`141dc6f`](https://github.com/smartcontractkit/mcms/commit/141dc6fceb2a194524ab36bb7addbe37eb28e9a5) Thanks [@gustavogama-cll](https://github.com/gustavogama-cll)! - chore: bump version Co-authored-by: app-token-issuer-engops[bot] <144731339+app-token-issuer-engops[bot]@users.noreply.github.com> --- .changeset/smooth-pugs-tease.md | 5 ----- CHANGELOG.md | 6 ++++++ package.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) delete mode 100644 .changeset/smooth-pugs-tease.md diff --git a/.changeset/smooth-pugs-tease.md b/.changeset/smooth-pugs-tease.md deleted file mode 100644 index e7a9c8175..000000000 --- a/.changeset/smooth-pugs-tease.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@smartcontractkit/mcms": minor ---- - -chore: bump version diff --git a/CHANGELOG.md b/CHANGELOG.md index 57f688264..26f5cf357 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # @smartcontractkit/mcms +## 0.32.0 + +### Minor Changes + +- [#571](https://github.com/smartcontractkit/mcms/pull/571) [`141dc6f`](https://github.com/smartcontractkit/mcms/commit/141dc6fceb2a194524ab36bb7addbe37eb28e9a5) Thanks [@gustavogama-cll](https://github.com/gustavogama-cll)! - chore: bump version + ## 0.31.1 ### Patch Changes diff --git a/package.json b/package.json index 5932f6ff1..147b0aff9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@smartcontractkit/mcms", - "version": "0.31.1", + "version": "0.32.0", "description": "Tools/Libraries to Deploy/Manage/Interact with MCMS", "private": true, "scripts": { From 3a6f011891afb141d7509091be342e7bd07a5777 Mon Sep 17 00:00:00 2001 From: Pablo Estrada <139084212+ecPablo@users.noreply.github.com> Date: Wed, 14 Jan 2026 12:36:03 -0600 Subject: [PATCH 14/26] fix: change pointer receiver evm converter (#576) Changing for consistency across the rest of chain family sdks --------- Signed-off-by: Pablo --- .changeset/eleven-apes-hug.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/eleven-apes-hug.md diff --git a/.changeset/eleven-apes-hug.md b/.changeset/eleven-apes-hug.md new file mode 100644 index 000000000..36d27c1c4 --- /dev/null +++ b/.changeset/eleven-apes-hug.md @@ -0,0 +1,5 @@ +--- +"@smartcontractkit/mcms": patch +--- + +update TimelockConverter in evm to use non-pointer receiver From 241f0a0397a7cc1046f0a47b63e51a7cc240c68f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 12:47:05 -0600 Subject: [PATCH 15/26] build(deps): bump github.com/smartcontractkit/chain-selectors from 1.0.85 to 1.0.89 (#574) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/smartcontractkit/chain-selectors](https://github.com/smartcontractkit/chain-selectors) from 1.0.85 to 1.0.89.
Release notes

Sourced from github.com/smartcontractkit/chain-selectors's releases.

v1.0.89

What's Changed

Full Changelog: https://github.com/smartcontractkit/chain-selectors/compare/v1.0.88...v1.0.89

v1.0.88

What's Changed

Full Changelog: https://github.com/smartcontractkit/chain-selectors/compare/v1.0.87...v1.0.88

v1.0.87

What's Changed

Full Changelog: https://github.com/smartcontractkit/chain-selectors/compare/v1.0.86...v1.0.87

v1.0.86

What's Changed

New Contributors

Full Changelog: https://github.com/smartcontractkit/chain-selectors/compare/v1.0.85...v1.0.86

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/smartcontractkit/chain-selectors&package-manager=go_modules&previous-version=1.0.85&new-version=1.0.89)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f1556fe53..a8072b4e1 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/joho/godotenv v1.5.1 github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 github.com/samber/lo v1.49.1 - github.com/smartcontractkit/chain-selectors v1.0.85 + github.com/smartcontractkit/chain-selectors v1.0.89 github.com/smartcontractkit/chainlink-aptos v0.0.0-20251024142440-51f2ad2652a2 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a diff --git a/go.sum b/go.sum index efbd71199..7dd33d0a9 100644 --- a/go.sum +++ b/go.sum @@ -626,8 +626,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/chain-selectors v1.0.85 h1:A7eyN7KIACxmngn1MJJ0giVtfELK9vh/eYyNU/Q/sFo= -github.com/smartcontractkit/chain-selectors v1.0.85/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.89 h1:L9oWZGqQXWyTPnC6ODXgu3b0DFyLmJ9eHv+uJrE9IZY= +github.com/smartcontractkit/chain-selectors v1.0.89/go.mod h1:qy7whtgG5g+7z0jt0nRyii9bLND9m15NZTzuQPkMZ5w= github.com/smartcontractkit/chainlink-aptos v0.0.0-20251024142440-51f2ad2652a2 h1:vGdeMwHO3ow88HvxfhA4DDPYNY0X9jmdux7L83UF/W8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20251024142440-51f2ad2652a2/go.mod h1:iteU0WORHkArACVh/HoY/1bipV4TcNcJdTmom9uIT0E= github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20251024142759-093ed1b4017f h1:jP2BHA7+QSp5IzWykT8KunThNbSwEM9j6lCXwEoxTIc= From 4aa9bd896a5ef98fbbb3819c9abf3776e74ba795 Mon Sep 17 00:00:00 2001 From: Kristijan Rebernisak Date: Thu, 15 Jan 2026 19:29:55 +0100 Subject: [PATCH 16/26] Add TON support (#486) Co-authored-by: Joe Huang --- .changeset/long-snakes-ring.md | 5 + .github/CODEOWNERS | 3 + .github/workflows/pull-request-main-nix.yml | 56 + .mockery.yaml | 18 + e2e/config.ton.toml | 18 + e2e/tests/aptos/set_config.go | 3 +- e2e/tests/runner_test.go | 10 + e2e/tests/setup.go | 32 + e2e/tests/sui/set_config.go | 3 +- e2e/tests/ton/common.go | 122 ++ e2e/tests/ton/executable.go | 785 ++++++++++ e2e/tests/ton/inspection.go | 130 ++ e2e/tests/ton/set_config.go | 235 +++ e2e/tests/ton/set_root.go | 279 ++++ e2e/tests/ton/signing.go | 12 + e2e/tests/ton/timelock_inspection.go | 419 +++++ factory.go | 12 + factory_test.go | 16 + flake.lock | 147 ++ flake.nix | 38 + go.mod | 60 +- go.sum | 130 +- internal/testutils/chaintest/testchain.go | 4 + internal/testutils/signer.go | 3 +- sdk/evm/timelock_converter.go | 5 +- sdk/evm/timelock_converter_test.go | 14 +- sdk/sui/transaction_test.go | 2 +- sdk/ton/common.go | 62 + sdk/ton/common_test.go | 19 + sdk/ton/config_transformer.go | 206 +++ sdk/ton/config_transformer_test.go | 428 +++++ sdk/ton/configurer.go | 117 ++ sdk/ton/configurer_test.go | 195 +++ sdk/ton/decoded_operation.go | 59 + sdk/ton/decoded_operation_test.go | 92 ++ sdk/ton/decoder.go | 77 + sdk/ton/decoder_test.go | 119 ++ sdk/ton/encoder.go | 214 +++ sdk/ton/encoder_test.go | 269 ++++ sdk/ton/executor.go | 199 +++ sdk/ton/executor_test.go | 425 +++++ sdk/ton/inspector.go | 104 ++ sdk/ton/inspector_test.go | 386 +++++ sdk/ton/mocks/api.go | 1570 +++++++++++++++++++ sdk/ton/mocks/wallet.go | 347 ++++ sdk/ton/timelock_converter.go | 168 ++ sdk/ton/timelock_converter_test.go | 156 ++ sdk/ton/timelock_executor.go | 97 ++ sdk/ton/timelock_executor_test.go | 203 +++ sdk/ton/timelock_inspector.go | 126 ++ sdk/ton/timelock_inspector_test.go | 568 +++++++ sdk/ton/transaction.go | 68 + sdk/ton/transaction_test.go | 107 ++ shell.nix | 56 + signable_test.go | 2 +- taskfiles/test/Taskfile.yml | 12 + types/chain_selector.go | 1 + types/config_test.go | 2 +- validation.go | 8 + 59 files changed, 8919 insertions(+), 104 deletions(-) create mode 100644 .changeset/long-snakes-ring.md create mode 100644 .github/workflows/pull-request-main-nix.yml create mode 100644 e2e/config.ton.toml create mode 100644 e2e/tests/ton/common.go create mode 100644 e2e/tests/ton/executable.go create mode 100644 e2e/tests/ton/inspection.go create mode 100644 e2e/tests/ton/set_config.go create mode 100644 e2e/tests/ton/set_root.go create mode 100644 e2e/tests/ton/signing.go create mode 100644 e2e/tests/ton/timelock_inspection.go create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 sdk/ton/common.go create mode 100644 sdk/ton/common_test.go create mode 100644 sdk/ton/config_transformer.go create mode 100644 sdk/ton/config_transformer_test.go create mode 100644 sdk/ton/configurer.go create mode 100644 sdk/ton/configurer_test.go create mode 100644 sdk/ton/decoded_operation.go create mode 100644 sdk/ton/decoded_operation_test.go create mode 100644 sdk/ton/decoder.go create mode 100644 sdk/ton/decoder_test.go create mode 100644 sdk/ton/encoder.go create mode 100644 sdk/ton/encoder_test.go create mode 100644 sdk/ton/executor.go create mode 100644 sdk/ton/executor_test.go create mode 100644 sdk/ton/inspector.go create mode 100644 sdk/ton/inspector_test.go create mode 100644 sdk/ton/mocks/api.go create mode 100644 sdk/ton/mocks/wallet.go create mode 100644 sdk/ton/timelock_converter.go create mode 100644 sdk/ton/timelock_converter_test.go create mode 100644 sdk/ton/timelock_executor.go create mode 100644 sdk/ton/timelock_executor_test.go create mode 100644 sdk/ton/timelock_inspector.go create mode 100644 sdk/ton/timelock_inspector_test.go create mode 100644 sdk/ton/transaction.go create mode 100644 sdk/ton/transaction_test.go create mode 100644 shell.nix diff --git a/.changeset/long-snakes-ring.md b/.changeset/long-snakes-ring.md new file mode 100644 index 000000000..6e6c8c304 --- /dev/null +++ b/.changeset/long-snakes-ring.md @@ -0,0 +1,5 @@ +--- +"@smartcontractkit/mcms": minor +--- + +Add TON implementation and unit/e2e tests diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f10f8abca..56b6be4b4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1,4 @@ * @smartcontractkit/op-tooling + +# Nix shell setup (supports TON e2e tests) +/.github/workflows/pull-request-main-nix.yml @smartcontractkit/ccip-ton diff --git a/.github/workflows/pull-request-main-nix.yml b/.github/workflows/pull-request-main-nix.yml new file mode 100644 index 000000000..0170328c8 --- /dev/null +++ b/.github/workflows/pull-request-main-nix.yml @@ -0,0 +1,56 @@ +name: pull-request-main-nix + +on: + merge_group: + pull_request: + branches: + - main + push: + branches: + - main + +jobs: + ci-test-e2e: + name: Tests E2E - Nix setup + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + actions: read + steps: + - name: Install Nix + uses: cachix/install-nix-action@02a151ada4993995686f9ed4f1be7cfbb229e56f # v31 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build TON contracts + id: ton-contracts-build + shell: bash + run: | + PATH_CONTRACTS_TON_PKG="$(nix build .#chainlink-ton-contracts --print-out-paths)/" + PATH_CONTRACTS_TON="$PATH_CONTRACTS_TON_PKG/lib/node_modules/@chainlink/contracts-ton/build/" + echo "path=$PATH_CONTRACTS_TON" >> "$GITHUB_OUTPUT" + + - name: Run e2e tests + uses: smartcontractkit/.github/actions/ci-test-go@ci-test-go/1.0.0 + with: + checkout-repo: false + use-go-cache: true + go-test-cmd: | + set +e + + echo "::group::TON" + export PATH_CONTRACTS_TON="${{ steps.ton-contracts-build.outputs.path }}" + CTF_CONFIGS=../config.ton.toml go test -p=1 -tags=e2e -v ./e2e/tests/... -run=TestTONSuite || ton_failure=true + echo "::endgroup::" + + [[ -n "${ton_failure}" ]] && echo "🚨 TON e2e tests failed." + [[ -n "${ton_failure}" ]] && { + exit 1 + } || { + echo "Exiting" + exit 0 + } diff --git a/.mockery.yaml b/.mockery.yaml index 26ca3c0bb..6614b1716 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -14,6 +14,24 @@ mockname: "{{.InterfaceName}}" inpackage: false outpkg: mocks packages: + github.com/xssnick/tonutils-go/ton/wallet: + config: + all: false + outpkg: "mock_ton" + interfaces: + TonAPI: + config: + dir: "./sdk/ton/mocks" + filename: "wallet.go" + github.com/xssnick/tonutils-go/ton: + config: + all: false + outpkg: "mock_ton" + interfaces: + APIClientWrapped: + config: + dir: "./sdk/ton/mocks" + filename: "api.go" github.com/smartcontractkit/mcms/inspectors: github.com/smartcontractkit/mcms/sdk: github.com/smartcontractkit/mcms/sdk/evm: diff --git a/e2e/config.ton.toml b/e2e/config.ton.toml new file mode 100644 index 000000000..5d0607301 --- /dev/null +++ b/e2e/config.ton.toml @@ -0,0 +1,18 @@ +[settings] +private_keys = [ + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", + "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a" +] + +[ton_config] +chain_id = "-217" +type = "ton" +image = "ghcr.io/neodix42/mylocalton-docker:v3.98" + +[ton_config.out] +family = "ton" + +[ton_config.custom_env] +NEXT_BLOCK_GENERATION_DELAY = "0.5" +VERSION_CAPABILITIES = "12" diff --git a/e2e/tests/aptos/set_config.go b/e2e/tests/aptos/set_config.go index d8c8c809a..721ed34ea 100644 --- a/e2e/tests/aptos/set_config.go +++ b/e2e/tests/aptos/set_config.go @@ -4,7 +4,6 @@ package aptos import ( "slices" - "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -30,7 +29,7 @@ func (a *TestSuite) TestSetConfig() { signers[i] = crypto.PubkeyToAddress(key.PublicKey) } slices.SortFunc(signers[:], func(a, b common.Address) int { - return strings.Compare(strings.ToLower(a.Hex()), strings.ToLower(b.Hex())) + return a.Cmp(b) }) bypasserConfig := &types.Config{ diff --git a/e2e/tests/runner_test.go b/e2e/tests/runner_test.go index caaae0074..a04ff50e7 100644 --- a/e2e/tests/runner_test.go +++ b/e2e/tests/runner_test.go @@ -11,6 +11,7 @@ import ( evme2e "github.com/smartcontractkit/mcms/e2e/tests/evm" solanae2e "github.com/smartcontractkit/mcms/e2e/tests/solana" suie2e "github.com/smartcontractkit/mcms/e2e/tests/sui" + tone2e "github.com/smartcontractkit/mcms/e2e/tests/ton" ) func TestEVMSuite(t *testing.T) { @@ -39,3 +40,12 @@ func TestSuiSuite(t *testing.T) { suite.Run(t, new(suie2e.TimelockCancelProposalTestSuite)) suite.Run(t, new(suie2e.MCMSUserUpgradeTestSuite)) } + +func TestTONSuite(t *testing.T) { + suite.Run(t, new(tone2e.SigningTestSuite)) + suite.Run(t, new(tone2e.SetConfigTestSuite)) + suite.Run(t, new(tone2e.SetRootTestSuite)) + suite.Run(t, new(tone2e.InspectionTestSuite)) + suite.Run(t, new(tone2e.ExecutionTestSuite)) + suite.Run(t, new(tone2e.TimelockInspectionTestSuite)) +} diff --git a/e2e/tests/setup.go b/e2e/tests/setup.go index 6deec0774..9aa6f374d 100644 --- a/e2e/tests/setup.go +++ b/e2e/tests/setup.go @@ -18,6 +18,9 @@ import ( "github.com/gagliardetto/solana-go/rpc/ws" "github.com/joho/godotenv" "github.com/stretchr/testify/require" + "github.com/xssnick/tonutils-go/ton" + + tonchain "github.com/smartcontractkit/chainlink-ton/pkg/ton/chain" "github.com/smartcontractkit/chainlink-testing-framework/framework" "github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain" @@ -39,6 +42,7 @@ type Config struct { SolanaChain *blockchain.Input `toml:"solana_config"` AptosChain *blockchain.Input `toml:"aptos_config"` SuiChain *blockchain.Input `toml:"sui_config"` + TonChain *blockchain.Input `toml:"ton_config"` Settings struct { PrivateKeys []string `toml:"private_keys"` @@ -57,6 +61,8 @@ type TestSetup struct { AptosBlockchain *blockchain.Output SuiClient sui.ISuiAPI SuiBlockchain *blockchain.Output + TonClient *ton.APIClient + TonBlockchain *blockchain.Output Config } @@ -203,6 +209,30 @@ func InitializeSharedTestSetup(t *testing.T) *TestSetup { t.Logf("Initialized Sui RPC client @ %s", nodeURL) } + var ( + tonClient *ton.APIClient + tonBlockchainOutput *blockchain.Output + ) + if in.TonChain != nil { + // Use blockchain network setup (fallback) + ports := freeport.GetN(t, 2) + port := ports[0] + faucetPort := ports[1] + in.TonChain.Port = strconv.Itoa(port) + in.TonChain.FaucetPort = strconv.Itoa(faucetPort) + + tonBlockchainOutput, err = blockchain.NewBlockchainNetwork(in.TonChain) + require.NoError(t, err, "Failed to initialize TON blockchain") + + nodeURL := tonBlockchainOutput.Nodes[0].ExternalHTTPUrl + pool, err := tonchain.CreateLiteserverConnectionPool(ctx, nodeURL) + require.NoError(t, err, "Failed to initialize TON client - failed to create liteserver connection pool") + tonClient = ton.NewAPIClient(pool, ton.ProofCheckPolicyFast) + + // Test liveness, will also fetch ChainID + t.Logf("Initialized TON RPC client @ %s", nodeURL) + } + sharedSetup = &TestSetup{ ClientA: ethClientA, ClientB: ethClientB, @@ -213,6 +243,8 @@ func InitializeSharedTestSetup(t *testing.T) *TestSetup { AptosBlockchain: aptosBlockchainOutput, SuiClient: suiClient, SuiBlockchain: suiBlockchainOutput, + TonClient: tonClient, + TonBlockchain: tonBlockchainOutput, Config: *in, } }) diff --git a/e2e/tests/sui/set_config.go b/e2e/tests/sui/set_config.go index 7d52bc77c..12b4d37b3 100644 --- a/e2e/tests/sui/set_config.go +++ b/e2e/tests/sui/set_config.go @@ -4,7 +4,6 @@ package sui import ( "slices" - "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -26,7 +25,7 @@ func (s *TestSuite) TestSetConfig() { signers[i] = crypto.PubkeyToAddress(key.PublicKey) } slices.SortFunc(signers[:], func(a, b common.Address) int { - return strings.Compare(strings.ToLower(a.Hex()), strings.ToLower(b.Hex())) + return a.Cmp(b) }) bypasserConfig := &types.Config{ diff --git a/e2e/tests/ton/common.go b/e2e/tests/ton/common.go new file mode 100644 index 000000000..0ba737fd4 --- /dev/null +++ b/e2e/tests/ton/common.go @@ -0,0 +1,122 @@ +//go:build e2e + +package tone2e + +import ( + "context" + "fmt" + "os" + "path/filepath" + + "github.com/ethereum/go-ethereum/common" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/ton/wallet" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/timelock" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/wrappers" + + "github.com/smartcontractkit/mcms/internal/testutils" + "github.com/smartcontractkit/mcms/types" +) + +const ( + EnvPathContracts = "PATH_CONTRACTS_TON" + + PathContractsMCMS = "mcms.MCMS.compiled.json" + PathContractsTimelock = "mcms.RBACTimelock.compiled.json" +) + +func must[E any](out E, err error) E { + if err != nil { + panic(err) + } + + return out +} + +type DeployOpts struct { + // Connection + Client *ton.APIClient + Wallet *wallet.Wallet + + // Deployment info + ContractPath string + + Amount tlb.Coins + Data any + Body any +} + +func DeployContract(ctx context.Context, opts DeployOpts) (*address.Address, error) { + contractCode, err := wrappers.ParseCompiledContract(opts.ContractPath) + if err != nil { + return nil, fmt.Errorf("failed to parse compiled contract: %w", err) + } + + contractData, ok := opts.Data.(*cell.Cell) // Cell or we try to decode + if !ok { + contractData, err = tlb.ToCell(opts.Data) + if err != nil { + return nil, fmt.Errorf("failed to create contract data cell: %w", err) + } + } + + bodyCell, ok := opts.Body.(*cell.Cell) // Cell or we try to decode + if !ok { + bodyCell, err = tlb.ToCell(opts.Body) + if err != nil { + return nil, fmt.Errorf("failed to create contract body cell: %w", err) + } + } + + _client := tracetracking.NewSignedAPIClient(opts.Client, *opts.Wallet) + contract, _, err := wrappers.Deploy(ctx, &_client, contractCode, contractData, opts.Amount, bodyCell) + if err != nil { + return nil, fmt.Errorf("failed to deploy contract: %w", err) + } + + return contract.Address, nil +} + +func DeployMCMSContract(ctx context.Context, client *ton.APIClient, w *wallet.Wallet, amount tlb.Coins, data mcms.Data) (*address.Address, error) { + return DeployContract(ctx, DeployOpts{ + Client: client, + Wallet: w, + ContractPath: filepath.Join(os.Getenv(EnvPathContracts), PathContractsMCMS), + Amount: amount, + Data: data, + Body: cell.BeginCell().EndCell(), // empty cell, top up + }) +} + +func DeployTimelockContract(ctx context.Context, client *ton.APIClient, w *wallet.Wallet, amount tlb.Coins, data timelock.Data, body timelock.Init) (*address.Address, error) { + return DeployContract(ctx, DeployOpts{ + Client: client, + Wallet: w, + ContractPath: filepath.Join(os.Getenv(EnvPathContracts), PathContractsTimelock), + Amount: amount, + Data: data, + Body: body, + }) +} + +// GenSimpleTestMCMSConfig generates a simple test configuration that's used in e2e tests. +func GenSimpleTestMCMSConfig(signers []testutils.ECDSASigner) *types.Config { + return &types.Config{ + Quorum: 1, + Signers: []common.Address{signers[0].Address()}, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{signers[1].Address()}, + GroupSigners: []types.Config{}, + }, + }, + } +} diff --git a/e2e/tests/ton/executable.go b/e2e/tests/ton/executable.go new file mode 100644 index 000000000..925aad6c3 --- /dev/null +++ b/e2e/tests/ton/executable.go @@ -0,0 +1,785 @@ +//go:build e2e + +package tone2e + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "strconv" + + "github.com/stretchr/testify/suite" + + cselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton/wallet" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/lib/access/rbac" + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/timelock" + toncommon "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/hash" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + "github.com/ethereum/go-ethereum/common" + + mcmslib "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/sdk/evm" + "github.com/smartcontractkit/mcms/types" + + e2e "github.com/smartcontractkit/mcms/e2e/tests" + "github.com/smartcontractkit/mcms/internal/testutils" + + mcmston "github.com/smartcontractkit/mcms/sdk/ton" +) + +type ExecutionTestSuite struct { + suite.Suite + + signers []testutils.ECDSASigner + + // Sign proposals across multiple chains, execute and verify on Chain A + ChainA types.ChainSelector + ChainB types.ChainSelector + ChainC types.ChainSelector + + // Chain A metadata + mcmsAddr string + timelockAddr string + + wallet *wallet.Wallet + + e2e.TestSetup +} + +// SetupSuite runs before the test suite +func (s *ExecutionTestSuite) SetupSuite() { + s.TestSetup = *e2e.InitializeSharedTestSetup(s.T()) + + // Init wallet + var err error + s.wallet, err = tvm.MyLocalTONWalletDefault(s.TonClient) + s.Require().NoError(err) + + // Generate few test signers + s.signers = testutils.MakeNewECDSASigners(2) + + // Initialize chains + details, err := cselectors.GetChainDetailsByChainIDAndFamily(s.TonBlockchain.ChainID, s.TonBlockchain.Family) + s.Require().NoError(err) + s.ChainA = types.ChainSelector(details.ChainSelector) + + s.ChainB = types.ChainSelector(cselectors.GETH_TESTNET.Selector) + s.ChainC = types.ChainSelector(cselectors.GETH_DEVNET_2.Selector) + + // Deploy contracts on chain A (the one we execute on) + s.deployMCMSContract(hash.CRC32("test.executable.mcms")) + s.deployTimelockContract(hash.CRC32("test.executable.timelock")) +} + +// TestExecuteProposal executes a proposal after setting the root +func (s *ExecutionTestSuite) TestExecuteProposal() { + ctx := context.Background() + + // Construct a proposal + + // Construct a TON transaction to grant a role + + // Grant role data + grantRoleData, err := tlb.ToCell(rbac.GrantRole{ + QueryID: 0x1, + Role: tlbe.NewUint256(timelock.RoleProposer), + Account: address.MustParseAddr(s.mcmsAddr), + }) + s.Require().NoError(err) + + opTX, err := mcmston.NewTransaction( + address.MustParseAddr(s.timelockAddr), + grantRoleData.ToBuilder().ToSlice(), + tlb.MustFromTON("0.1").Nano(), + "RBACTimelock", + []string{"RBACTimelock", "GrantRole"}, + ) + s.Require().NoError(err) + + proposal := mcmslib.Proposal{ + BaseProposal: mcmslib.BaseProposal{ + Version: "v1", + Description: "Grants RBACTimelock 'Proposer' Role to MCMS Contract", + Kind: types.KindProposal, + ValidUntil: 2004259681, + Signatures: []types.Signature{}, + OverridePreviousRoot: false, + ChainMetadata: map[types.ChainSelector]types.ChainMetadata{ + s.ChainA: { + StartingOpCount: 0, + MCMAddress: s.mcmsAddr, + AdditionalFields: testOpAdditionalFields, + }, + }, + }, + Operations: []types.Operation{ + { + ChainSelector: s.ChainA, + Transaction: opTX, + }, + }, + } + + tree, err := proposal.MerkleTree() + s.Require().NotNil(tree) + s.Require().NoError(err) + + // Gen caller map for easy access (we can use geth chainselector for anvil) + inspectors := map[types.ChainSelector]sdk.Inspector{ + s.ChainA: mcmston.NewInspector(s.TonClient), + } + + // Construct executor + signable, err := mcmslib.NewSignable(&proposal, inspectors) + s.Require().NoError(err) + s.Require().NotNil(signable) + + err = signable.ValidateConfigs(ctx) + s.Require().NoError(err) + + _, err = signable.SignAndAppend(mcmslib.NewPrivateKeySigner(s.signers[1].Key)) + s.Require().NoError(err) + + // Validate the signatures + quorumMet, err := signable.ValidateSignatures(ctx) + s.Require().NoError(err) + s.Require().True(quorumMet) + + // Construct encoders + encoders, err := proposal.GetEncoders() + s.Require().NoError(err) + + // Construct executors + encoder := encoders[s.ChainA].(*mcmston.Encoder) + executor, err := mcmston.NewExecutor(mcmston.ExecutorOpts{ + Encoder: encoder, + Client: s.TonClient, + Wallet: s.wallet, + Amount: tlb.MustFromTON("0.1"), + }) + s.Require().NoError(err) + executors := map[types.ChainSelector]sdk.Executor{ + s.ChainA: executor, + } + + // Construct executable + executable, err := mcmslib.NewExecutable(&proposal, executors) + s.Require().NoError(err) + + // SetRoot on the contract + res, err := executable.SetRoot(ctx, s.ChainA) + s.Require().NoError(err) + s.Require().NotEmpty(res.Hash) + + // Wait for transaction to be mined + tx, ok := res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx) + + // Wait and check success + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) + + // Validate Contract State and verify root was set A + rootARoot, rootAValidUntil, err := inspectors[s.ChainA].GetRoot(ctx, s.mcmsAddr) + s.Require().NoError(err) + s.Require().Equal(rootARoot, common.Hash([32]byte(tree.Root.Bytes()))) + s.Require().Equal(rootAValidUntil, proposal.ValidUntil) + + // Execute the proposal + res, err = executable.Execute(ctx, 0) + s.Require().NoError(err) + s.Require().NotEmpty(res.Hash) + + // Wait for transaction to be mined + tx, ok = res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx) + + // Wait and check success + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) + + // Verify the operation count is updated on chain A + newOpCountA, err := inspectors[s.ChainA].GetOpCount(ctx, s.mcmsAddr) + s.Require().NoError(err) + s.Require().Equal(uint64(1), newOpCountA) + + // Check the state of the timelock contract + inspectorT := mcmston.NewTimelockInspector(s.TonClient) + proposers, err := inspectorT.GetProposers(ctx, s.timelockAddr) + s.Require().NoError(err) + s.Require().Len(proposers, 2) + s.Require().Contains(proposers, s.mcmsAddr) +} + +// TestExecuteProposalMultiple executes 2 proposals to check nonce calculation mechanisms are working +func (s *ExecutionTestSuite) TestExecuteProposalMultiple() { + ctx := context.Background() + + // Construct a TON transaction to grant a role + + // Grant role data + grantRoleData, err := tlb.ToCell(rbac.GrantRole{ + QueryID: 0x1, + Role: tlbe.NewUint256(timelock.RoleProposer), + Account: s.wallet.Address(), + }) + s.Require().NoError(err) + + opTX, err := mcmston.NewTransaction( + address.MustParseAddr(s.timelockAddr), + grantRoleData.ToBuilder().ToSlice(), + tlb.MustFromTON("0.1").Nano(), + "RBACTimelock", + []string{"RBACTimelock", "GrantRole"}, + ) + s.Require().NoError(err) + + // Construct a proposal + proposal := mcmslib.Proposal{ + BaseProposal: mcmslib.BaseProposal{ + Version: "v1", + Description: "Grants RBACTimelock 'Proposer' Role to MCMS Contract", + Kind: types.KindProposal, + ValidUntil: 2004259681, + Signatures: []types.Signature{}, + OverridePreviousRoot: false, + ChainMetadata: map[types.ChainSelector]types.ChainMetadata{ + s.ChainA: { + StartingOpCount: 1, + MCMAddress: s.mcmsAddr, + AdditionalFields: testOpAdditionalFields, + }, + }, + }, + Operations: []types.Operation{ + { + ChainSelector: s.ChainA, + Transaction: opTX, + }, + }, + } + + tree, err := proposal.MerkleTree() + s.Require().NotNil(tree) + s.Require().NoError(err) + + // Gen caller map for easy access (we can use geth chainselector for anvil) + inspectors := map[types.ChainSelector]sdk.Inspector{ + s.ChainA: mcmston.NewInspector(s.TonClient), + } + + // Construct executor + signable, err := mcmslib.NewSignable(&proposal, inspectors) + s.Require().NoError(err) + s.Require().NotNil(signable) + + _, err = signable.SignAndAppend(mcmslib.NewPrivateKeySigner(s.signers[1].Key)) + s.Require().NoError(err) + + // Validate the signatures + quorumMet, err := signable.ValidateSignatures(ctx) + s.Require().NoError(err) + s.Require().True(quorumMet) + + // Construct encoders + encoders, err := proposal.GetEncoders() + s.Require().NoError(err) + + // Construct executors + encoder := encoders[s.ChainA].(*mcmston.Encoder) + executor, err := mcmston.NewExecutor(mcmston.ExecutorOpts{ + Encoder: encoder, + Client: s.TonClient, + Wallet: s.wallet, + Amount: tlb.MustFromTON("0.1"), + }) + s.Require().NoError(err) + executors := map[types.ChainSelector]sdk.Executor{ + s.ChainA: executor, + } + + // Construct executable + executable, err := mcmslib.NewExecutable(&proposal, executors) + s.Require().NoError(err) + + // SetRoot on the contract + res, err := executable.SetRoot(ctx, s.ChainA) + s.Require().NoError(err) + s.Require().NotEmpty(res.Hash) + + // Wait for transaction to be mined + tx, ok := res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx) + + // Wait and check success + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) + + // Validate Contract State and verify root was set A + rootARoot, rootAValidUntil, err := inspectors[s.ChainA].GetRoot(ctx, s.mcmsAddr) + s.Require().NoError(err) + s.Require().Equal(rootARoot, common.Hash([32]byte(tree.Root.Bytes()))) + s.Require().Equal(rootAValidUntil, proposal.ValidUntil) + + // Execute the proposal + res, err = executable.Execute(ctx, 0) + s.Require().NoError(err) + s.Require().NotEmpty(res.Hash) + + // Wait for transaction to be mined + tx, ok = res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx) + + // Wait and check success + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) + + // Verify the operation count is updated on chain A + newOpCountA, err := inspectors[s.ChainA].GetOpCount(ctx, s.mcmsAddr) + s.Require().NoError(err) + s.Require().Equal(uint64(2), newOpCountA) + + // Check the state of the timelock contract + inspectorT := mcmston.NewTimelockInspector(s.TonClient) + proposers, err := inspectorT.GetProposers(ctx, s.timelockAddr) + s.Require().NoError(err) + s.Require().Len(proposers, 2) + s.Require().Contains(proposers, s.wallet.Address().String()) + + // Construct 2nd proposal + + // Construct a TON transaction to grant a role + // Grant role data + grantRoleData2, err := tlb.ToCell(rbac.GrantRole{ + QueryID: 0x1, + Role: tlbe.NewUint256(timelock.RoleBypasser), + Account: address.MustParseAddr(s.mcmsAddr), + }) + s.Require().NoError(err) + + opTX2, err := mcmston.NewTransaction( + address.MustParseAddr(s.timelockAddr), + grantRoleData2.ToBuilder().ToSlice(), + tlb.MustFromTON("0.1").Nano(), + "RBACTimelock", + []string{"RBACTimelock", "GrantRole"}, + ) + s.Require().NoError(err) + + proposal2 := mcmslib.Proposal{ + BaseProposal: mcmslib.BaseProposal{ + Version: "v1", + Description: "Grants RBACTimelock 'Proposer' Role to MCMS Contract", + Kind: types.KindProposal, + ValidUntil: 2004259681, + Signatures: []types.Signature{}, + OverridePreviousRoot: false, + ChainMetadata: map[types.ChainSelector]types.ChainMetadata{ + s.ChainA: { + StartingOpCount: 2, + MCMAddress: s.mcmsAddr, + AdditionalFields: testOpAdditionalFields, + }, + }, + }, + Operations: []types.Operation{ + { + ChainSelector: s.ChainA, + Transaction: opTX2, + }, + }, + } + + // Construct executor + signable2, err := mcmslib.NewSignable(&proposal2, inspectors) + s.Require().NoError(err) + s.Require().NotNil(signable2) + + _, err = signable2.SignAndAppend(mcmslib.NewPrivateKeySigner(s.signers[1].Key)) + s.Require().NoError(err) + + // Validate the signatures + quorumMet, err = signable2.ValidateSignatures(ctx) + s.Require().NoError(err) + s.Require().True(quorumMet) + + // Construct executors + executors2 := map[types.ChainSelector]sdk.Executor{ + s.ChainA: executor, + } + + // Construct executable + executable2, err := mcmslib.NewExecutable(&proposal2, executors2) + s.Require().NoError(err) + + // SetRoot on the contract + res, err = executable2.SetRoot(ctx, s.ChainA) + s.Require().NoError(err) + s.Require().NotEmpty(res.Hash) + + // Wait for transaction to be mined + tx, ok = res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx) + + // Wait and check success + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) + + tree2, err := proposal2.MerkleTree() + s.Require().NotNil(tree2) + s.Require().NoError(err) + + // Validate Contract State and verify root was set A + rootARoot, rootAValidUntil, err = inspectors[s.ChainA].GetRoot(ctx, s.mcmsAddr) + s.Require().NoError(err) + s.Require().Equal(rootARoot, common.Hash([32]byte(tree2.Root.Bytes()))) + s.Require().Equal(rootAValidUntil, proposal2.ValidUntil) + + // Execute the proposal + res, err = executable2.Execute(ctx, 0) + s.Require().NoError(err) + s.Require().NotEmpty(res.Hash) + + // Wait for transaction to be mined + tx, ok = res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx) + + // Wait and check success + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) + + // Check the state of the MCMS contract + // Verify the operation count is updated on chain A + newOpCountA, err = inspectors[s.ChainA].GetOpCount(ctx, s.mcmsAddr) + s.Require().NoError(err) + s.Require().Equal(uint64(3), newOpCountA) + + // Check the state of the timelock contract + bypassers, err := inspectorT.GetBypassers(ctx, s.timelockAddr) + s.Require().NoError(err) + s.Require().Len(bypassers, 2) + s.Require().Contains(bypassers, s.mcmsAddr) +} + +// TestExecuteProposalMultipleChains executes a proposal with operations on two different chains +func (s *ExecutionTestSuite) TestExecuteProposalMultipleChains() { + ctx := context.Background() + + // Op counts before execution + inspectorA := mcmston.NewInspector(s.TonClient) + opCountA, err := inspectorA.GetOpCount(ctx, s.mcmsAddr) + s.Require().NoError(err) + opCountB := uint64(0) + opCountC := uint64(0) + + // Construct a TON transaction to grant a role + + // Sends some funds to MCMS contract + opTX, err := mcmston.NewTransaction( + address.MustParseAddr(s.mcmsAddr), + cell.BeginCell().ToSlice(), // empty message (top up) + tlb.MustFromTON("0.1").Nano(), + "RBACTimelock", + []string{"RBACTimelock", "TopUp"}, + ) + s.Require().NoError(err) + + // Dummy transaction for EVM chains B/C + dummyTX := evm.NewTransaction( + s.signers[0].Address(), + []byte("0x13424"), + big.NewInt(0), + "", + []string{""}, + ) + + proposalTimelock := mcmslib.TimelockProposal{ + BaseProposal: mcmslib.BaseProposal{ + Version: "v1", + Kind: types.KindTimelockProposal, + Description: "description", + ValidUntil: 2004259681, + OverridePreviousRoot: true, + Signatures: []types.Signature{}, + ChainMetadata: map[types.ChainSelector]types.ChainMetadata{ + s.ChainA: { + StartingOpCount: opCountA, + MCMAddress: s.mcmsAddr, + AdditionalFields: testOpAdditionalFields, + }, + s.ChainB: { + StartingOpCount: opCountB, + MCMAddress: "0xdead0001", + }, + s.ChainC: { + StartingOpCount: opCountC, + MCMAddress: "0xdead1001", + }, + }, + }, + Action: types.TimelockActionSchedule, + Delay: types.MustParseDuration("0s"), + TimelockAddresses: map[types.ChainSelector]string{ + s.ChainA: s.timelockAddr, + s.ChainB: "0xdead0002", + s.ChainC: "0xdead1002", + }, + Operations: []types.BatchOperation{ + { + ChainSelector: s.ChainA, + Transactions: []types.Transaction{opTX}, + }, + { + ChainSelector: s.ChainB, + Transactions: []types.Transaction{dummyTX}, + }, + { + ChainSelector: s.ChainC, + Transactions: []types.Transaction{dummyTX}, + }, + }, + } + + proposal, _, err := proposalTimelock.Convert(ctx, map[types.ChainSelector]sdk.TimelockConverter{ + s.ChainA: mcmston.NewTimelockConverter(mcmston.DefaultSendAmount), + s.ChainB: &evm.TimelockConverter{}, + s.ChainC: &evm.TimelockConverter{}, + }) + s.Require().NoError(err) + + tree, err := proposal.MerkleTree() + s.Require().NotNil(tree) + s.Require().NoError(err) + + // Sign proposal + inspectors := map[types.ChainSelector]sdk.Inspector{ + s.ChainA: inspectorA, + s.ChainB: s.newMockEVMInspector(proposal.ChainMetadata[s.ChainB]), + s.ChainC: s.newMockEVMInspector(proposal.ChainMetadata[s.ChainC]), + } + + // Construct signable object + signable, err := mcmslib.NewSignable(&proposal, inspectors) + s.Require().NoError(err) + s.Require().NotNil(signable) + + err = signable.ValidateConfigs(ctx) + s.Require().NoError(err) + + _, err = signable.SignAndAppend(mcmslib.NewPrivateKeySigner(s.signers[1].Key)) + s.Require().NoError(err) + + // Validate signatures + quorumMet, err := signable.ValidateSignatures(ctx) + s.Require().NoError(err) + s.Require().True(quorumMet) + + // Construct encoders for both chains + encoders, err := proposal.GetEncoders() + s.Require().NoError(err) + encoderA := encoders[s.ChainA].(*mcmston.Encoder) + encoderB := encoders[s.ChainB].(*evm.Encoder) + encoderC := encoders[s.ChainC].(*evm.Encoder) + + // Construct executors for both chains + executors := map[types.ChainSelector]sdk.Executor{ + s.ChainA: must(mcmston.NewExecutor(mcmston.ExecutorOpts{ + Encoder: encoderA, + Client: s.TonClient, + Wallet: s.wallet, + Amount: tlb.MustFromTON("0.1"), + })), + s.ChainB: evm.NewExecutor(encoderB, nil, nil), // No need to execute on Chain B or C + s.ChainC: evm.NewExecutor(encoderC, nil, nil), + } + + // Notice: simulation not supported for TON executor yet + + // Construct executable object + executable, err := mcmslib.NewExecutable(&proposal, executors) + s.Require().NoError(err) + + // SetRoot on MCMS Contract for Chain A (only) + res, err := executable.SetRoot(ctx, s.ChainA) + s.Require().NoError(err) + s.Require().NotEmpty(res.Hash) + + // Wait for transaction to be mined + tx, ok := res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx) + + // Wait and check success + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) + + // Validate Contract State and verify root was set A + rootARoot, rootAValidUntil, err := inspectors[s.ChainA].GetRoot(ctx, s.mcmsAddr) + s.Require().NoError(err) + s.Require().Equal(rootARoot, common.Hash([32]byte(tree.Root.Bytes()))) + s.Require().Equal(rootAValidUntil, proposal.ValidUntil) + + res, err = executable.Execute(ctx, 0) + s.Require().NoError(err) + s.Require().NotEmpty(res.Hash) + + // Wait for transaction to be mined + tx, ok = res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx) + + // Wait and check success + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) + + // Verify the operation count is updated on chain A + newOpCountA, err := inspectorA.GetOpCount(ctx, s.mcmsAddr) + s.Require().NoError(err) + s.Require().Equal(opCountA+1, newOpCountA) + + // Construct executors + tExecutors := map[types.ChainSelector]sdk.TimelockExecutor{ + s.ChainA: must(mcmston.NewTimelockExecutor(mcmston.TimelockExecutorOpts{ + Client: s.TonClient, + Wallet: s.wallet, + Amount: tlb.MustFromTON("0.2"), + })), + s.ChainB: evm.NewTimelockExecutor(nil, nil), // No need to execute on Chain B or C + s.ChainC: evm.NewTimelockExecutor(nil, nil), + } + + // Create new executable + tExecutable, err := mcmslib.NewTimelockExecutable(ctx, &proposalTimelock, tExecutors) + s.Require().NoError(err) + + // Notice: skipped as fails on sdk/evm.TimelockInspector.IsOperationReady + // Could be enabled with an evm TimelockExecutor/Inspector mock similar + // err = tExecutable.IsReady(ctx) + // s.Require().NoError(err) + + // Execute operation 0 + res, err = tExecutable.Execute(ctx, 0) + s.Require().NoError(err) + + // Wait for transaction to be mined + tx, ok = res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx) + + // Wait and check success + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) +} + +var testOpAdditionalFields = json.RawMessage(fmt.Sprintf(`{"value": %d}`, tlb.MustFromTON("0.1").Nano().Uint64())) + +func (s *ExecutionTestSuite) deployTimelockContract(id uint32) { + ctx := s.T().Context() + amount := tlb.MustFromTON("1.5") // TODO (ton): high gas + + data := timelock.EmptyDataFrom(id) + mcmsAddr := address.MustParseAddr(s.mcmsAddr) + // When deploying the contract, send the Init message to initialize the Timelock contract + accounts := []toncommon.AddressWrap{ + {Val: mcmsAddr}, + {Val: s.wallet.Address()}, + } + body := timelock.Init{ + QueryID: 0, + MinDelay: 0, + Admin: mcmsAddr, + Proposers: accounts, + Executors: accounts, + Cancellers: accounts, + Bypassers: accounts, + ExecutorRoleCheckEnabled: true, + OpFinalizationTimeout: 0, + } + + timelockAddr, err := DeployTimelockContract(ctx, s.TonClient, s.wallet, amount, data, body) + s.Require().NoError(err) + s.timelockAddr = timelockAddr.String() +} + +func (s *ExecutionTestSuite) deployMCMSContract(id uint32) { + ctx := s.T().Context() + + // TODO (ton): when MCMS is out of gas, executions fail silently + // - trace doesn't return error, but opCount doesn't increase + amount := tlb.MustFromTON("10") + chainID, err := strconv.ParseInt(s.TonBlockchain.ChainID, 10, 64) + s.Require().NoError(err) + data := mcms.EmptyDataFrom(id, s.wallet.Address(), chainID) + mcmsAddr, err := DeployMCMSContract(ctx, s.TonClient, s.wallet, amount, data) + s.Require().NoError(err) + s.mcmsAddr = mcmsAddr.String() + + // Set configuration + configurerTON, err := mcmston.NewConfigurer(s.wallet, amount) + s.Require().NoError(err) + + config := GenSimpleTestMCMSConfig(s.signers) + clearRoot := true + res, err := configurerTON.SetConfig(ctx, s.mcmsAddr, config, clearRoot) + s.Require().NoError(err, "Failed to set contract configuration") + s.Require().NotNil(res) + + tx, ok := res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx.Description) + + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) +} + +func (s *ExecutionTestSuite) newMockEVMInspector(rootMetadata types.ChainMetadata) sdk.Inspector { + return mockEVMInspector{ + config: GenSimpleTestMCMSConfig(s.signers), + opCount: 0, + root: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), + rootMetadata: rootMetadata, + } +} + +// Implements sdk.Inspector +type mockEVMInspector struct { + config *types.Config + opCount uint64 + root common.Hash + rootMetadata types.ChainMetadata +} + +func (i mockEVMInspector) GetConfig(ctx context.Context, mcmAddr string) (*types.Config, error) { + return i.config, nil +} + +func (i mockEVMInspector) GetOpCount(ctx context.Context, mcmAddr string) (uint64, error) { + return i.opCount, nil +} + +func (i mockEVMInspector) GetRoot(ctx context.Context, mcmAddr string) (common.Hash, uint32, error) { + return i.root, 0, nil +} + +func (i mockEVMInspector) GetRootMetadata(ctx context.Context, mcmAddr string) (types.ChainMetadata, error) { + return i.rootMetadata, nil +} diff --git a/e2e/tests/ton/inspection.go b/e2e/tests/ton/inspection.go new file mode 100644 index 000000000..9ade61241 --- /dev/null +++ b/e2e/tests/ton/inspection.go @@ -0,0 +1,130 @@ +//go:build e2e + +package tone2e + +import ( + "strconv" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/suite" + + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton/wallet" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/hash" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + e2e "github.com/smartcontractkit/mcms/e2e/tests" + "github.com/smartcontractkit/mcms/internal/testutils" + mcmston "github.com/smartcontractkit/mcms/sdk/ton" +) + +// InspectionTestSuite defines the test suite +type InspectionTestSuite struct { + suite.Suite + e2e.TestSetup + + wallet *wallet.Wallet + mcmsAddr string + + signers []testutils.ECDSASigner +} + +// SetupSuite runs before the test suite +func (s *InspectionTestSuite) SetupSuite() { + s.TestSetup = *e2e.InitializeSharedTestSetup(s.T()) + + // Generate few test signers + s.signers = testutils.MakeNewECDSASigners(2) + + var err error + s.wallet, err = tvm.MyLocalTONWalletDefault(s.TonClient) + s.Require().NoError(err) + + s.deployMCMSContract() +} + +func (s *InspectionTestSuite) deployMCMSContract() { + ctx := s.T().Context() + + amount := tlb.MustFromTON("0.3") + chainID, err := strconv.ParseInt(s.TonBlockchain.ChainID, 10, 64) + s.Require().NoError(err) + data := mcms.EmptyDataFrom(hash.CRC32("test.inspection.mcms"), s.wallet.Address(), chainID) + mcmsAddr, err := DeployMCMSContract(ctx, s.TonClient, s.wallet, amount, data) + s.Require().NoError(err) + s.mcmsAddr = mcmsAddr.String() + + // Set configuration + configurerTON, err := mcmston.NewConfigurer(s.wallet, amount) + s.Require().NoError(err) + + config := GenSimpleTestMCMSConfig(s.signers) + clearRoot := true + res, err := configurerTON.SetConfig(ctx, s.mcmsAddr, config, clearRoot) + s.Require().NoError(err, "Failed to set contract configuration") + s.Require().NotNil(res) + + tx, ok := res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx.Description) + + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) +} + +// TestGetConfig checks contract configuration +func (s *InspectionTestSuite) TestGetConfig() { + ctx := s.T().Context() + + inspector := mcmston.NewInspector(s.TonClient) + config, err := inspector.GetConfig(ctx, s.mcmsAddr) + + s.Require().NoError(err, "Failed to get contract configuration") + s.Require().NotNil(config, "Contract configuration is nil") + + // Check first group + s.Require().Equal(uint8(1), config.Quorum, "Quorum does not match") + s.Require().Equal(s.signers[0].Address(), config.Signers[0], "Signers do not match") + + // Check second group + s.Require().Equal(uint8(1), config.GroupSigners[0].Quorum, "Group quorum does not match") + s.Require().Equal(s.signers[1].Address(), config.GroupSigners[0].Signers[0], "Group signers do not match") +} + +// TestGetOpCount checks contract operation count +func (s *InspectionTestSuite) TestGetOpCount() { + ctx := s.T().Context() + + inspector := mcmston.NewInspector(s.TonClient) + opCount, err := inspector.GetOpCount(ctx, s.mcmsAddr) + + s.Require().NoError(err, "Failed to get op count") + s.Require().Equal(uint64(0), opCount, "Operation count does not match") +} + +// TestGetRoot checks contract root +func (s *InspectionTestSuite) TestGetRoot() { + ctx := s.T().Context() + + inspector := mcmston.NewInspector(s.TonClient) + root, validUntil, err := inspector.GetRoot(ctx, s.mcmsAddr) + + s.Require().NoError(err, "Failed to get root from contract") + s.Require().Equal(common.Hash{}, root, "Roots do not match") + s.Require().Equal(uint32(0), validUntil, "ValidUntil does not match") +} + +// TestGetRootMetadata checks contract root metadata +func (s *InspectionTestSuite) TestGetRootMetadata() { + ctx := s.T().Context() + + inspector := mcmston.NewInspector(s.TonClient) + metadata, err := inspector.GetRootMetadata(ctx, s.mcmsAddr) + + s.Require().NoError(err, "Failed to get root metadata from contract") + s.Require().Equal(metadata.MCMAddress, s.mcmsAddr, "MCMAddress does not match") + s.Require().Equal(uint64(0), metadata.StartingOpCount, "StartingOpCount does not match") +} diff --git a/e2e/tests/ton/set_config.go b/e2e/tests/ton/set_config.go new file mode 100644 index 000000000..8e3680008 --- /dev/null +++ b/e2e/tests/ton/set_config.go @@ -0,0 +1,235 @@ +//go:build e2e + +package tone2e + +import ( + "strconv" + + "github.com/ethereum/go-ethereum/common" + + "github.com/stretchr/testify/suite" + + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton/wallet" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/hash" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + e2e "github.com/smartcontractkit/mcms/e2e/tests" + "github.com/smartcontractkit/mcms/internal/testutils" + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + + mcmston "github.com/smartcontractkit/mcms/sdk/ton" +) + +// SetConfigTestSuite tests signing a proposal and converting back to a file +type SetConfigTestSuite struct { + suite.Suite + e2e.TestSetup + + wallet *wallet.Wallet + mcmsAddr string +} + +// SetupSuite runs before the test suite +func (s *SetConfigTestSuite) SetupSuite() { + s.TestSetup = *e2e.InitializeSharedTestSetup(s.T()) + + var err error + s.wallet, err = tvm.MyLocalTONWalletDefault(s.TonClient) + s.Require().NoError(err) + + s.deployMCMSContract() +} + +func (s *SetConfigTestSuite) deployMCMSContract() { + ctx := s.T().Context() + + amount := tlb.MustFromTON("0.3") + chainID, err := strconv.ParseInt(s.TonBlockchain.ChainID, 10, 64) + s.Require().NoError(err) + data := mcms.EmptyDataFrom(hash.CRC32("test.set_config.mcms"), s.wallet.Address(), chainID) + mcmsAddr, err := DeployMCMSContract(ctx, s.TonClient, s.wallet, amount, data) + s.Require().NoError(err) + s.mcmsAddr = mcmsAddr.String() +} + +func (s *SetConfigTestSuite) TestSetConfigInspect() { + // Signers in each group need to be sorted alphabetically + signers := testutils.MakeNewECDSASigners(30) + + amount := tlb.MustFromTON("0.3") + configurerTON, err := mcmston.NewConfigurer(s.wallet, amount) + s.Require().NoError(err) + + inspectorTON := mcmston.NewInspector(s.TonClient) + + tests := []struct { + name string + config types.Config + configurer sdk.Configurer + inspector sdk.Inspector + wantErr error + }{ + { + name: "config small/default", + config: types.Config{ + Quorum: 1, + Signers: []common.Address{signers[0].Address()}, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{signers[1].Address()}, + GroupSigners: []types.Config{}, + }, + }, + }, + configurer: configurerTON, + inspector: inspectorTON, + }, + { + name: "config proposer", + config: types.Config{ + Quorum: 2, + Signers: []common.Address{ + signers[0].Address(), + signers[1].Address(), + signers[2].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 4, + Signers: []common.Address{ + signers[3].Address(), + signers[4].Address(), + signers[5].Address(), + signers[6].Address(), + signers[7].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{ + signers[8].Address(), + signers[9].Address(), + }, + GroupSigners: []types.Config{}, + }, + }, + }, + { + Quorum: 3, + Signers: []common.Address{ + signers[10].Address(), + signers[11].Address(), + signers[12].Address(), + signers[13].Address(), + }, + GroupSigners: []types.Config{}, + }, + }, + }, + configurer: configurerTON, + inspector: inspectorTON, + }, + { + name: "config canceller", + config: types.Config{ + Quorum: 1, + Signers: []common.Address{ + signers[14].Address(), + signers[15].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 2, + Signers: []common.Address{ + signers[16].Address(), + signers[17].Address(), + signers[18].Address(), + signers[19].Address(), + }, + GroupSigners: []types.Config{}, + }, + }, + }, + configurer: configurerTON, + inspector: inspectorTON, + }, + { + name: "config proposer", + config: types.Config{ + Quorum: 2, + Signers: []common.Address{}, + GroupSigners: []types.Config{ + { + Quorum: 2, + Signers: []common.Address{ + signers[20].Address(), + signers[21].Address(), + signers[22].Address(), + signers[23].Address(), + }, + GroupSigners: []types.Config{}, + }, { + Quorum: 2, + Signers: []common.Address{ + signers[24].Address(), + signers[25].Address(), + signers[26].Address(), + signers[27].Address(), + }, + GroupSigners: []types.Config{}, + }, { + Quorum: 1, + Signers: []common.Address{ + signers[28].Address(), + signers[29].Address(), + }, + GroupSigners: []types.Config{}, + }, + }, + }, + configurer: configurerTON, + inspector: inspectorTON, + }, + } + + for _, tt := range tests { + s.Run(tt.name, func() { + ctx := s.T().Context() + // Set config + { + res, err := tt.configurer.SetConfig(ctx, s.mcmsAddr, &tt.config, true) + s.Require().NoError(err, "setting config on MCMS contract") + + s.Require().NotNil(res.Hash) + s.Require().NotNil(res.RawData) + + tx, ok := res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx.Description) + + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) + } + + { + gotCount, err := tt.inspector.GetOpCount(ctx, s.mcmsAddr) + s.Require().NoError(err, "getting config on MCMS contract") + s.Require().Equal(uint64(0), gotCount) + } + + // Assert that config has been set + { + gotConfig, err := tt.inspector.GetConfig(ctx, s.mcmsAddr) + s.Require().NoError(err, "getting config on MCMS contract") + s.Require().NotNil(gotConfig) + s.Require().Equal(&tt.config, gotConfig) + } + }) + } +} diff --git a/e2e/tests/ton/set_root.go b/e2e/tests/ton/set_root.go new file mode 100644 index 000000000..22c8ba01b --- /dev/null +++ b/e2e/tests/ton/set_root.go @@ -0,0 +1,279 @@ +//go:build e2e + +package tone2e + +import ( + "context" + "encoding/json" + "strconv" + + "github.com/stretchr/testify/suite" + + cselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/hash" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/ton/wallet" + "github.com/xssnick/tonutils-go/tvm/cell" + + mcmslib "github.com/smartcontractkit/mcms" + e2e "github.com/smartcontractkit/mcms/e2e/tests" + "github.com/smartcontractkit/mcms/internal/testutils" + "github.com/smartcontractkit/mcms/internal/testutils/chaintest" + "github.com/smartcontractkit/mcms/sdk" + mcmston "github.com/smartcontractkit/mcms/sdk/ton" + "github.com/smartcontractkit/mcms/types" +) + +const ( + AddrTimelock = "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8" // static mock address +) + +// SetRootTestSuite tests the SetRoot functionality +type SetRootTestSuite struct { + suite.Suite + e2e.TestSetup + + wallet *wallet.Wallet + mcmsAddr string + + signers []testutils.ECDSASigner + chainSelector types.ChainSelector + accounts []*address.Address +} + +// SetupSuite runs before the test suite +func (s *SetRootTestSuite) SetupSuite() { + s.TestSetup = *e2e.InitializeSharedTestSetup(s.T()) + + // Generate few test signers + s.signers = testutils.MakeNewECDSASigners(2) + + // Generate few test wallets + var chainID = chaintest.Chain7TONID + var client *ton.APIClient + s.accounts = []*address.Address{ + must(tvm.NewRandomV5R1TestWallet(client, chainID)).Address(), + must(tvm.NewRandomV5R1TestWallet(client, chainID)).Address(), + } + + var err error + s.wallet, err = tvm.MyLocalTONWalletDefault(s.TonClient) + s.Require().NoError(err) + + s.deployMCMSContract() + + chainDetails, err := cselectors.GetChainDetailsByChainIDAndFamily(s.TonBlockchain.ChainID, s.TonBlockchain.Family) + s.Require().NoError(err) + s.chainSelector = types.ChainSelector(chainDetails.ChainSelector) +} + +func (s *SetRootTestSuite) deployMCMSContract() { + ctx := s.T().Context() + + amount := tlb.MustFromTON("0.3") + chainID, err := strconv.ParseInt(s.TonBlockchain.ChainID, 10, 64) + s.Require().NoError(err) + data := mcms.EmptyDataFrom(hash.CRC32("test.set_root.mcms"), s.wallet.Address(), chainID) + mcmsAddr, err := DeployMCMSContract(ctx, s.TonClient, s.wallet, amount, data) + s.Require().NoError(err) + s.mcmsAddr = mcmsAddr.String() + + // Set configuration + configurerTON, err := mcmston.NewConfigurer(s.wallet, amount) + s.Require().NoError(err) + + config := GenSimpleTestMCMSConfig(s.signers) + clearRoot := true + res, err := configurerTON.SetConfig(ctx, s.mcmsAddr, config, clearRoot) + s.Require().NoError(err, "Failed to set contract configuration") + s.Require().NotNil(res) + + tx, ok := res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx.Description) + + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) +} + +// TestGetConfig checks contract configuration +func (s *SetRootTestSuite) TestGetConfig() { + ctx := s.T().Context() + + inspector := mcmston.NewInspector(s.TonClient) + config, err := inspector.GetConfig(ctx, s.mcmsAddr) + s.Require().NoError(err, "Failed to get contract configuration") + s.Require().NotNil(config, "Contract configuration is nil") + + // Check first group + s.Require().Equal(uint8(1), config.Quorum, "Quorum does not match") + s.Require().Equal(s.signers[0].Address(), config.Signers[0], "Signers do not match") + + // Check second group + s.Require().Equal(uint8(1), config.GroupSigners[0].Quorum, "Group quorum does not match") + s.Require().Equal(s.signers[1].Address(), config.GroupSigners[0].Signers[0], "Group signers do not match") +} + +// TestSetRootProposal sets the root of the MCMS contract +func (s *SetRootTestSuite) TestSetRootProposal() { + ctx := context.Background() + builder := mcmslib.NewProposalBuilder() + builder. + SetVersion("v1"). + SetValidUntil(1794610529). + SetDescription("proposal to test SetRoot"). + SetOverridePreviousRoot(true). + AddChainMetadata( + s.chainSelector, + types.ChainMetadata{MCMAddress: s.mcmsAddr}, + ). + AddOperation(types.Operation{ + ChainSelector: s.chainSelector, + Transaction: types.Transaction{ + To: s.accounts[0].String(), + Data: cell.BeginCell().EndCell().ToBOC(), + AdditionalFields: json.RawMessage(`{"value": 0}`), + }, + }) + proposal, err := builder.Build() + s.Require().NoError(err) + + // Sign the proposal + inspectors := map[types.ChainSelector]sdk.Inspector{ + s.chainSelector: mcmston.NewInspector(s.TonClient), + } + signable, err := mcmslib.NewSignable(proposal, inspectors) + s.Require().NoError(err) + s.Require().NotNil(signable) + _, err = signable.SignAndAppend(mcmslib.NewPrivateKeySigner(s.signers[0].Key)) + s.Require().NoError(err) + + // Validate the signatures + quorumMet, err := signable.ValidateSignatures(ctx) + s.Require().NoError(err) + s.Require().True(quorumMet) + + // Create the chain MCMS proposal executor + encoders, err := proposal.GetEncoders() + s.Require().NoError(err) + encoder := encoders[s.chainSelector].(*mcmston.Encoder) + + executor, err := mcmston.NewExecutor(mcmston.ExecutorOpts{ + Encoder: encoder, + Client: s.TonClient, + Wallet: s.wallet, + Amount: tlb.MustFromTON("0.1"), + }) + s.Require().NoError(err) + executorsMap := map[types.ChainSelector]sdk.Executor{ + s.chainSelector: executor, + } + executable, err := mcmslib.NewExecutable(proposal, executorsMap) + s.Require().NoError(err) + + // Call SetRoot + res, err := executable.SetRoot(ctx, s.chainSelector) + s.Require().NoError(err) + s.Require().NotEmpty(res.Hash) + + tx, ok := res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx) + + // Wait and check success + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) +} + +// TestSetRootTimelockProposal sets the root of the MCMS contract from a timelock proposal type. +func (s *SetRootTestSuite) TestSetRootTimelockProposal() { + ctx := context.Background() + + builder := mcmslib.NewTimelockProposalBuilder() + builder. + SetVersion("v1"). + SetValidUntil(1794610529). + SetDescription("proposal to test SetRoot"). + SetOverridePreviousRoot(true). + SetAction(types.TimelockActionSchedule). + SetDelay(types.MustParseDuration("24h")). + SetTimelockAddresses(map[types.ChainSelector]string{ + s.chainSelector: AddrTimelock, + }). + AddChainMetadata( + s.chainSelector, + types.ChainMetadata{MCMAddress: s.mcmsAddr}, + ). + AddOperation(types.BatchOperation{ + ChainSelector: s.chainSelector, + Transactions: []types.Transaction{ + { + To: s.accounts[0].String(), + Data: cell.BeginCell().MustStoreSlice([]byte{0x01}, 8).EndCell().ToBOC(), + AdditionalFields: json.RawMessage(`{"value": 3}`), + }, + { + To: s.accounts[1].String(), + Data: cell.BeginCell().MustStoreSlice([]byte{0x02}, 8).EndCell().ToBOC(), + AdditionalFields: json.RawMessage(`{"value": 4}`), + }, + }, + }) + proposalTimelock, err := builder.Build() + s.Require().NoError(err) + + proposal, _, err := proposalTimelock.Convert(ctx, map[types.ChainSelector]sdk.TimelockConverter{ + s.chainSelector: mcmston.NewTimelockConverter(mcmston.DefaultSendAmount), + }) + s.Require().NoError(err) + + // Sign proposal + inspectors := map[types.ChainSelector]sdk.Inspector{ + s.chainSelector: mcmston.NewInspector(s.TonClient), + } + signable, err := mcmslib.NewSignable(&proposal, inspectors) + s.Require().NoError(err) + s.Require().NotNil(signable) + _, err = signable.SignAndAppend(mcmslib.NewPrivateKeySigner(s.signers[1].Key)) + s.Require().NoError(err) + + encoders, err := proposal.GetEncoders() + s.Require().NoError(err) + encoder := encoders[s.chainSelector].(*mcmston.Encoder) + + executor, err := mcmston.NewExecutor(mcmston.ExecutorOpts{ + Encoder: encoder, + Client: s.TonClient, + Wallet: s.wallet, + Amount: tlb.MustFromTON("0.1"), + }) + s.Require().NoError(err) + executorsMap := map[types.ChainSelector]sdk.Executor{ + s.chainSelector: executor, + } + + // Notice: no simulation on TON (like on EVM) + + // Create the chain MCMS proposal executor + executable, err := mcmslib.NewExecutable(&proposal, executorsMap) + s.Require().NoError(err) + // Call SetRoot + res, err := executable.SetRoot(ctx, s.chainSelector) + s.Require().NoError(err) + s.Require().NotEmpty(res.Hash) + + tx, ok := res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx) + + // Wait and check success + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) +} diff --git a/e2e/tests/ton/signing.go b/e2e/tests/ton/signing.go new file mode 100644 index 000000000..c15902f6d --- /dev/null +++ b/e2e/tests/ton/signing.go @@ -0,0 +1,12 @@ +//go:build e2e + +package tone2e + +import ( + "github.com/smartcontractkit/mcms/e2e/tests/common" +) + +// SigningTestSuite tests signing a proposal and converting back to a file +type SigningTestSuite struct { + common.SigningTestSuite +} diff --git a/e2e/tests/ton/timelock_inspection.go b/e2e/tests/ton/timelock_inspection.go new file mode 100644 index 000000000..618128f96 --- /dev/null +++ b/e2e/tests/ton/timelock_inspection.go @@ -0,0 +1,419 @@ +//go:build e2e + +package tone2e + +import ( + "bytes" + "encoding/json" + "fmt" + "math/big" + "slices" + + "github.com/stretchr/testify/suite" + + "github.com/ethereum/go-ethereum/common" + + cselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton/wallet" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/lib/access/rbac" + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/timelock" + toncommon "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/hash" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + e2e "github.com/smartcontractkit/mcms/e2e/tests" + mcmston "github.com/smartcontractkit/mcms/sdk/ton" + "github.com/smartcontractkit/mcms/types" +) + +// TimelockInspectionTestSuite is a suite of tests for the RBACTimelock contract inspection. +type TimelockInspectionTestSuite struct { + suite.Suite + e2e.TestSetup + + wallet *wallet.Wallet + timelockAddr *address.Address + + accounts []*address.Address +} + +func (s *TimelockInspectionTestSuite) grantRole(role [32]byte, acc *address.Address) { + ctx := s.T().Context() + body, err := tlb.ToCell(rbac.GrantRole{ + QueryID: must(tvm.RandomQueryID()), + + Role: tlbe.NewUint256(new(big.Int).SetBytes(role[:])), + Account: acc, + }) + s.Require().NoError(err) + + msg := &wallet.Message{ + Mode: wallet.PayGasSeparately | wallet.IgnoreErrors, + InternalMessage: &tlb.InternalMessage{ + IHRDisabled: true, + Bounce: true, + DstAddr: s.timelockAddr, + Amount: tlb.MustFromTON("0.12"), + Body: body, + }, + } + + tx, _, err := s.wallet.SendWaitTransaction(ctx, msg) + s.Require().NoError(err) + s.Require().NotNil(tx) + + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) +} + +func (s *TimelockInspectionTestSuite) scheduleBatch(timelockAddr *address.Address, calls []timelock.Call, predecessor, salt common.Hash, delay uint32) { + ctx := s.T().Context() + body, err := tlb.ToCell(timelock.ScheduleBatch{ + QueryID: must(tvm.RandomQueryID()), + + Calls: calls, + Predecessor: tlbe.NewUint256(predecessor.Big()), + Salt: tlbe.NewUint256(salt.Big()), + Delay: delay, + }) + s.Require().NoError(err) + + msg := &wallet.Message{ + Mode: wallet.PayGasSeparately | wallet.IgnoreErrors, + InternalMessage: &tlb.InternalMessage{ + IHRDisabled: true, + Bounce: true, + DstAddr: timelockAddr, + Amount: tlb.MustFromTON("0.3"), + Body: body, + }, + } + + tx, _, err := s.wallet.SendWaitTransaction(ctx, msg) + s.Require().NoError(err) + s.Require().NotNil(tx) + + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) +} + +func (s *TimelockInspectionTestSuite) deployTimelockContract(id uint32) (*address.Address, error) { + ctx := s.T().Context() + amount := tlb.MustFromTON("1.5") // TODO (ton): high gas + + data := timelock.EmptyDataFrom(id) + // When deploying the contract, send the Init message to initialize the Timelock contract + // Admin will get all roles (not required, just for testing) + addrs := []toncommon.AddressWrap{ + {Val: s.wallet.Address()}, + } + + body := timelock.Init{ + QueryID: 0, + MinDelay: 0, + Admin: s.wallet.Address(), + Proposers: addrs, + Executors: addrs, + Cancellers: addrs, + Bypassers: addrs, + ExecutorRoleCheckEnabled: true, + OpFinalizationTimeout: 0, + } + + return DeployTimelockContract(ctx, s.TonClient, s.wallet, amount, data, body) +} + +// SetupSuite runs before the test suite +func (s *TimelockInspectionTestSuite) SetupSuite() { + s.TestSetup = *e2e.InitializeSharedTestSetup(s.T()) + + // Generate few test wallets + chainID := cselectors.TON_LOCALNET.ChainID + client := s.TonClient + s.accounts = []*address.Address{ + must(tvm.NewRandomV5R1TestWallet(client, chainID)).Address(), + must(tvm.NewRandomV5R1TestWallet(client, chainID)).Address(), + } + + // Sort accounts to have deterministic order + slices.SortFunc(s.accounts, func(a, b *address.Address) int { + return bytes.Compare(a.Data(), b.Data()) + }) + + var err error + s.wallet, err = tvm.MyLocalTONWalletDefault(client) + s.Require().NoError(err) + + // Deploy Timelock contract + s.timelockAddr, err = s.deployTimelockContract(hash.CRC32("test.timelock_inspection.timelock")) + s.Require().NoError(err) + + // Grant Some Roles for testing + // Proposers + role := [32]byte(timelock.RoleProposer.Bytes()) + s.Require().NoError(err) + s.grantRole(role, s.accounts[0]) + // Executors + role = [32]byte(timelock.RoleExecutor.Bytes()) + s.Require().NoError(err) + s.grantRole(role, s.accounts[0]) + s.grantRole(role, s.accounts[1]) + + // Bypassers + role = [32]byte(timelock.RoleBypasser.Bytes()) + s.Require().NoError(err) + s.grantRole(role, s.accounts[1]) + + // Cancellers + role = [32]byte(timelock.RoleCanceller.Bytes()) + s.Require().NoError(err) + s.grantRole(role, s.accounts[0]) + s.grantRole(role, s.accounts[1]) +} + +// TestGetProposers gets the list of proposers +func (s *TimelockInspectionTestSuite) TestGetProposers() { + ctx := s.T().Context() + inspector := mcmston.NewTimelockInspector(s.TonClient) + + proposers, err := inspector.GetProposers(ctx, s.timelockAddr.String()) + s.Require().NoError(err) + s.Require().Len(proposers, 2) + s.Require().Equal(s.accounts[0].String(), proposers[0]) +} + +// TestGetExecutors gets the list of executors +func (s *TimelockInspectionTestSuite) TestGetExecutors() { + ctx := s.T().Context() + inspector := mcmston.NewTimelockInspector(s.TonClient) + + executors, err := inspector.GetExecutors(ctx, s.timelockAddr.String()) + s.Require().NoError(err) + s.Require().Len(executors, 3) + s.Require().Equal(s.accounts[0].String(), executors[0]) + s.Require().Equal(s.accounts[1].String(), executors[1]) +} + +// TestGetBypassers gets the list of bypassers +func (s *TimelockInspectionTestSuite) TestGetBypassers() { + ctx := s.T().Context() + inspector := mcmston.NewTimelockInspector(s.TonClient) + + bypassers, err := inspector.GetBypassers(ctx, s.timelockAddr.String()) + s.Require().NoError(err) + s.Require().Len(bypassers, 2) // Ensure lengths match + // Check that all elements of signerAddresses are in proposers + s.Require().Contains(bypassers, s.accounts[1].String()) +} + +// TestGetCancellers gets the list of cancellers +func (s *TimelockInspectionTestSuite) TestGetCancellers() { + ctx := s.T().Context() + inspector := mcmston.NewTimelockInspector(s.TonClient) + + cancellers, err := inspector.GetCancellers(ctx, s.timelockAddr.String()) + s.Require().NoError(err) + s.Require().Len(cancellers, 3) + s.Require().Equal(s.accounts[0].String(), cancellers[0]) + s.Require().Equal(s.accounts[1].String(), cancellers[1]) +} + +// TestIsOperation tests the IsOperation method +func (s *TimelockInspectionTestSuite) TestIsOperation() { + ctx := s.T().Context() + inspector := mcmston.NewTimelockInspector(s.TonClient) + + // Schedule a test operation + calls := []timelock.Call{ + { + Target: s.accounts[0], + Value: tlb.MustFromTON("0.1"), // TON implementation enforces min value per call + Data: cell.BeginCell().EndCell(), + }, + } + delay := 3600 + pred := common.Hash([32]byte{0x0}) + salt := common.Hash([32]byte{0x01}) + s.scheduleBatch(s.timelockAddr, calls, pred, salt, uint32(delay)) + + opID, err := mcmston.HashOperationBatch(calls, pred, salt) + s.Require().NoError(err) + isOP, err := inspector.IsOperation(ctx, s.timelockAddr.String(), opID) + s.Require().NoError(err) + s.Require().True(isOP) +} + +// TestIsOperationPending tests the IsOperationPending method +func (s *TimelockInspectionTestSuite) TestIsOperationPending() { + ctx := s.T().Context() + inspector := mcmston.NewTimelockInspector(s.TonClient) + + // Schedule a test operation + calls := []timelock.Call{ + { + Target: s.accounts[0], + Value: tlb.MustFromTON("0.1"), // TON implementation enforces min value per call + Data: cell.BeginCell().EndCell(), + }, + } + delay := 3600 + salt := common.Hash([32]byte{0x01}) + pred, err := mcmston.HashOperationBatch(calls, [32]byte{0x0}, salt) + s.Require().NoError(err) + s.scheduleBatch(s.timelockAddr, calls, pred, salt, uint32(delay)) + + opID, err := mcmston.HashOperationBatch(calls, pred, salt) + s.Require().NoError(err) + isOP, err := inspector.IsOperationPending(ctx, s.timelockAddr.String(), opID) + s.Require().NoError(err) + s.Require().True(isOP) +} + +// TestIsOperationReady tests the IsOperationReady and IsOperationDone methods +func (s *TimelockInspectionTestSuite) TestIsOperationReady() { + ctx := s.T().Context() + inspector := mcmston.NewTimelockInspector(s.TonClient) + + // Schedule a test operation + calls := []timelock.Call{ + { + Target: s.accounts[0], + Value: tlb.MustFromTON("0.1"), // TON implementation enforces min value per call + Data: cell.BeginCell().EndCell(), + }, + } + delay := 0 + salt := common.Hash([32]byte{0x01}) + pred2, err := mcmston.HashOperationBatch(calls, [32]byte{0x0}, salt) + s.Require().NoError(err) + pred, err := mcmston.HashOperationBatch(calls, pred2, salt) + s.Require().NoError(err) + s.scheduleBatch(s.timelockAddr, calls, pred, salt, uint32(delay)) + + opID, err := mcmston.HashOperationBatch(calls, pred, salt) + s.Require().NoError(err) + isOP, err := inspector.IsOperationReady(ctx, s.timelockAddr.String(), opID) + s.Require().NoError(err) + s.Require().True(isOP) +} + +func (s *TimelockInspectionTestSuite) TestIsOperationDone() { + ctx := s.T().Context() + + // Deploy a new timelock for this test + newTimelockAddr, err := s.deployTimelockContract(hash.CRC32("test.timelock_inspection.timelock.1")) + s.Require().NoError(err) + + // Schedule a test operation + calls := []timelock.Call{ + { + Target: s.accounts[1], + Value: tlb.MustFromTON("0.1"), // TON implementation enforces min value per call + Data: cell.BeginCell().EndCell(), + }, + } + delay := 0 + pred := common.Hash([32]byte{0x0}) + salt := common.Hash([32]byte{0x01}) + + id, err := mcmston.HashOperationBatch(calls, pred, salt) + s.Require().NoError(err) + + s.scheduleBatch(newTimelockAddr, calls, pred, salt, uint32(delay)) + + inspector := mcmston.NewTimelockInspector(s.TonClient) + isOp, err := inspector.IsOperation(ctx, newTimelockAddr.String(), id) + s.Require().NoError(err, "Failed to check if operation exists") + s.Require().True(isOp, "Operation should exist") + + isOpPending, err := inspector.IsOperationPending(ctx, newTimelockAddr.String(), id) + s.Require().NoError(err, "Failed to check if operation is pending") + s.Require().True(isOpPending, "Operation should be pending") + + isOpReady, err := inspector.IsOperationReady(ctx, newTimelockAddr.String(), id) + s.Require().NoError(err, "Failed to check if operation is ready") + s.Require().True(isOpReady, "Operation should be ready") + + isOpDone, err := inspector.IsOperationDone(ctx, newTimelockAddr.String(), id) + s.Require().NoError(err, "Failed to check if operation is done") + s.Require().False(isOpDone, "Operation should not be done yet") + + // Attempt to execute the batch + executor, err := mcmston.NewTimelockExecutor(mcmston.TimelockExecutorOpts{ + Client: s.TonClient, + Wallet: s.wallet, + Amount: tlb.MustFromTON("0.1"), + }) + s.Require().NoError(err, "Failed to create TimelockExecutor") + + bop := types.BatchOperation{ + ChainSelector: types.ChainSelector(cselectors.TON_LOCALNET.Selector), + Transactions: []types.Transaction{ + { + To: s.accounts[1].String(), + Data: cell.BeginCell().EndCell().ToBOC(), + AdditionalFields: json.RawMessage(fmt.Sprintf(`{"value": %d}`, tlb.MustFromTON("0.1").Nano().Uint64())), + }, + }, + } + + // Test same ID + _calls, err := mcmston.ConvertBatchToCalls(bop) + s.Require().NoError(err, "Failed to convert batch to calls") + + _id, err := mcmston.HashOperationBatch(_calls, pred, salt) + s.Require().NoError(err, "Failed to compute operation ID") + s.Require().Equal(id, _id, "Operation IDs do not match") + + res, err := executor.Execute(ctx, bop, newTimelockAddr.String(), pred, salt) + s.Require().NoError(err, "Failed to execute batch") + s.Require().NotEmpty(res.Hash, "Transaction hash is empty") + + // Wait for the transaction to be mined + tx, ok := res.RawData.(*tlb.Transaction) + s.Require().True(ok) + s.Require().NotNil(tx.Description) + + err = tracetracking.WaitForTrace(ctx, s.TonClient, tx) + s.Require().NoError(err) + + // Check the operation (still) exists + isOp, err = inspector.IsOperation(ctx, newTimelockAddr.String(), id) + s.Require().NoError(err, "Failed to check if operation exists") + s.Require().True(isOp, "Operation should exist") + + // Check the operation is NOT pending anymore + isOpPending, err = inspector.IsOperationPending(ctx, newTimelockAddr.String(), id) + s.Require().NoError(err, "Failed to check if operation is pending") + s.Require().False(isOpPending, "Operation should NOT be pending") + + // Check the operation is NOT done + isOpDone, err = inspector.IsOperationDone(ctx, newTimelockAddr.String(), id) + s.Require().NoError(err, "Failed to check if operation is done") + s.Require().False(isOpDone, "Operation should NOT be done (in error state)") + + // Check the operation is in error state (bounced from an uninitialized account) + tonInspector, ok := inspector.(*mcmston.TimelockInspector) + s.Require().True(ok, "Inspector is not of type TimelockInspector") + + isOpError, err := tonInspector.IsOperationError(ctx, newTimelockAddr.String(), id) + s.Require().NoError(err, "Failed to check if operation is in error state") + s.Require().True(isOpError, "Operation should be in error state") +} + +// TestGetMinDelay tests the GetMinDelay method +func (s *TimelockInspectionTestSuite) TestGetMinDelay() { + ctx := s.T().Context() + inspector := mcmston.NewTimelockInspector(s.TonClient) + + delay, err := inspector.GetMinDelay(ctx, s.timelockAddr.String()) + s.Require().NoError(err, "Failed to get min delay") + s.Require().EqualValues(0, delay) +} diff --git a/factory.go b/factory.go index 6e172d56e..37cc1cb1a 100644 --- a/factory.go +++ b/factory.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/sdk/solana" "github.com/smartcontractkit/mcms/sdk/sui" + "github.com/smartcontractkit/mcms/sdk/ton" "github.com/smartcontractkit/mcms/types" ) @@ -52,6 +53,12 @@ func newEncoder( txCount, overridePreviousRoot, ) + case cselectors.FamilyTon: + encoder = ton.NewEncoder( + csel, + txCount, + overridePreviousRoot, + ) } return encoder, nil @@ -78,6 +85,11 @@ func newTimelockConverter(csel types.ChainSelector) (sdk.TimelockConverter, erro case cselectors.FamilySui: return &sui.TimelockConverter{}, nil + case cselectors.FamilyTon: + // Notice: we need to define the send amount from MCMS to Timelock, + // to cover gas fees. We use a static default value here for now. + return ton.NewTimelockConverter(ton.DefaultSendAmount), nil + default: return nil, fmt.Errorf("unsupported chain family %s", family) } diff --git a/factory_test.go b/factory_test.go index 5e57e85a9..f29df20af 100644 --- a/factory_test.go +++ b/factory_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/sdk/solana" "github.com/smartcontractkit/mcms/sdk/sui" + "github.com/smartcontractkit/mcms/sdk/ton" ) func TestNewEncoder(t *testing.T) { @@ -84,6 +85,16 @@ func TestNewEncoder(t *testing.T) { OverridePreviousRoot: false, }, }, + { + name: "success: returns a TON encoder", + giveSelector: chaintest.Chain7Selector, + giveIsSim: false, + want: &ton.Encoder{ + TxCount: giveTxCount, + ChainSelector: chaintest.Chain7Selector, + OverridePreviousRoot: false, + }, + }, { name: "failure: chain not found for selector", giveSelector: chaintest.ChainInvalidSelector, @@ -137,6 +148,11 @@ func TestNewTimelockConverter(t *testing.T) { chainSelector: chaintest.Chain6Selector, want: &sui.TimelockConverter{}, }, + { + name: "success: TON executor", + chainSelector: chaintest.Chain7Selector, + want: ton.NewTimelockConverter(ton.DefaultSendAmount), + }, { name: "failure: unknown selector", chainSelector: types.ChainSelector(123456789), diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..f53bdbbcf --- /dev/null +++ b/flake.lock @@ -0,0 +1,147 @@ +{ + "nodes": { + "chainlink-ton": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "nixpkgs-release-25-05": "nixpkgs-release-25-05" + }, + "locked": { + "lastModified": 1766053776, + "narHash": "sha256-oLNPlV7FaBe/63FvPgU+l5MKiU40hOfRCMK5GVsbPBI=", + "owner": "smartcontractkit", + "repo": "chainlink-ton", + "rev": "bacca2f28229622e4084e3395cbe4bedb2160310", + "type": "github" + }, + "original": { + "owner": "smartcontractkit", + "repo": "chainlink-ton", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1761373498, + "narHash": "sha256-Q/uhWNvd7V7k1H1ZPMy/vkx3F8C13ZcdrKjO7Jv7v0c=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "6a08e6bb4e46ff7fcbb53d409b253f6bad8a28ce", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-release-25-05": { + "locked": { + "lastModified": 1761667842, + "narHash": "sha256-p+6l/f8bbMErsxK3JWBtVds+pF1umiBjiA/wXJX6svE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "94db704ecbf4b0371436ea82fef81fd9dcc092d1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1765779637, + "narHash": "sha256-KJ2wa/BLSrTqDjbfyNx70ov/HdgNBCBBSQP3BIzKnv4=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "1306659b587dc277866c7b69eb97e5f07864d8c4", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "chainlink-ton": "chainlink-ton", + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..56b68aefa --- /dev/null +++ b/flake.nix @@ -0,0 +1,38 @@ +{ + description = "MCMS SDK Flake"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + + chainlink-ton.url = "github:smartcontractkit/chainlink-ton"; + }; + + outputs = inputs @ { + self, + nixpkgs, + flake-utils, + chainlink-ton, + ... + }: + flake-utils.lib.eachDefaultSystem (system: let + # Import nixpkgs with specific configuration + pkgs = import nixpkgs { + inherit system; + }; + + # The rev (git commit hash) of the current flake + rev = self.rev or self.dirtyRev or "-"; + + pkgsContracts = { + chainlink-ton-contracts = chainlink-ton.packages.${system}.contracts; + }; + in rec { + # Output a set of dev environments (shells) + devShells = { + default = pkgs.callPackage ./shell.nix {inherit pkgs pkgsContracts;}; + }; + + packages = {} // pkgsContracts; + }); +} diff --git a/go.mod b/go.mod index a8072b4e1..82226edad 100644 --- a/go.mod +++ b/go.mod @@ -8,27 +8,29 @@ replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alp require ( github.com/aptos-labs/aptos-go-sdk v1.11.0 github.com/block-vision/sui-go-sdk v1.1.2 - github.com/ethereum/go-ethereum v1.16.2 + github.com/ethereum/go-ethereum v1.16.8 github.com/gagliardetto/binary v0.8.0 github.com/gagliardetto/solana-go v1.13.0 github.com/go-playground/validator/v10 v10.28.0 github.com/google/go-cmp v0.7.0 github.com/joho/godotenv v1.5.1 github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 - github.com/samber/lo v1.49.1 + github.com/samber/lo v1.52.0 github.com/smartcontractkit/chain-selectors v1.0.89 github.com/smartcontractkit/chainlink-aptos v0.0.0-20251024142440-51f2ad2652a2 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a github.com/smartcontractkit/chainlink-sui v0.0.0-20251104205009-00bd79b81471 github.com/smartcontractkit/chainlink-testing-framework/framework v0.12.1 + github.com/smartcontractkit/chainlink-ton v0.0.0-20260115170733-b16e9683d4d5 github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e github.com/spf13/cast v1.10.0 github.com/stretchr/testify v1.11.1 + github.com/xssnick/tonutils-go v1.14.1 github.com/zksync-sdk/zksync2-go v1.1.1-0.20250620124214-2c742ee399c6 - go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.43.0 - golang.org/x/tools v0.37.0 + go.uber.org/zap v1.27.1 + golang.org/x/crypto v0.45.0 + golang.org/x/tools v0.38.0 gotest.tools/v3 v3.5.2 ) @@ -38,7 +40,9 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/BurntSushi/toml v1.5.0 // indirect github.com/DataDog/zstd v1.5.6 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect github.com/VictoriaMetrics/fastcache v1.13.0 // indirect github.com/XSAM/otelsql v0.37.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect @@ -72,9 +76,10 @@ require ( github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect - github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dchest/siphash v1.2.3 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/distribution/reference v0.6.0 // indirect @@ -83,7 +88,8 @@ require ( github.com/docker/go-units v0.5.0 // indirect github.com/ebitengine/purego v0.8.4 // indirect github.com/emicklei/dot v1.6.2 // indirect - github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab // indirect github.com/ethereum/go-verkle v0.2.2 // indirect github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -115,7 +121,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect - github.com/hashicorp/go-plugin v1.6.3 // indirect + github.com/hashicorp/go-plugin v1.7.0 // indirect github.com/hashicorp/yamux v0.1.2 // indirect github.com/hasura/go-graphql-client v0.14.5 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect @@ -137,7 +143,7 @@ require ( github.com/jmoiron/sqlx v1.4.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/compress v1.18.1 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect @@ -187,7 +193,7 @@ require ( github.com/prometheus/common v0.65.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/cors v1.11.1 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect @@ -196,13 +202,15 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v4 v4.25.5 // indirect github.com/shopspring/decimal v1.4.0 // indirect + github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20251024142759-093ed1b4017f // indirect - github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142 // indirect - github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4 // indirect - github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2 // indirect + github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260107192940-0be702ef3ff5 // indirect + github.com/smartcontractkit/chainlink-common v0.9.6-0.20260109203210-6efadaacad99 // indirect + github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 // indirect + github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20251124151448-0448aefdaab9 // indirect + github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect - github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d // indirect + github.com/smartcontractkit/libocr v0.0.0-20250912173940-f3ab0246e23d // indirect github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863 // indirect github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/stretchr/objx v0.5.2 // indirect @@ -222,8 +230,8 @@ require ( github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.mongodb.org/mongo-driver v1.17.2 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 // indirect @@ -246,16 +254,16 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.3.1 // indirect golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc // indirect - golang.org/x/net v0.46.0 // indirect - golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.37.0 // indirect - golang.org/x/term v0.36.0 // indirect - golang.org/x/text v0.30.0 // indirect + golang.org/x/net v0.47.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/term v0.37.0 // indirect + golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.12.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect - google.golang.org/grpc v1.74.2 // indirect - google.golang.org/protobuf v1.36.7 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect + google.golang.org/grpc v1.77.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 7dd33d0a9..7737e2d8c 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,8 @@ github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1 github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 h1:1zYrtlhrZ6/b6SAjLSfKzWtdgqK0U+HtH/VcBWh1BaU= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0= github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU= github.com/XSAM/otelsql v0.37.0 h1:ya5RNw028JW0eJW8Ma4AmoKxAYsJSGuNVbC7F1J457A= @@ -133,8 +135,8 @@ github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GK github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/crate-crypto/go-eth-kzg v1.3.0 h1:05GrhASN9kDAidaFJOda6A4BEvgvuXbazXg/0E3OOdI= -github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= +github.com/crate-crypto/go-eth-kzg v1.4.0 h1:WzDGjHk4gFg6YzV0rJOAsTK4z3Qkz5jd4RE3DAvPFkg= +github.com/crate-crypto/go-eth-kzg v1.4.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -152,6 +154,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA= +github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= @@ -180,10 +184,12 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w= -github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E= -github.com/ethereum/go-ethereum v1.16.2 h1:VDHqj86DaQiMpnMgc7l0rwZTg0FRmlz74yupSG5SnzI= -github.com/ethereum/go-ethereum v1.16.2/go.mod h1:X5CIOyo8SuK1Q5GnaEizQVLHT/DfsiGWuNeVdQcEMNA= +github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s= +github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk= +github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8= +github.com/ethereum/go-ethereum v1.16.8 h1:LLLfkZWijhR5m6yrAXbdlTeXoqontH+Ga2f9igY7law= +github.com/ethereum/go-ethereum v1.16.8/go.mod h1:Fs6QebQbavneQTYcA39PEKv2+zIjX7rPUZ14DER46wk= github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= @@ -318,8 +324,8 @@ github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJ github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-memdb v1.3.5 h1:b3taDMxCBCBVgyRrS1AZVHO14ubMYZB++QpNhBg+Nyo= github.com/hashicorp/go-memdb v1.3.5/go.mod h1:8IVKKBkVe+fxFgdFOYxzQQNjz+sWCyHCdIC/+5+Vy1Y= -github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= -github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= +github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshfk+mA= +github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= @@ -401,8 +407,8 @@ github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7Bd github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= -github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= +github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= +github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= @@ -420,8 +426,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co= +github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0= github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -594,8 +600,8 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -606,8 +612,8 @@ github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= -github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= +github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= +github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -622,6 +628,8 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs= +github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -630,28 +638,32 @@ github.com/smartcontractkit/chain-selectors v1.0.89 h1:L9oWZGqQXWyTPnC6ODXgu3b0D github.com/smartcontractkit/chain-selectors v1.0.89/go.mod h1:qy7whtgG5g+7z0jt0nRyii9bLND9m15NZTzuQPkMZ5w= github.com/smartcontractkit/chainlink-aptos v0.0.0-20251024142440-51f2ad2652a2 h1:vGdeMwHO3ow88HvxfhA4DDPYNY0X9jmdux7L83UF/W8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20251024142440-51f2ad2652a2/go.mod h1:iteU0WORHkArACVh/HoY/1bipV4TcNcJdTmom9uIT0E= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20251024142759-093ed1b4017f h1:jP2BHA7+QSp5IzWykT8KunThNbSwEM9j6lCXwEoxTIc= -github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20251024142759-093ed1b4017f/go.mod h1:pETrvAF8uvkZgtDgI/oRllZZaC4IpPO26tMxh1u9LC4= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260107192940-0be702ef3ff5 h1:zn5uuemiuL/Rda48li8Gql929DeYPTRhR2ZGrO3Tgz4= +github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260107192940-0be702ef3ff5/go.mod h1:k5Ln240ZCu7weL16IgR1EN5xUsgVMjU9qr84eYZfCto= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a h1:kQ8Zs6OzXizScIK8PEb8THxDUziGttGT9D6tTTAwmZk= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a/go.mod h1:Ve1xD71bl193YIZQEoJMmBqLGQJdNs29bwbuObwvbhQ= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a h1:38dAlTPRUQHZus5dCnBnQyf/V4oYn0p2svWlbPgHDQ4= github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a/go.mod h1:xtZNi6pOKdC3sLvokDvXOhgHzT+cyBqH/gWwvxTxqrg= -github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142 h1:xyGWWEwIwZv4wflEA12TDBGKEa86tDEECzl3n1Az2m0= -github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142/go.mod h1:1r3aM96KHAESfnayJ3BTHCkP1qJS1BEG1r4czeoaXlA= -github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4 h1:hvqATtrZ0iMRTI80cpBot/3JFbjz2j+2tvpfooVhRHw= -github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4/go.mod h1:eKGyfTKzr0/PeR7qKN4l2FcW9p+HzyKUwAfGhm/5YZc= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2 h1:1/KdO5AbUr3CmpLjMPuJXPo2wHMbfB8mldKLsg7D4M8= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2/go.mod h1:jUC52kZzEnWF9tddHh85zolKybmLpbQ1oNA4FjOHt1Q= +github.com/smartcontractkit/chainlink-common v0.9.6-0.20260109203210-6efadaacad99 h1:B9k1Icj8IoH9HGmMoWC6/T5IeTI3+YaPPDGWlRJQeeM= +github.com/smartcontractkit/chainlink-common v0.9.6-0.20260109203210-6efadaacad99/go.mod h1:DAwaVSiQMgAsCjHa8nOnIAM9GixuIQWsgEZFGpf3JxE= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20251124151448-0448aefdaab9 h1:QRWXJusIj/IRY5Pl3JclNvDre0cZPd/5NbILwc4RV2M= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20251124151448-0448aefdaab9/go.mod h1:jUC52kZzEnWF9tddHh85zolKybmLpbQ1oNA4FjOHt1Q= +github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b h1:QuI6SmQFK/zyUlVWEf0GMkiUYBPY4lssn26nKSd/bOM= +github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b/go.mod h1:qSTSwX3cBP3FKQwQacdjArqv0g6QnukjV4XuzO6UyoY= github.com/smartcontractkit/chainlink-sui v0.0.0-20251104205009-00bd79b81471 h1:EaLuGs7jZ6Vm2iv6rNK3bQ3XN5CRbFd4knjjvaD1zFc= github.com/smartcontractkit/chainlink-sui v0.0.0-20251104205009-00bd79b81471/go.mod h1:VlyZhVw+a93Sk8rVHOIH6tpiXrMzuWLZrjs1eTIExW8= github.com/smartcontractkit/chainlink-testing-framework/framework v0.12.1 h1:Ld3OrOQfLubJ+os0/oau2V6RISgsEdBg+Q002zkgXpQ= github.com/smartcontractkit/chainlink-testing-framework/framework v0.12.1/go.mod h1:r6KXRM1u9ch5KFR2jspkgtyWEC1X+gxPCL8mR63U990= +github.com/smartcontractkit/chainlink-ton v0.0.0-20260115170733-b16e9683d4d5 h1:qoXtC2Ypwt/4BYYCsjs58hnzL+38Mp5N7WYmN0cvMkM= +github.com/smartcontractkit/chainlink-ton v0.0.0-20260115170733-b16e9683d4d5/go.mod h1:8Nbyr/8SUFNH9wmTlT4FNd80XzlO3RN5r2DQReeXg7k= github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e h1:Hv9Mww35LrufCdM9wtS9yVi/rEWGI1UnjHbcKKU0nVY= github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d h1:/0/80Ic6wpKH5F1nwDoRj9+70IxXunvCyNcCkA+9ik0= -github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d/go.mod h1:Acy3BTBxou83ooMESLO90s8PKSu7RvLCzwSTbxxfOK0= +github.com/smartcontractkit/libocr v0.0.0-20250912173940-f3ab0246e23d h1:LokA9PoCNb8mm8mDT52c3RECPMRsGz1eCQORq+J3n74= +github.com/smartcontractkit/libocr v0.0.0-20250912173940-f3ab0246e23d/go.mod h1:Acy3BTBxou83ooMESLO90s8PKSu7RvLCzwSTbxxfOK0= github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= @@ -716,6 +728,8 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +github.com/xssnick/tonutils-go v1.14.1 h1:zV/iVYl/h3hArS+tPsd9XrSFfGert3r21caMltPSeHg= +github.com/xssnick/tonutils-go v1.14.1/go.mod h1:68xwWjpoGGqiTbLJ0gT63sKu1Z1moCnDLLzA+DKanIg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -729,10 +743,10 @@ github.com/zksync-sdk/zksync2-go v1.1.1-0.20250620124214-2c742ee399c6 h1:VRdX3Gn github.com/zksync-sdk/zksync2-go v1.1.1-0.20250620124214-2c742ee399c6/go.mod h1:NWNlQS21isOsSsn+hLRAPpiuv+3P+LcdaZNuRt2T5Yo= go.mongodb.org/mongo-driver v1.17.2 h1:gvZyk8352qSfzyZ2UMWcpDpMSGEr1eqE4T793SqyhzM= go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI= @@ -798,8 +812,8 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= @@ -819,8 +833,8 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc h1:TS73t7x3KarrNd5qAipmspBDS1rkMcgVG/fS1aRb4Rc= golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc= @@ -836,8 +850,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= -golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= +golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -867,8 +881,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -878,8 +892,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -931,10 +945,10 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8= -golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20251208220230-2638a1023523 h1:H52Mhyrc44wBgLTGzq6+0cmuVuF3LURCSXsLMOqfFos= +golang.org/x/telemetry v0.0.0-20251208220230-2638a1023523/go.mod h1:ArQvPJS723nJQietgilmZA+shuB3CZxH1n2iXq9VSfs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -944,8 +958,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -957,8 +971,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -981,8 +995,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1001,18 +1015,18 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ= -google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4= +google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= -google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= +google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= +google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1024,8 +1038,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= -google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/internal/testutils/chaintest/testchain.go b/internal/testutils/chaintest/testchain.go index 210cfd975..0c27fb075 100644 --- a/internal/testutils/chaintest/testchain.go +++ b/internal/testutils/chaintest/testchain.go @@ -31,6 +31,10 @@ var ( Chain6Selector = types.ChainSelector(Chain6RawSelector) Chain6SuiID = cselectors.SUI_TESTNET.ChainID + Chain7RawSelector = cselectors.TON_TESTNET.Selector + Chain7Selector = types.ChainSelector(Chain7RawSelector) + Chain7TONID = cselectors.TON_TESTNET.ChainID + // ChainInvalidSelector is a chain selector that doesn't exist. ChainInvalidSelector = types.ChainSelector(0) ) diff --git a/internal/testutils/signer.go b/internal/testutils/signer.go index a54b8e2ad..1750d8bcf 100644 --- a/internal/testutils/signer.go +++ b/internal/testutils/signer.go @@ -3,7 +3,6 @@ package testutils import ( "crypto/ecdsa" "slices" - "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -30,7 +29,7 @@ func MakeNewECDSASigners(n int) []ECDSASigner { } // Signers need to be sorted alphabetically slices.SortFunc(signers[:], func(a, b ECDSASigner) int { - return strings.Compare(strings.ToLower(a.Address().Hex()), strings.ToLower(b.Address().Hex())) + return a.Address().Cmp(b.Address()) }) return signers diff --git a/sdk/evm/timelock_converter.go b/sdk/evm/timelock_converter.go index ab412ead5..7022aa058 100644 --- a/sdk/evm/timelock_converter.go +++ b/sdk/evm/timelock_converter.go @@ -3,6 +3,7 @@ package evm import ( "context" "encoding/json" + "fmt" "math/big" "github.com/ethereum/go-ethereum/common" @@ -44,7 +45,7 @@ func (t TimelockConverter) ConvertBatchToChainOperations( // Unmarshal the additional fields var additionalFields AdditionalFields if err := json.Unmarshal(tx.AdditionalFields, &additionalFields); err != nil { - return []types.Operation{}, common.Hash{}, err + return []types.Operation{}, common.Hash{}, fmt.Errorf("failed to unmarshal EVM additional fields: %w", err) } calls = append(calls, bindings.RBACTimelockCall{ @@ -81,7 +82,7 @@ func (t TimelockConverter) ConvertBatchToChainOperations( } if err != nil { - return []types.Operation{}, common.Hash{}, err + return []types.Operation{}, common.Hash{}, fmt.Errorf("failed to encode timelock action data: %w", err) } op := types.Operation{ diff --git a/sdk/evm/timelock_converter_test.go b/sdk/evm/timelock_converter_test.go index ed2277d85..30c6199c5 100644 --- a/sdk/evm/timelock_converter_test.go +++ b/sdk/evm/timelock_converter_test.go @@ -2,7 +2,6 @@ package evm import ( "context" - "encoding/json" "math/big" "testing" @@ -31,7 +30,7 @@ func TestTimelockConverter_ConvertBatchToChainOperation(t *testing.T) { operation types.TimelockAction predecessor common.Hash salt common.Hash - expectedError error + expectedError string expectedOpType string }{ { @@ -52,7 +51,6 @@ func TestTimelockConverter_ConvertBatchToChainOperation(t *testing.T) { operation: types.TimelockActionSchedule, predecessor: zeroHash, salt: zeroHash, - expectedError: nil, expectedOpType: "RBACTimelock", }, { @@ -73,7 +71,6 @@ func TestTimelockConverter_ConvertBatchToChainOperation(t *testing.T) { operation: types.TimelockActionCancel, predecessor: zeroHash, salt: zeroHash, - expectedError: nil, expectedOpType: "RBACTimelock", }, { @@ -94,7 +91,7 @@ func TestTimelockConverter_ConvertBatchToChainOperation(t *testing.T) { operation: types.TimelockAction("invalid"), predecessor: zeroHash, salt: zeroHash, - expectedError: sdkerrors.NewInvalidTimelockOperationError("invalid"), + expectedError: sdkerrors.NewInvalidTimelockOperationError("invalid").Error(), expectedOpType: "", }, { @@ -112,7 +109,7 @@ func TestTimelockConverter_ConvertBatchToChainOperation(t *testing.T) { operation: types.TimelockActionSchedule, predecessor: zeroHash, salt: zeroHash, - expectedError: &json.SyntaxError{}, + expectedError: "failed to unmarshal EVM additional fields: invalid character 'i' looking for beginning of value", }, } @@ -133,10 +130,9 @@ func TestTimelockConverter_ConvertBatchToChainOperation(t *testing.T) { tc.salt, ) - if tc.expectedError != nil { + if tc.expectedError != "" { require.Error(t, err) - //nolint:testifylint // Allow IsType for error type checking - require.IsType(t, tc.expectedError, err) + require.EqualError(t, err, tc.expectedError) } else { require.NoError(t, err) require.NotEqual(t, common.Hash{}, operationID) diff --git a/sdk/sui/transaction_test.go b/sdk/sui/transaction_test.go index 2a9098d8a..7e27406c5 100644 --- a/sdk/sui/transaction_test.go +++ b/sdk/sui/transaction_test.go @@ -513,7 +513,7 @@ func TestNewTransactionWithManyStateObj(t *testing.T) { } } -func TestAdditionalFieldsJSONMarshaling(t *testing.T) { +func TestAdditionalFields_JSONMarshaling(t *testing.T) { t.Parallel() tests := []struct { diff --git a/sdk/ton/common.go b/sdk/ton/common.go new file mode 100644 index 000000000..39e9accb6 --- /dev/null +++ b/sdk/ton/common.go @@ -0,0 +1,62 @@ +package ton + +import ( + "context" + "encoding/hex" + "fmt" + + cselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton/wallet" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/mcms/types" +) + +type TxOpts struct { + Wallet *wallet.Wallet + DstAddr *address.Address + Amount tlb.Coins + Body *cell.Cell + SkipSend bool +} + +func SendTx(ctx context.Context, opts TxOpts) (types.TransactionResult, error) { + if opts.SkipSend { + var tx types.Transaction + tx, err := NewTransaction(opts.DstAddr, opts.Body.ToBuilder().ToSlice(), opts.Amount.Nano(), "", nil) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("error encoding transaction: %w", err) + } + + return types.TransactionResult{ + Hash: "", // Returning no hash since the transaction hasn't been sent yet. + ChainFamily: cselectors.FamilyTon, + RawData: tx, // will be of type types.Transaction + }, nil + } + + msg := &wallet.Message{ + Mode: wallet.PayGasSeparately | wallet.IgnoreErrors, + InternalMessage: &tlb.InternalMessage{ + IHRDisabled: true, + Bounce: true, + DstAddr: opts.DstAddr, + Amount: opts.Amount, + Body: opts.Body, + }, + } + + tx, _, err := opts.Wallet.SendWaitTransaction(ctx, msg) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to send transaction: %w", err) + } + + return types.TransactionResult{ + Hash: hex.EncodeToString(tx.Hash), + ChainFamily: cselectors.FamilyTon, + RawData: tx, // *tlb.Transaction + }, nil +} diff --git a/sdk/ton/common_test.go b/sdk/ton/common_test.go new file mode 100644 index 000000000..8a77b223b --- /dev/null +++ b/sdk/ton/common_test.go @@ -0,0 +1,19 @@ +package ton_test + +import ( + "github.com/smartcontractkit/mcms/internal/testutils" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" +) + +func must[E any](out E, err error) E { + if err != nil { + panic(err) + } + + return out +} + +func AsUint160Addr(s testutils.ECDSASigner) *tlbe.Uint160 { + return tlbe.NewUint160(s.Address().Big()) +} diff --git a/sdk/ton/config_transformer.go b/sdk/ton/config_transformer.go new file mode 100644 index 000000000..69349c2c6 --- /dev/null +++ b/sdk/ton/config_transformer.go @@ -0,0 +1,206 @@ +package ton + +import ( + "fmt" + "math" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + "github.com/smartcontractkit/mcms/sdk" + + sdkerrors "github.com/smartcontractkit/mcms/sdk/errors" + "github.com/smartcontractkit/mcms/sdk/evm" + "github.com/smartcontractkit/mcms/sdk/evm/bindings" + "github.com/smartcontractkit/mcms/types" +) + +type ConfigTransformer = sdk.ConfigTransformer[mcms.Config, any] + +var _ ConfigTransformer = &configTransformer{} + +type configTransformer struct { + evmTransformer evm.ConfigTransformer +} + +func NewConfigTransformer() ConfigTransformer { return &configTransformer{} } + +// ToChainConfig converts the chain agnostic config to the chain-specific config +func (e *configTransformer) ToChainConfig(cfg types.Config, _ any) (mcms.Config, error) { + groupQuorum, groupParents, signerAddrs, signerGroups, err := evm.ExtractSetConfigInputs(&cfg) + if err != nil { + return mcms.Config{}, fmt.Errorf("unable to extract set config inputs: %w", err) + } + + // Check the length of signerAddresses up-front + if len(signerAddrs) > math.MaxUint8 { + return mcms.Config{}, sdkerrors.NewTooManySignersError(uint64(len(signerAddrs))) + } + + // Figure out the number of groups + var groupMax uint8 + for _, v := range signerGroups { + if v > groupMax { + groupMax = v + } + } + + // Convert to the binding config + signers := make([]mcms.Signer, len(signerAddrs)) + idx := uint8(0) + for i, signerAddr := range signerAddrs { + signers[i] = mcms.Signer{ + Address: tlbe.NewUint160(signerAddr.Big()), // represented as big.Int on TON + Group: signerGroups[i], + Index: idx, + } + idx++ + } + + keySz := uint(tvm.SizeUINT8) + signersDict := cell.NewDict(keySz) + for i, s := range signers { + var sc *cell.Cell + sc, err = tlb.ToCell(s) + if err != nil { + return mcms.Config{}, fmt.Errorf("unable to encode signer %d: %w", i, err) + } + + err = signersDict.SetIntKey(big.NewInt(int64(i)), sc) + if err != nil { + return mcms.Config{}, fmt.Errorf("unable to dict.set signer %d: %w", i, err) + } + } + + sz := uint(tvm.SizeUINT8) + gqDict := cell.NewDict(keySz) + for i, g := range groupQuorum { + //nolint:gosec // G115 conversion safe, max 32 groups + if uint8(i) <= groupMax { // don't set unnecessary groups + v := cell.BeginCell().MustStoreUInt(uint64(g), sz).EndCell() + err = gqDict.SetIntKey(big.NewInt(int64(i)), v) + if err != nil { + return mcms.Config{}, fmt.Errorf("unable to dict.set group quorum %d: %w", i, err) + } + } + } + + gpDict := cell.NewDict(keySz) + for i, g := range groupParents { + //nolint:gosec // G115 conversion safe, max 32 groups + if uint8(i) <= groupMax { // don't set unnecessary groups + v := cell.BeginCell().MustStoreUInt(uint64(g), sz).EndCell() + err = gpDict.SetIntKey(big.NewInt(int64(i)), v) + if err != nil { + return mcms.Config{}, fmt.Errorf("unable to dict.set group parent %d: %w", i, err) + } + } + } + + // TODO (ton): this fn can be optimized to avoid double dict creation + _signersDict, err := tlbe.NewDictFromDictionary[uint8, mcms.Signer](signersDict) + if err != nil { + return mcms.Config{}, fmt.Errorf("unable to create signers dict: %w", err) + } + + _gqDict, err := tlbe.NewDictFromDictionary[uint8, uint8](gqDict) + if err != nil { + return mcms.Config{}, fmt.Errorf("unable to create group quorums dict: %w", err) + } + + _gpDict, err := tlbe.NewDictFromDictionary[uint8, uint8](gpDict) + if err != nil { + return mcms.Config{}, fmt.Errorf("unable to create group parents dict: %w", err) + } + + return mcms.Config{ + Signers: _signersDict, + GroupQuorums: _gqDict, + GroupParents: _gpDict, + }, nil +} + +// ToConfig Maps the chain-specific config to the chain-agnostic config +func (e *configTransformer) ToConfig(config mcms.Config) (*types.Config, error) { + _signers, err := config.Signers.AsDictionary() + if err != nil { + return nil, fmt.Errorf("unable to get signers as Dictionary: %w", err) + } + kvSigners, err := _signers.LoadAll() + if err != nil { + return nil, fmt.Errorf("unable to load signers: %w", err) + } + + // Re-using the EVM implementation here, but need to convert input first + evmConfig := bindings.ManyChainMultiSigConfig{ + Signers: make([]bindings.ManyChainMultiSigSigner, len(kvSigners)), + GroupQuorums: [32]uint8{}, + GroupParents: [32]uint8{}, + } + + for i, kvSigner := range kvSigners { + var signer mcms.Signer + err = tlb.LoadFromCell(&signer, kvSigner.Value) + if err != nil { + return nil, fmt.Errorf("unable to decode signer: %w", err) + } + + addrBytes := make([]byte, common.AddressLength) + signer.Address.Value().FillBytes(addrBytes) // TODO: tvm.KeyUINT160 + + evmConfig.Signers[i] = bindings.ManyChainMultiSigSigner{ + Addr: common.Address(addrBytes), + Index: signer.Index, + Group: signer.Group, + } + } + + _groupQuorums, err := config.GroupQuorums.AsDictionary() + if err != nil { + return nil, fmt.Errorf("unable to get group quorums as Dictionary: %w", err) + } + kvGroupQuorums, err := _groupQuorums.LoadAll() + if err != nil { + return nil, fmt.Errorf("unable to load all group quorums: %w", err) + } + + for i, kvGroupQuorum := range kvGroupQuorums { + var val uint64 + val, err = kvGroupQuorum.Value.LoadUInt(tvm.SizeUINT8) + if err != nil { + return nil, fmt.Errorf("unable to load group quorum value: %w", err) + } + + //nolint:gosec // G115 conversion safe + evmConfig.GroupQuorums[i] = uint8(val) + } + + _groupParents, err := config.GroupParents.AsDictionary() + if err != nil { + return nil, fmt.Errorf("unable to get group parents as Dictionary: %w", err) + } + + kvGroupParents, err := _groupParents.LoadAll() + if err != nil { + return nil, fmt.Errorf("unable to load group parents: %w", err) + } + + for i, kvGroupParent := range kvGroupParents { + var val uint64 + val, err = kvGroupParent.Value.LoadUInt(tvm.SizeUINT8) + if err != nil { + return nil, fmt.Errorf("unable to load group parent value: %w", err) + } + + //nolint:gosec // G115 conversion safe + evmConfig.GroupParents[i] = uint8(val) + } + + return e.evmTransformer.ToConfig(evmConfig) +} diff --git a/sdk/ton/config_transformer_test.go b/sdk/ton/config_transformer_test.go new file mode 100644 index 000000000..91df59b5a --- /dev/null +++ b/sdk/ton/config_transformer_test.go @@ -0,0 +1,428 @@ +package ton_test + +import ( + "math" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/mcms/internal/testutils" + "github.com/smartcontractkit/mcms/types" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" + + mcmston "github.com/smartcontractkit/mcms/sdk/ton" +) + +func TestConfigTransformer_ToConfig(t *testing.T) { + t.Parallel() + + signers := testutils.MakeNewECDSASigners(16) + + tests := []struct { + name string + give mcms.Config + want *types.Config + wantErr string + }{ + { + name: "success: converts binding config to config", + give: mcms.Config{ + Signers: must(tlbe.NewDictFromSlice[uint8]([]mcms.Signer{ + {Address: AsUint160Addr(signers[0]), Group: 0, Index: 0}, + {Address: AsUint160Addr(signers[1]), Group: 1, Index: 1}, + })), + GroupQuorums: must(tlbe.NewDictFromSlice[uint8]([]uint8{1, 1})), + GroupParents: must(tlbe.NewDictFromSlice[uint8]([]uint8{0, 0})), + }, + want: &types.Config{ + Quorum: 1, + Signers: []common.Address{signers[0].Address()}, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{signers[1].Address()}, + GroupSigners: []types.Config{}, + }, + }, + }, + }, + { + name: "success: nested configs", + give: mcms.Config{ + GroupQuorums: must(tlbe.NewDictFromSlice[uint8]([]uint8{2, 4, 1, 1, 3, 1})), + GroupParents: must(tlbe.NewDictFromSlice[uint8]([]uint8{0, 0, 1, 2, 0, 4})), + Signers: must(tlbe.NewDictFromSlice[uint8]([]mcms.Signer{ + {Address: AsUint160Addr(signers[0]), Index: 0, Group: 0}, + {Address: AsUint160Addr(signers[1]), Index: 1, Group: 0}, + {Address: AsUint160Addr(signers[2]), Index: 2, Group: 0}, + {Address: AsUint160Addr(signers[3]), Index: 3, Group: 1}, + {Address: AsUint160Addr(signers[4]), Index: 4, Group: 1}, + {Address: AsUint160Addr(signers[5]), Index: 5, Group: 1}, + {Address: AsUint160Addr(signers[6]), Index: 6, Group: 1}, + {Address: AsUint160Addr(signers[7]), Index: 7, Group: 1}, + {Address: AsUint160Addr(signers[8]), Index: 8, Group: 2}, + {Address: AsUint160Addr(signers[9]), Index: 9, Group: 2}, + {Address: AsUint160Addr(signers[10]), Index: 10, Group: 3}, + {Address: AsUint160Addr(signers[11]), Index: 11, Group: 4}, + {Address: AsUint160Addr(signers[12]), Index: 12, Group: 4}, + {Address: AsUint160Addr(signers[13]), Index: 13, Group: 4}, + {Address: AsUint160Addr(signers[14]), Index: 14, Group: 4}, + {Address: AsUint160Addr(signers[15]), Index: 15, Group: 5}, + })), + }, + want: &types.Config{ + Quorum: 2, + Signers: []common.Address{ + signers[0].Address(), + signers[1].Address(), + signers[2].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 4, + Signers: []common.Address{ + signers[3].Address(), + signers[4].Address(), + signers[5].Address(), + signers[6].Address(), + signers[7].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{ + signers[8].Address(), + signers[9].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{ + signers[10].Address(), + }, + GroupSigners: []types.Config{}, + }, + }, + }, + }, + }, + { + Quorum: 3, + Signers: []common.Address{ + signers[11].Address(), + signers[12].Address(), + signers[13].Address(), + signers[14].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{ + signers[15].Address(), + }, + GroupSigners: []types.Config{}, + }, + }, + }, + }, + }, + }, + { + name: "failure: validation error on resulting config", + give: mcms.Config{ + Signers: must(tlbe.NewDictFromSlice[uint8]([]mcms.Signer{ + {Address: AsUint160Addr(signers[0]), Group: 0, Index: 0}, + {Address: AsUint160Addr(signers[1]), Group: 1, Index: 1}, + })), + GroupQuorums: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 0, // A zero quorum makes this invalid + 1, + })), + GroupParents: must(tlbe.NewDictFromSlice[uint8]([]uint8{0, 0})), + }, + wantErr: "invalid MCMS config: Quorum must be greater than 0", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + transformer := mcmston.NewConfigTransformer() + got, err := transformer.ToConfig(tt.give) + + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got) + } + }) + } +} + +func TestSetConfigInputs(t *testing.T) { + t.Parallel() + + signers := testutils.MakeNewECDSASigners(5) + + tests := []struct { + name string + giveConfig types.Config + want mcms.Config + wantErr string + }{ + { + name: "success: root signers with some groups", + giveConfig: types.Config{ + Quorum: 1, + Signers: []common.Address{ + signers[0].Address(), + signers[1].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{signers[2].Address()}, + GroupSigners: []types.Config{}, + }, + }, + }, + want: mcms.Config{ + Signers: must(tlbe.NewDictFromSlice[uint8]([]mcms.Signer{ + {Address: AsUint160Addr(signers[0]), Group: 0, Index: 0}, + {Address: AsUint160Addr(signers[1]), Group: 0, Index: 1}, + {Address: AsUint160Addr(signers[2]), Group: 1, Index: 2}, + })), + GroupQuorums: must(tlbe.NewDictFromSlice[uint8]([]uint8{1, 1})), + GroupParents: must(tlbe.NewDictFromSlice[uint8]([]uint8{0, 0})), + }, + }, + { + name: "success: root signers with some groups and increased quorum", + giveConfig: types.Config{ + Quorum: 2, + Signers: []common.Address{ + signers[0].Address(), + signers[1].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{signers[2].Address()}, + GroupSigners: []types.Config{}, + }, + }, + }, + want: mcms.Config{ + Signers: must(tlbe.NewDictFromSlice[uint8]([]mcms.Signer{ + {Address: AsUint160Addr(signers[0]), Group: 0, Index: 0}, + {Address: AsUint160Addr(signers[1]), Group: 0, Index: 1}, + {Address: AsUint160Addr(signers[2]), Group: 1, Index: 2}, + })), + GroupQuorums: must(tlbe.NewDictFromSlice[uint8]([]uint8{2, 1})), + GroupParents: must(tlbe.NewDictFromSlice[uint8]([]uint8{0, 0})), + }, + }, + { + name: "success: only root signers", + giveConfig: types.Config{ + Quorum: 1, + Signers: []common.Address{ + signers[0].Address(), + signers[1].Address(), + }, + GroupSigners: []types.Config{}, + }, + want: mcms.Config{ + Signers: must(tlbe.NewDictFromSlice[uint8]([]mcms.Signer{ + {Address: AsUint160Addr(signers[0]), Group: 0, Index: 0}, + {Address: AsUint160Addr(signers[1]), Group: 0, Index: 1}, + })), + GroupQuorums: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 1, + })), + GroupParents: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 0, + })), + }, + }, + { + name: "success: only groups", + giveConfig: types.Config{ + Quorum: 2, + Signers: []common.Address{}, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{signers[0].Address()}, + GroupSigners: []types.Config{}, + }, + { + Quorum: 1, + Signers: []common.Address{signers[1].Address()}, + GroupSigners: []types.Config{}, + }, + { + Quorum: 1, + Signers: []common.Address{signers[2].Address()}, + GroupSigners: []types.Config{}, + }, + }, + }, + want: mcms.Config{ + Signers: must(tlbe.NewDictFromSlice[uint8]([]mcms.Signer{ + {Address: AsUint160Addr(signers[0]), Group: 1, Index: 0}, + {Address: AsUint160Addr(signers[1]), Group: 2, Index: 1}, + {Address: AsUint160Addr(signers[2]), Group: 3, Index: 2}, + })), + GroupQuorums: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 2, + 1, + 1, + 1, + })), + GroupParents: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 0, + 0, + 0, + 0, + })), + }, + }, + { + name: "success: nested signers and groups", + giveConfig: types.Config{ + Quorum: 2, + Signers: []common.Address{ + signers[0].Address(), + signers[1].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{signers[2].Address()}, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{signers[3].Address()}, + GroupSigners: []types.Config{}, + }, + }, + }, + { + Quorum: 1, + Signers: []common.Address{signers[4].Address()}, + GroupSigners: []types.Config{}, + }, + }, + }, + want: mcms.Config{ + Signers: must(tlbe.NewDictFromSlice[uint8]([]mcms.Signer{ + {Address: AsUint160Addr(signers[0]), Group: 0, Index: 0}, + {Address: AsUint160Addr(signers[1]), Group: 0, Index: 1}, + {Address: AsUint160Addr(signers[2]), Group: 1, Index: 2}, + {Address: AsUint160Addr(signers[3]), Group: 2, Index: 3}, + {Address: AsUint160Addr(signers[4]), Group: 3, Index: 4}, + })), + GroupQuorums: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 2, + 1, + 1, + 1, + })), + GroupParents: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 0, + 0, + 1, + 0, + })), + }, + }, + { + name: "success: unsorted signers and groups", + giveConfig: types.Config{ + Quorum: 2, + // Root signers are out of order (signer2 is before signer1) + Signers: []common.Address{ + signers[1].Address(), + signers[0].Address(), + }, + // Group signers are out of order (signer5 is before the signer4 group) + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{signers[2].Address()}, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{signers[4].Address()}, + GroupSigners: []types.Config{}, + }, + }, + }, + { + Quorum: 1, + Signers: []common.Address{signers[3].Address()}, + GroupSigners: []types.Config{}, + }, + }, + }, + want: mcms.Config{ + Signers: must(tlbe.NewDictFromSlice[uint8]([]mcms.Signer{ + {Address: AsUint160Addr(signers[0]), Group: 0, Index: 0}, + {Address: AsUint160Addr(signers[1]), Group: 0, Index: 1}, + {Address: AsUint160Addr(signers[2]), Group: 1, Index: 2}, + {Address: AsUint160Addr(signers[3]), Group: 3, Index: 3}, + {Address: AsUint160Addr(signers[4]), Group: 2, Index: 4}, + })), + GroupQuorums: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 2, + 1, + 1, + 1, + })), + GroupParents: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 0, + 0, + 1, + 0, + })), + }, + }, + { + name: "failure: signer count cannot exceed 255", + giveConfig: types.Config{ + Quorum: 1, + Signers: make([]common.Address, math.MaxUint8+1), + }, + wantErr: "too many signers: 256 max number is 255", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + transformer := mcmston.NewConfigTransformer() + got, err := transformer.ToChainConfig(tt.giveConfig, nil) + + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got) + + recovered, err := transformer.ToConfig(got) + require.NoError(t, err) + // Notice: compare .GroupSigners to avoid issues with recovering case unsorted_signers_and_groups + assert.Equal(t, tt.giveConfig.GroupSigners, recovered.GroupSigners) + } + }) + } +} diff --git a/sdk/ton/configurer.go b/sdk/ton/configurer.go new file mode 100644 index 000000000..d49ccc5a9 --- /dev/null +++ b/sdk/ton/configurer.go @@ -0,0 +1,117 @@ +package ton + +import ( + "context" + "fmt" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/sdk/evm" + "github.com/smartcontractkit/mcms/types" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton/wallet" +) + +var _ sdk.Configurer = &configurer{} + +type configurer struct { + wallet *wallet.Wallet + + // Transaction opts + amount tlb.Coins + + skipSend bool +} + +// NewConfigurer creates a new Configurer for TON chains. +// +// options: +// +// WithDoNotSendInstructionsOnChain: when selected, the Configurer instance will not +// send the TON instructions to the blockchain. +func NewConfigurer(w *wallet.Wallet, amount tlb.Coins, opts ...ConfigurerOption) (sdk.Configurer, error) { + c := configurer{w, amount, false} + + for _, o := range opts { + o(&c) + } + + return c, nil +} + +type ConfigurerOption func(*configurer) + +// WithDoNotSendInstructionsOnChain sets the configurer to not sign and send the configuration transaction +// but rather make it return a prepared MCMS types.Transaction instead. +// If set, the Hash field in the result will be empty. +func WithDoNotSendInstructionsOnChain() ConfigurerOption { + return func(c *configurer) { + c.skipSend = true + } +} + +func (c configurer) SetConfig(ctx context.Context, mcmsAddr string, cfg *types.Config, clearRoot bool) (types.TransactionResult, error) { + // Map to Ton Address type + dstAddr, err := address.ParseAddr(mcmsAddr) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("invalid mcms address: %w", err) + } + + groupQuorum, groupParents, signerAddresses, _signerGroups, err := evm.ExtractSetConfigInputs(cfg) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("unable to extract set config inputs: %w", err) + } + + signerKeys := make([]mcms.SignerAddress, len(signerAddresses)) + for i, addr := range signerAddresses { + signerKeys[i] = mcms.SignerAddress{Val: tlbe.NewUint160(addr.Big())} + } + + signerGroups := make([]mcms.SignerGroup, len(_signerGroups)) + for i, g := range _signerGroups { + signerGroups[i] = mcms.SignerGroup{Val: g} + } + + // Encode SetConfig message + gqDict, err := tlbe.NewDictFromSlice[uint8](groupQuorum[:]) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("unable to create group quorum dict: %w", err) + } + + gpDict, err := tlbe.NewDictFromSlice[uint8](groupParents[:]) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("unable to create group parents dict: %w", err) + } + + qID, err := tvm.RandomQueryID() + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to generate random query ID: %w", err) + } + + body, err := tlb.ToCell(mcms.SetConfig{ + QueryID: qID, + + SignerAddresses: signerKeys, + SignerGroups: signerGroups, + GroupQuorums: gqDict, + GroupParents: gpDict, + + ClearRoot: clearRoot, + }) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to encode SetConfig body: %w", err) + } + + return SendTx(ctx, TxOpts{ + Wallet: c.wallet, + DstAddr: dstAddr, + Amount: c.amount, + Body: body, + SkipSend: c.skipSend, + }) +} diff --git a/sdk/ton/configurer_test.go b/sdk/ton/configurer_test.go new file mode 100644 index 000000000..3c1c6ce2f --- /dev/null +++ b/sdk/ton/configurer_test.go @@ -0,0 +1,195 @@ +package ton_test + +import ( + "context" + "errors" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/mcms/internal/testutils" + "github.com/smartcontractkit/mcms/internal/testutils/chaintest" + "github.com/smartcontractkit/mcms/types" + + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + mcmston "github.com/smartcontractkit/mcms/sdk/ton" + ton_mocks "github.com/smartcontractkit/mcms/sdk/ton/mocks" +) + +// TestConfigurer_SetConfig tests the SetConfig method of the Configurer. +func TestConfigurer_SetConfig(t *testing.T) { + t.Parallel() + + ctx := context.Background() + + signers := testutils.MakeNewECDSASigners(16) + + tests := []struct { + name string + options []mcmston.ConfigurerOption + mcmAddr string + cfg *types.Config + clearRoot bool + mockSetup func(m *ton_mocks.TonAPI) + want string + wantErr error + }{ + { + name: "success", + options: []mcmston.ConfigurerOption{}, + mcmAddr: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + cfg: &types.Config{ + Quorum: 2, + Signers: []common.Address{ + signers[1].Address(), + signers[2].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{ + signers[3].Address(), + }, + GroupSigners: nil, + }, + }, + }, + clearRoot: true, + mockSetup: func(m *ton_mocks.TonAPI) { + // Mock CurrentMasterchainInfo + m.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + // Mock WaitForBlock + apiw := ton_mocks.NewAPIClientWrapped(t) + apiw.EXPECT().GetAccount(mock.Anything, mock.Anything, mock.Anything). + Return(&tlb.Account{}, nil) + + apiw.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(ton.NewExecutionResult([]any{big.NewInt(5)}), nil) + + m.EXPECT().WaitForBlock(mock.Anything). + Return(apiw) + + m.EXPECT().SendExternalMessageWaitTransaction(mock.Anything, mock.Anything). + Return(&tlb.Transaction{Hash: []byte{1, 2, 3, 4, 14}}, &ton.BlockIDExt{}, []byte{}, nil) + }, + want: "010203040e", + wantErr: nil, + }, + { + name: "success - WithDoNotSendInstructionsOnChain option", + options: []mcmston.ConfigurerOption{ + mcmston.WithDoNotSendInstructionsOnChain(), + }, + mcmAddr: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + cfg: &types.Config{ + Quorum: 2, + Signers: []common.Address{ + signers[1].Address(), + signers[2].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{ + signers[3].Address(), + }, + GroupSigners: nil, + }, + }, + }, + clearRoot: true, + mockSetup: func(m *ton_mocks.TonAPI) { + // No mocks needed as transaction won't be sent + }, + want: "", // Hash is empty when not sending transaction + wantErr: nil, + }, + { + name: "failure - SendTransaction fails", + options: []mcmston.ConfigurerOption{}, + mcmAddr: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + cfg: &types.Config{ + Quorum: 2, + Signers: []common.Address{ + signers[1].Address(), + signers[2].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 1, + Signers: []common.Address{ + signers[3].Address(), + }, + GroupSigners: nil, + }, + }, + }, + clearRoot: false, + mockSetup: func(m *ton_mocks.TonAPI) { + // Mock CurrentMasterchainInfo + m.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + // Mock WaitForBlock + apiw := ton_mocks.NewAPIClientWrapped(t) + apiw.EXPECT().GetAccount(mock.Anything, mock.Anything, mock.Anything). + Return(&tlb.Account{}, nil) + + apiw.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(ton.NewExecutionResult([]any{big.NewInt(5)}), nil) + + m.EXPECT().WaitForBlock(mock.Anything). + Return(apiw) + + // Mock SendTransaction to return an error + m.EXPECT().SendExternalMessageWaitTransaction(mock.Anything, mock.Anything). + Return(&tlb.Transaction{Hash: []byte{1, 2, 3, 4, 14}}, &ton.BlockIDExt{}, []byte{}, errors.New("transaction failed")) + }, + want: "", + wantErr: errors.New("transaction failed"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + _api := ton_mocks.NewTonAPI(t) + chainID := chaintest.Chain7TONID + walletOperator := must(tvm.NewRandomV5R1TestWallet(_api, chainID)) + + // Apply the mock setup for the ContractDeployBackend + if tt.mockSetup != nil { + tt.mockSetup(_api) + } + + // Create the Configurer instance + configurer, err := mcmston.NewConfigurer(walletOperator, tlb.MustFromTON("0.1"), tt.options...) + require.NoError(t, err) + + // Call SetConfig + tx, err := configurer.SetConfig(ctx, tt.mcmAddr, tt.cfg, tt.clearRoot) + + // Assert the results + if tt.wantErr != nil { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.wantErr.Error()) + assert.Empty(t, tx.Hash) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, tx.Hash) + } + }) + } +} diff --git a/sdk/ton/decoded_operation.go b/sdk/ton/decoded_operation.go new file mode 100644 index 000000000..3c07513b1 --- /dev/null +++ b/sdk/ton/decoded_operation.go @@ -0,0 +1,59 @@ +package ton + +import ( + "encoding/json" + "errors" + "fmt" + + "github.com/smartcontractkit/mcms/sdk" +) + +type DecodedOperation struct { + ContractType string + MsgType string + MsgOpcode uint64 + + // Message data + MsgDecoded any // normalized and decoded cell structure + InputKeys []string + InputArgs []any +} + +var _ sdk.DecodedOperation = &DecodedOperation{} + +func NewDecodedOperation(contractType string, msgType string, msgOpcode uint64, msgDecoded any, inputKeys []string, inputArgs []any) (sdk.DecodedOperation, error) { + if len(inputKeys) != len(inputArgs) { + return nil, errors.New("input keys and input args must have the same length") + } + + return &DecodedOperation{contractType, msgType, msgOpcode, msgDecoded, inputKeys, inputArgs}, nil +} + +func (o *DecodedOperation) MethodName() string { + return fmt.Sprintf("%s::%s(0x%x)", o.ContractType, o.MsgType, o.MsgOpcode) +} + +func (o *DecodedOperation) Keys() []string { + return o.InputKeys +} + +func (o *DecodedOperation) Args() []any { + return o.InputArgs +} + +func (o *DecodedOperation) String() (string, string, error) { + // Create a human readable representation of the decoded operation + // by displaying a map of input keys to input values + // e.g. {"key1": "value1", "key2": "value2"} + + // Notice: cell is an encoded tree structure, where args can be nested so we print + // out the full decoded structure here, but we only return the first layer of keys + // and args via Keys() and Args() respective funcs. + + byteMap, err := json.MarshalIndent(o.MsgDecoded, "", " ") + if err != nil { + return "", "", fmt.Errorf("failed to JSON marshal the decoded op: %w", err) + } + + return o.MethodName(), string(byteMap), nil +} diff --git a/sdk/ton/decoded_operation_test.go b/sdk/ton/decoded_operation_test.go new file mode 100644 index 000000000..da4c140a9 --- /dev/null +++ b/sdk/ton/decoded_operation_test.go @@ -0,0 +1,92 @@ +package ton_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/mcms/sdk/ton" +) + +func TestNewDecodedOperation(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + contractType string + msgType string + msgOpcode uint64 + msgDecoded map[string]any + inputKeys []string + inputArgs []any + wantMethod string + wantErr string + }{ + { + name: "success", + contractType: "com.foo.acc", + msgType: "functionName", + msgOpcode: 0x1, + msgDecoded: map[string]any{ + "inputKey1": "inputArg1", + "inputKey2": "inputArg2", + }, + inputKeys: []string{"inputKey1", "inputKey2"}, + inputArgs: []any{"inputArg1", "inputArg2"}, + wantMethod: "com.foo.acc::functionName(0x1)", + }, + { + name: "success with empty input keys and args", + contractType: "com.foo.acc", + msgType: "functionName", + msgOpcode: 0x7362d09c, + msgDecoded: map[string]any{}, + inputKeys: []string{}, + inputArgs: []any{}, + wantMethod: "com.foo.acc::functionName(0x7362d09c)", + }, + { + name: "error with mismatched input keys and args", + contractType: "com.foo.acc", + msgType: "functionName", + msgOpcode: 0x1, + msgDecoded: map[string]any{ + "inputKey1": "inputArg1", + "inputKey2": "inputArg2", + }, + inputKeys: []string{"inputKey1", "inputKey2"}, + inputArgs: []any{"inputArg1"}, + wantMethod: "com.foo.acc::functionName(0x1)", + wantErr: "input keys and input args must have the same length", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got, err := ton.NewDecodedOperation(tt.contractType, tt.msgType, tt.msgOpcode, tt.msgDecoded, tt.inputKeys, tt.inputArgs) + if tt.wantErr != "" { + require.Error(t, err) + assert.EqualError(t, err, tt.wantErr) + } else { + require.NoError(t, err) + + // Test member functions + assert.Equal(t, tt.wantMethod, got.MethodName()) + assert.Equal(t, tt.inputKeys, got.Keys()) + assert.Equal(t, tt.inputArgs, got.Args()) + + // Test String() + fn, inputs, err := got.String() + require.NoError(t, err) + assert.Equal(t, tt.wantMethod, fn) + for i := range tt.inputKeys { + assert.Contains(t, inputs, fmt.Sprintf(`"%s": "%v"`, tt.inputKeys[i], tt.inputArgs[i])) + } + } + }) + } +} diff --git a/sdk/ton/decoder.go b/sdk/ton/decoder.go new file mode 100644 index 000000000..5f023d69d --- /dev/null +++ b/sdk/ton/decoder.go @@ -0,0 +1,77 @@ +package ton + +import ( + "fmt" + + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +type decoder struct { + // Map of contract type to TL-B definitions (type -> opcode -> TL-B struct) + TypeToTLBMap map[string]tvm.TLBMap +} + +var _ sdk.Decoder = &decoder{} + +func NewDecoder(tlbs map[string]tvm.TLBMap) sdk.Decoder { + return &decoder{ + TypeToTLBMap: tlbs, + } +} + +func (d *decoder) Decode(tx types.Transaction, contractInterfaces string) (sdk.DecodedOperation, error) { + contractType := contractInterfaces + tlbs, ok := d.TypeToTLBMap[contractType] + if !ok { + return nil, fmt.Errorf("decoding failed - unknown contract interface: %s", contractType) + } + + datac, err := cell.FromBOC(tx.Data) + if err != nil { + return nil, fmt.Errorf("invalid cell BOC data: %w", err) + } + + // Handle message with no body - empty cell + isEmpty := datac.RefsNum() == 0 && datac.BitsSize() == 0 + if isEmpty { + return NewDecodedOperation(contractType, "", 0, map[string]any{}, []string{}, []any{}) + } + + msgType, msgDecoded, err := codec.DecodeTLBValToJSON(datac, tlbs) + if err != nil { + return nil, fmt.Errorf("error while JSON decoding message (cell) for contract %s: %w", contractType, err) + } + + if msgType == "Cell" || msgType == "" { // on decoder fallback (not decoded) + return nil, fmt.Errorf("failed to decode message for contract %s: %w", contractType, err) + } + + // Extract the input keys and args (tree/map lvl 0) + keys, err := codec.DecodeTLBStructKeys(datac, tlbs) + if err != nil { + return nil, fmt.Errorf("error while (struct) decoding message (cell) for contract %s: %w", contractType, err) + } + inputKeys := make([]string, len(keys)) + inputArgs := make([]any, len(keys)) + + m, ok := msgDecoded.(map[string]any) // JSON normalized + if !ok { + return nil, fmt.Errorf("failed to cast as map %s: %w", contractType, err) + } + + // Notice: sorting keys based on TL-B order (decoded map is unsorted) + for i, k := range keys { + inputKeys[i] = k + inputArgs[i] = m[k] + } + + msgOpcode := uint64(0) // TODO (ton): not exposed currently + + return NewDecodedOperation(contractType, msgType, msgOpcode, msgDecoded, inputKeys, inputArgs) +} diff --git a/sdk/ton/decoder_test.go b/sdk/ton/decoder_test.go new file mode 100644 index 000000000..080e4fd27 --- /dev/null +++ b/sdk/ton/decoder_test.go @@ -0,0 +1,119 @@ +package ton_test + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/lib/access/rbac" + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/timelock" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + "github.com/smartcontractkit/mcms/sdk/ton" + "github.com/smartcontractkit/mcms/types" +) + +// Map of contract type to TL-B definitions (type -> opcode -> TL-B struct) +var typeToTLBMap = map[string]tvm.TLBMap{ + // MCMS contract types + "com.chainlink.ton.lib.access.RBAC": rbac.TLBs, + "com.chainlink.ton.mcms.MCMS": mcms.TLBs, + "com.chainlink.ton.mcms.Timelock": timelock.TLBs, +} + +func TestDecoder(t *testing.T) { + t.Parallel() + + exampleRole := crypto.Keccak256Hash([]byte("EXAMPLE_ROLE")) + // Notice: need to convert to Uint256 (big.Int) + exampleRoleBig := tlbe.NewUint256(exampleRole.Big()) + + // Grant role data + grantRoleData, err := tlb.ToCell(rbac.GrantRole{ + QueryID: 0x1, + Role: exampleRoleBig, + Account: address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8"), + }) + require.NoError(t, err) + + tests := []struct { + name string + give types.Operation + contractInterfaces string + want *ton.DecodedOperation + wantErr string + }{ + { + name: "success - empty message", + give: types.Operation{ + ChainSelector: 1, + Transaction: must(ton.NewTransaction( + address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8"), + cell.BeginCell().ToSlice(), + big.NewInt(0), + "RBACTimelock", + []string{"topUp"}, + )), + }, + contractInterfaces: "com.chainlink.ton.lib.access.RBAC", + want: &ton.DecodedOperation{ + ContractType: "com.chainlink.ton.lib.access.RBAC", + MsgType: "", + MsgDecoded: map[string]any{}, + InputKeys: []string{}, + InputArgs: []any{}, + }, + wantErr: "", + }, + { + name: "success - message with body", + give: types.Operation{ + ChainSelector: 1, + Transaction: must(ton.NewTransaction( + address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8"), + grantRoleData.ToBuilder().ToSlice(), + big.NewInt(0), + "RBACTimelock", + []string{"grantRole"}, + )), + }, + contractInterfaces: "com.chainlink.ton.lib.access.RBAC", + want: &ton.DecodedOperation{ + ContractType: "com.chainlink.ton.lib.access.RBAC", + MsgType: "GrantRole", + MsgDecoded: map[string]any{ + "QueryID": uint64(0x1), + "Role": exampleRoleBig, + "Account": address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8"), + }, + InputKeys: []string{"QueryID", "Role", "Account"}, + InputArgs: []any{uint64(0x1), exampleRoleBig, address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8")}, + }, + wantErr: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + d := ton.NewDecoder(typeToTLBMap) + got, err := d.Decode(tt.give.Transaction, tt.contractInterfaces) + if tt.wantErr != "" { + require.Error(t, err) + assert.EqualError(t, err, tt.wantErr) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got) + } + }) + } +} diff --git a/sdk/ton/encoder.go b/sdk/ton/encoder.go new file mode 100644 index 000000000..066c0a665 --- /dev/null +++ b/sdk/ton/encoder.go @@ -0,0 +1,214 @@ +package ton + +import ( + "encoding/json" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + chain_selectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + "github.com/smartcontractkit/mcms/sdk" + sdkerrors "github.com/smartcontractkit/mcms/sdk/errors" + "github.com/smartcontractkit/mcms/types" +) + +var _ sdk.Encoder = &Encoder{} + +// Implementations of various encoding interfaces for TON MCMS +var _ RootMetadataEncoder[mcms.RootMetadata] = &Encoder{} +var _ OperationEncoder[mcms.Op] = &Encoder{} +var _ ProofEncoder[mcms.Proof] = &Encoder{} +var _ SignaturesEncoder[mcms.Signature] = &Encoder{} + +// TODO: bubble up to sdk, use in evm as well +// Defines encoding from sdk types.ChainMetadata to chain type RootMetadata T +type RootMetadataEncoder[T any] interface { + ToRootMetadata(metadata types.ChainMetadata) (T, error) +} + +// TODO: bubble up to sdk, use in evm as well +// Defines encoding from sdk types.ChainMetadata + types.Operation to chain type Operation T +type OperationEncoder[T any] interface { + ToOperation(opCount uint32, metadata types.ChainMetadata, op types.Operation) (T, error) +} + +// TODO: bubble up to sdk, use in evm as well +// Defines encoding from sdk []common.Hash to chain type Proof []T +type ProofEncoder[T any] interface { + ToProof(p []common.Hash) ([]T, error) +} + +// TODO: bubble up to sdk, use in evm as well +// Defines encoding from sdk []types.Signature to chain type Signature []T +type SignaturesEncoder[T any] interface { + ToSignatures(s []types.Signature, hash common.Hash) ([]T, error) +} + +// Encoder encoding MCMS operations and metadata into hashes. +type Encoder struct { + ChainSelector types.ChainSelector + TxCount uint64 + OverridePreviousRoot bool +} + +func NewEncoder(chainSelector types.ChainSelector, txCount uint64, overridePreviousRoot bool) sdk.Encoder { + return &Encoder{ + ChainSelector: chainSelector, + TxCount: txCount, + OverridePreviousRoot: overridePreviousRoot, + } +} + +func (e *Encoder) HashOperation(opCount uint32, metadata types.ChainMetadata, op types.Operation) (common.Hash, error) { + opBind, err := e.ToOperation(opCount, metadata, op) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to convert operation: %w", err) + } + + opCell, err := tlb.ToCell(opBind) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to encode op: %w", err) + } + + // Hash operation according to TON specs + // @dev we use the standard sha256 (cell) hash function to hash the leaf. + b := cell.BeginCell() + if err := b.StoreBigUInt(new(big.Int).SetBytes(mcms.ManyChainMultiSigDomainSeparatorOp[:]), tvm.SizeUINT256); err != nil { + return common.Hash{}, fmt.Errorf("failed to store domain separator: %w", err) + } + if err := b.StoreRef(opCell); err != nil { + return common.Hash{}, fmt.Errorf("failed to store op cell ref: %w", err) + } + + var hash common.Hash + copy(hash[:], b.EndCell().Hash()[:32]) + + return hash, nil +} + +func (e *Encoder) HashMetadata(metadata types.ChainMetadata) (common.Hash, error) { + rm, err := e.ToRootMetadata(metadata) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to convert to root metadata: %w", err) + } + + // Encode metadata according to TON specs + metaCell, err := tlb.ToCell(rm) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to encode op: %w", err) + } + + // Hash metadata according to TON specs + // @dev we use the standard sha256 (cell) hash function to hash the leaf. + b := cell.BeginCell() + if err := b.StoreBigUInt(new(big.Int).SetBytes(mcms.ManyChainMultiSigDomainSeparatorMetadata[:]), tvm.SizeUINT256); err != nil { + return common.Hash{}, fmt.Errorf("failed to store domain separator: %w", err) + } + if err := b.StoreBuilder(metaCell.ToBuilder()); err != nil { + return common.Hash{}, fmt.Errorf("failed to store metadata bytes: %w", err) + } + + var hash common.Hash + copy(hash[:], b.EndCell().Hash()[:32]) + + return hash, nil +} + +func (e *Encoder) ToOperation(opCount uint32, metadata types.ChainMetadata, op types.Operation) (mcms.Op, error) { + chainID, err := chain_selectors.TonChainIdFromSelector(uint64(e.ChainSelector)) + if err != nil { + return mcms.Op{}, &sdkerrors.InvalidChainIDError{ReceivedChainID: e.ChainSelector} + } + + // Unmarshal the AdditionalFields from the operation + var additionalFields AdditionalFields + if err = json.Unmarshal(op.Transaction.AdditionalFields, &additionalFields); err != nil { + return mcms.Op{}, err + } + + // Map to Ton Address types + mcmsAddr, err := address.ParseAddr(metadata.MCMAddress) + if err != nil { + return mcms.Op{}, fmt.Errorf("invalid mcms address: %w", err) + } + + toAddr, err := address.ParseAddr(op.Transaction.To) + if err != nil { + return mcms.Op{}, fmt.Errorf("invalid to address: %w", err) + } + + datac, err := cell.FromBOC(op.Transaction.Data) + if err != nil { + return mcms.Op{}, fmt.Errorf("invalid cell BOC data: %w", err) + } + + return mcms.Op{ + ChainID: new(big.Int).SetInt64(int64(chainID)), + MultiSig: mcmsAddr, + Nonce: uint64(opCount), + To: toAddr, + Data: datac, + Value: tlb.FromNanoTON(additionalFields.Value), + }, nil +} + +func (e *Encoder) ToRootMetadata(metadata types.ChainMetadata) (mcms.RootMetadata, error) { + chainID, err := chain_selectors.TonChainIdFromSelector(uint64(e.ChainSelector)) + if err != nil { + return mcms.RootMetadata{}, &sdkerrors.InvalidChainIDError{ReceivedChainID: e.ChainSelector} + } + + // Map to Ton Address type (mcms.address) + mcmsAddr, err := address.ParseAddr(metadata.MCMAddress) + if err != nil { + return mcms.RootMetadata{}, fmt.Errorf("invalid mcms address: %w", err) + } + + return mcms.RootMetadata{ + ChainID: new(big.Int).SetInt64(int64(chainID)), + MultiSig: mcmsAddr, + PreOpCount: metadata.StartingOpCount, + PostOpCount: metadata.StartingOpCount + e.TxCount, + OverridePreviousRoot: e.OverridePreviousRoot, + }, nil +} + +func (e *Encoder) ToProof(p []common.Hash) ([]mcms.Proof, error) { + proofs := make([]mcms.Proof, 0, len(p)) + for _, hash := range p { + proofs = append(proofs, mcms.Proof{Val: tlbe.NewUint256(hash.Big())}) + } + + return proofs, nil +} + +const ( + SignatureVOffset = 27 + SignatureVThreshold = 2 +) + +func (e *Encoder) ToSignatures(ss []types.Signature, hash common.Hash) ([]mcms.Signature, error) { + bindSignatures := make([]mcms.Signature, 0, len(ss)) + for _, s := range ss { + if s.V < SignatureVThreshold { + s.V += SignatureVOffset + } + + bindSignatures = append(bindSignatures, mcms.Signature{ + V: s.V, + R: new(big.Int).SetBytes(s.R.Bytes()), + S: new(big.Int).SetBytes(s.S.Bytes()), + }) + } + + return bindSignatures, nil +} diff --git a/sdk/ton/encoder_test.go b/sdk/ton/encoder_test.go new file mode 100644 index 000000000..7757975d1 --- /dev/null +++ b/sdk/ton/encoder_test.go @@ -0,0 +1,269 @@ +package ton_test + +import ( + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + cselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/mcms/internal/testutils/chaintest" + "github.com/smartcontractkit/mcms/sdk/ton" + "github.com/smartcontractkit/mcms/types" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" +) + +func TestEncoder_HashOperation(t *testing.T) { + t.Parallel() + + var ( + // Static argument values to HashOperation since they don't affect the test + giveOpCount = uint32(0) + giveMetadata = types.ChainMetadata{ + StartingOpCount: 0, + MCMAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + } + ) + + tests := []struct { + name string + giveOp types.Operation + want string + wantErr string + }{ + { + name: "success: hash operation", + giveOp: types.Operation{ + ChainSelector: chaintest.Chain7Selector, + Transaction: must(ton.NewTransaction( + address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8"), + cell.BeginCell().MustStoreBinarySnake([]byte("data")).ToSlice(), + new(big.Int).SetUint64(1000000000000000000), + "", + []string{}, + )), + }, + want: "0x5f473c83be95f5666ec098506843a1b03878dab0dba84bb5ba9fa52172b87138", + }, + { + name: "failure: cannot unmarshal additional fields", + giveOp: types.Operation{ + ChainSelector: chaintest.Chain7Selector, + Transaction: types.Transaction{ + AdditionalFields: []byte("invalid"), + }, + }, + wantErr: "failed to convert operation: invalid character 'i' looking for beginning of value", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + encoder := ton.NewEncoder(chaintest.Chain7Selector, 5, false) + got, err := encoder.HashOperation(giveOpCount, giveMetadata, tt.giveOp) + + if tt.wantErr != "" { + require.Error(t, err) + require.EqualError(t, err, tt.wantErr) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got.Hex()) + } + }) + } +} + +func TestEncoder_HashMetadata(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + giveSelector types.ChainSelector + giveMeta types.ChainMetadata + want string + wantErr string + }{ + { + name: "success: hash metadata", + giveSelector: chaintest.Chain7Selector, + giveMeta: types.ChainMetadata{ + StartingOpCount: 0, + MCMAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + }, + want: "0xdc28983fc828ede55ccd16567b1e0b7ae74e28f96c4e6383357c175550d363fb", + // TODO (ton): fix me, the above hash is bc we replace -217 chain id with -1 (mylocalton bug) + // want: "0x4e376893226a88f610e5e741ec88ada4deff4c29b7c0611c7f7c80ce0a847924", + }, + { + name: "failure: could not get TON chain id", + giveSelector: chaintest.ChainInvalidSelector, + giveMeta: types.ChainMetadata{}, + wantErr: "failed to convert to root metadata: invalid chain ID: 0", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + encoder := ton.NewEncoder(tt.giveSelector, 1, false) + got, err := encoder.HashMetadata(tt.giveMeta) + + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got.Hex()) + } + }) + } +} + +func TestEncoder_ToOperation(t *testing.T) { + t.Parallel() + + var ( + chainID = int32(-217) + chainSelector = types.ChainSelector(cselectors.TonChainIdToChainSelector()[chainID]) + + // Static argument values to ToGethOperation since they don't affect the test + giveOpCount = uint32(0) + giveMetadata = types.ChainMetadata{ + StartingOpCount: 0, + MCMAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + } + ) + + tests := []struct { + name string + giveSelector types.ChainSelector + giveOp types.Operation + want mcms.Op + wantErr string + }{ + { + name: "success: converts to a TON mcms.Op operations", + giveSelector: chaintest.Chain7Selector, + giveOp: types.Operation{ + ChainSelector: chainSelector, + Transaction: must(ton.NewTransaction( + address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8"), + cell.BeginCell().MustStoreBinarySnake([]byte("data")).ToSlice(), + new(big.Int).SetUint64(1000000000000000000), + "", + []string{}, + )), + }, + want: mcms.Op{ + ChainID: new(big.Int).SetInt64(int64(chaintest.Chain7TONID)), + MultiSig: address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8"), + Nonce: uint64(0), + To: address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8"), + // Notice: we wrap in BOC as it decodes differently to pass the equality test + // - refs: ([]*cell.Cell) + // + refs: ([]*cell.Cell) {} + Data: must(cell.FromBOC(cell.BeginCell().MustStoreBinarySnake([]byte("data")).EndCell().ToBOC())), + Value: tlb.MustFromTON("1000000000"), + }, + }, + { + name: "failure: invalid chain selector", + giveSelector: chaintest.ChainInvalidSelector, + giveOp: types.Operation{}, + wantErr: "invalid chain ID: 0", + }, + { + name: "failure: cannot unmarshal additional fields", + giveSelector: chaintest.Chain7Selector, + giveOp: types.Operation{ + ChainSelector: chainSelector, + Transaction: types.Transaction{ + AdditionalFields: []byte("invalid"), + }, + }, + wantErr: "invalid character 'i' looking for beginning of value", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + encoder := ton.NewEncoder(tt.giveSelector, 5, false) + got, err := encoder.(ton.OperationEncoder[mcms.Op]).ToOperation(giveOpCount, giveMetadata, tt.giveOp) + + if tt.wantErr != "" { + require.Error(t, err) + require.EqualError(t, err, tt.wantErr) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got) + } + }) + } +} + +func TestEncoder_ToRootMetadata(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + giveSelector types.ChainSelector + giveMetadata types.ChainMetadata + want mcms.RootMetadata + wantErr string + }{ + { + name: "success: converts to a geth root metadata", + giveSelector: chaintest.Chain7Selector, + giveMetadata: types.ChainMetadata{ + StartingOpCount: 0, + MCMAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + }, + want: mcms.RootMetadata{ + ChainID: new(big.Int).SetInt64(int64(chaintest.Chain7TONID)), + MultiSig: address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8"), + PreOpCount: uint64(0), + PostOpCount: uint64(5), + OverridePreviousRoot: false, + }, + }, + { + name: "faiure: invalid chain selector", + giveSelector: chaintest.ChainInvalidSelector, + giveMetadata: types.ChainMetadata{}, + wantErr: "invalid chain ID: 0", + }, + { + name: "faiure: invalid mcms address", + giveSelector: chaintest.Chain7Selector, + giveMetadata: types.ChainMetadata{ + StartingOpCount: 0, + MCMAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-", // invalid address + }, + wantErr: "invalid mcms address: incorrect address data", + }, + } + + txCount := uint64(5) + for _, tt := range tests { + encoder := ton.NewEncoder(tt.giveSelector, txCount, false) + got, err := encoder.(ton.RootMetadataEncoder[mcms.RootMetadata]).ToRootMetadata(tt.giveMetadata) + + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got) + } + } +} diff --git a/sdk/ton/executor.go b/sdk/ton/executor.go new file mode 100644 index 000000000..b88be2180 --- /dev/null +++ b/sdk/ton/executor.go @@ -0,0 +1,199 @@ +package ton + +import ( + "context" + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/samber/lo" + + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/ton/wallet" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +// sdk.Executor implementation for TON chains, allowing for the execution of operations on the MCMS contract +type executor struct { + sdk.Encoder + sdk.Inspector + + wallet *wallet.Wallet + + // Transaction opts + amount tlb.Coins +} + +type ExecutorOpts struct { + Encoder sdk.Encoder + Client ton.APIClientWrapped + Wallet *wallet.Wallet + Amount tlb.Coins +} + +// NewExecutor creates a new Executor for TON chains +func NewExecutor(opts ExecutorOpts) (sdk.Executor, error) { + if lo.IsNil(opts.Encoder) { + return nil, errors.New("failed to create sdk.Executor - encoder (sdk.Encoder) is nil") + } + + if lo.IsNil(opts.Client) { + return nil, errors.New("failed to create sdk.Executor - client (ton.APIClientWrapped) is nil") + } + + if opts.Wallet == nil { + return nil, errors.New("failed to create sdk.Executor - wallet (*wallet.Wallet) is nil") + } + + return &executor{ + Encoder: opts.Encoder, + Inspector: NewInspector(opts.Client), + wallet: opts.Wallet, + amount: opts.Amount, + }, nil +} + +func (e *executor) ExecuteOperation( + ctx context.Context, + metadata types.ChainMetadata, + nonce uint32, + proof []common.Hash, + op types.Operation, +) (types.TransactionResult, error) { + oe, ok := e.Encoder.(OperationEncoder[mcms.Op]) + if !ok { + return types.TransactionResult{}, errors.New("failed to assert OperationEncoder") + } + + bindOp, err := oe.ToOperation(nonce, metadata, op) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to convert to operation: %w", err) + } + + // Encode proofs + pe, ok := e.Encoder.(ProofEncoder[mcms.Proof]) + if !ok { + return types.TransactionResult{}, errors.New("failed to assert ProofEncoder") + } + + bindProof, err := pe.ToProof(proof) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to encode proof: %w", err) + } + + qID, err := tvm.RandomQueryID() + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to generate random query ID: %w", err) + } + + body, err := tlb.ToCell(mcms.Execute{ + QueryID: qID, + + Op: bindOp, + Proof: bindProof, + }) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to encode ExecuteBatch body: %w", err) + } + + // Map to Ton Address type + dstAddr, err := address.ParseAddr(metadata.MCMAddress) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("invalid mcms address: %w", err) + } + + skipSend := false // TODO: expose via executor options + + return SendTx(ctx, TxOpts{ + Wallet: e.wallet, + DstAddr: dstAddr, + Amount: e.amount, + Body: body, + SkipSend: skipSend, + }) +} + +func (e *executor) SetRoot( + ctx context.Context, + metadata types.ChainMetadata, + proof []common.Hash, + root [32]byte, + validUntil uint32, + sortedSignatures []types.Signature, +) (types.TransactionResult, error) { + rme, ok := e.Encoder.(RootMetadataEncoder[mcms.RootMetadata]) + if !ok { + return types.TransactionResult{}, errors.New("failed to assert RootMetadataEncoder") + } + + rm, err := rme.ToRootMetadata(metadata) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to convert to root metadata: %w", err) + } + + // Map to Ton Address type + dstAddr, err := address.ParseAddr(metadata.MCMAddress) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("invalid mcms address: %w", err) + } + + // Encode proofs + pe, ok := e.Encoder.(ProofEncoder[mcms.Proof]) + if !ok { + return types.TransactionResult{}, errors.New("failed to assert ProofEncoder") + } + + bindProof, err := pe.ToProof(proof) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to encode proof: %w", err) + } + + // Encode signatures + se, ok := e.Encoder.(SignaturesEncoder[mcms.Signature]) + if !ok { + return types.TransactionResult{}, errors.New("failed to assert SignatureEncoder") + } + + bindSignatures, err := se.ToSignatures(sortedSignatures, root) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to encode signatures: %w", err) + } + + qID, err := tvm.RandomQueryID() + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to generate random query ID: %w", err) + } + + body, err := tlb.ToCell(mcms.SetRoot{ + QueryID: qID, + + Root: tlbe.NewUint256(new(big.Int).SetBytes(root[:])), + ValidUntil: validUntil, + Metadata: rm, + + MetadataProof: bindProof, + Signatures: bindSignatures, + }) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to encode ExecuteBatch body: %w", err) + } + + skipSend := false // TODO: expose via executor options + + return SendTx(ctx, TxOpts{ + Wallet: e.wallet, + DstAddr: dstAddr, + Amount: e.amount, + Body: body, + SkipSend: skipSend, + }) +} diff --git a/sdk/ton/executor_test.go b/sdk/ton/executor_test.go new file mode 100644 index 000000000..221c92889 --- /dev/null +++ b/sdk/ton/executor_test.go @@ -0,0 +1,425 @@ +package ton_test + +import ( + "context" + "encoding/json" + "errors" + "math/big" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + "github.com/smartcontractkit/mcms/internal/testutils/chaintest" + "github.com/smartcontractkit/mcms/types" + + mcmston "github.com/smartcontractkit/mcms/sdk/ton" + + ton_mocks "github.com/smartcontractkit/mcms/sdk/ton/mocks" +) + +func TestExecutor_NewExecutor(t *testing.T) { + t.Parallel() + + amount := tlb.MustFromTON("0.1") + chainID := chaintest.Chain7TONID + + tests := []struct { + name string + mutate func(opts mcmston.ExecutorOpts) mcmston.ExecutorOpts + wantErr string + }{ + { + name: "success", + mutate: func(opts mcmston.ExecutorOpts) mcmston.ExecutorOpts { + return opts + }, + wantErr: "", + }, + { + name: "nil encoder", + mutate: func(opts mcmston.ExecutorOpts) mcmston.ExecutorOpts { + opts.Encoder = nil + + return opts + }, + wantErr: "failed to create sdk.Executor - encoder (sdk.Encoder) is nil", + }, + { + name: "nil client", + mutate: func(opts mcmston.ExecutorOpts) mcmston.ExecutorOpts { + opts.Client = nil + + return opts + }, + wantErr: "failed to create sdk.Executor - client (ton.APIClientWrapped) is nil", + }, + { + name: "nil wallet", + mutate: func(opts mcmston.ExecutorOpts) mcmston.ExecutorOpts { + opts.Wallet = nil + + return opts + }, + wantErr: "failed to create sdk.Executor - wallet (*wallet.Wallet) is nil", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + _api := ton_mocks.NewTonAPI(t) + walletOperator := must(tvm.NewRandomV5R1TestWallet(_api, chainID)) + var client ton.APIClientWrapped = ton_mocks.NewAPIClientWrapped(t) + var encoder = mcmston.NewEncoder(chaintest.Chain7Selector, 0, false) + + opts := tt.mutate(mcmston.ExecutorOpts{ + Encoder: encoder, + Client: client, + Wallet: walletOperator, + Amount: amount, + }) + + exec, err := mcmston.NewExecutor(opts) + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + require.Nil(t, exec) + + return + } + + require.NoError(t, err) + require.NotNil(t, exec) + }) + } +} + +func TestExecutor_ExecuteOperation(t *testing.T) { + t.Parallel() + + ctx := context.Background() + tests := []struct { + name string + encoder *mcmston.Encoder + metadata types.ChainMetadata + nonce uint32 + proof []common.Hash + op types.Operation + mockSetup func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) + wantTxHash string + wantErrNew error + wantErr error + }{ + { + name: "success", + encoder: &mcmston.Encoder{ + ChainSelector: chaintest.Chain7Selector, + }, + metadata: types.ChainMetadata{ + MCMAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + }, + nonce: 1, + op: types.Operation{ + ChainSelector: chaintest.Chain7Selector, + Transaction: types.Transaction{ + To: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + Data: cell.BeginCell().MustStoreBinarySnake([]byte{1, 2, 3}).EndCell().ToBOC(), + AdditionalFields: json.RawMessage(`{"value": 0}`)}, + }, + mockSetup: func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) { + // Mock CurrentMasterchainInfo + api.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + // Mock WaitForBlock + client.EXPECT().GetAccount(mock.Anything, mock.Anything, mock.Anything). + Return(&tlb.Account{}, nil) + + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(ton.NewExecutionResult([]any{big.NewInt(5)}), nil) + + api.EXPECT().WaitForBlock(mock.Anything). + Return(client) + + // Mock SendTransaction to return an error + api.EXPECT().SendExternalMessageWaitTransaction(mock.Anything, mock.Anything). + Return(&tlb.Transaction{Hash: []byte{1, 2, 3, 4, 14}}, &ton.BlockIDExt{}, []byte{}, nil) + }, + wantTxHash: "010203040e", + wantErr: nil, + }, + { + name: "failure in tx execution", + encoder: &mcmston.Encoder{ + ChainSelector: chaintest.Chain7Selector, + }, + metadata: types.ChainMetadata{ + MCMAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + }, + nonce: 1, + op: types.Operation{ + ChainSelector: chaintest.Chain7Selector, + Transaction: types.Transaction{ + To: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + Data: cell.BeginCell().MustStoreBinarySnake([]byte{1, 2, 3}).EndCell().ToBOC(), + AdditionalFields: json.RawMessage(`{"value": 0}`)}, + }, + mockSetup: func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) { + // Mock CurrentMasterchainInfo + api.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + // Mock WaitForBlock + client.EXPECT().GetAccount(mock.Anything, mock.Anything, mock.Anything). + Return(&tlb.Account{}, nil) + + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(ton.NewExecutionResult([]any{big.NewInt(5)}), nil) + + api.EXPECT().WaitForBlock(mock.Anything). + Return(client) + + // Mock SendTransaction to return an error + api.EXPECT().SendExternalMessageWaitTransaction(mock.Anything, mock.Anything). + Return(&tlb.Transaction{Hash: []byte{1, 2, 3, 4, 14}}, &ton.BlockIDExt{}, []byte{}, errors.New("error during tx send")) + }, + wantTxHash: "", + wantErr: errors.New("failed to send transaction: error during tx send"), + }, + { + name: "failure - nil encoder", + encoder: nil, + mockSetup: func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) {}, + wantTxHash: "", + wantErrNew: errors.New("failed to create sdk.Executor - encoder (sdk.Encoder) is nil"), + }, + { + name: "failure in operation conversion due to invalid chain ID", + encoder: &mcmston.Encoder{ + ChainSelector: types.ChainSelector(1), + }, + op: types.Operation{ + ChainSelector: types.ChainSelector(1), + Transaction: types.Transaction{ + To: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + Data: cell.BeginCell().MustStoreBinarySnake([]byte{1, 2, 3}).EndCell().ToBOC(), + AdditionalFields: json.RawMessage(`{"value": 0}`)}, + }, + mockSetup: func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) {}, + wantTxHash: "", + wantErr: errors.New("failed to convert to operation: invalid chain ID: 1"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + // Initialize the mock + chainID := chaintest.Chain7TONID + _api := ton_mocks.NewTonAPI(t) + walletOperator := must(tvm.NewRandomV5R1TestWallet(_api, chainID)) + + client := ton_mocks.NewAPIClientWrapped(t) + + if tt.mockSetup != nil { + tt.mockSetup(_api, client) + } + + executor, err := mcmston.NewExecutor(mcmston.ExecutorOpts{ + Encoder: tt.encoder, + Client: client, + Wallet: walletOperator, + Amount: tlb.MustFromTON("0.1"), + }) + if tt.wantErrNew != nil { + require.EqualError(t, err, tt.wantErrNew.Error()) + return + } + require.NoError(t, err) + + tx, err := executor.ExecuteOperation(ctx, tt.metadata, tt.nonce, tt.proof, tt.op) + + if tt.wantErr != nil { + require.EqualError(t, err, tt.wantErr.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tt.wantTxHash, tx.Hash) + } + }) + } +} + +func TestExecutor_SetRoot(t *testing.T) { + t.Parallel() + + ctx := context.Background() + tests := []struct { + name string + encoder *mcmston.Encoder + metadata types.ChainMetadata + proof []common.Hash + root [32]byte + validUntil uint32 + sortedSignatures []types.Signature + mockSetup func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) + wantTxHash string + wantErrNew error + wantErr error + }{ + { + name: "success", + encoder: &mcmston.Encoder{ + ChainSelector: chaintest.Chain7Selector, + }, + metadata: types.ChainMetadata{ + MCMAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + }, + root: [32]byte{1, 2, 3}, + validUntil: 4130013354, + sortedSignatures: []types.Signature{ + makeTestSignature("0xabcdef1234567890"), + makeTestSignature("0xabcdef1234567890"), + }, + mockSetup: func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) { + // Mock CurrentMasterchainInfo + api.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + // Mock WaitForBlock + client.EXPECT().GetAccount(mock.Anything, mock.Anything, mock.Anything). + Return(&tlb.Account{}, nil) + + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(ton.NewExecutionResult([]any{big.NewInt(5)}), nil) + + api.EXPECT().WaitForBlock(mock.Anything). + Return(client) + + // Mock SendTransaction to return an error + api.EXPECT().SendExternalMessageWaitTransaction(mock.Anything, mock.Anything). + Return(&tlb.Transaction{Hash: []byte{1, 2, 3, 4, 14}}, &ton.BlockIDExt{}, []byte{}, nil) + }, + wantTxHash: "010203040e", + wantErr: nil, + }, + { + name: "failure in tx send", + encoder: &mcmston.Encoder{ + ChainSelector: chaintest.Chain7Selector, + }, + metadata: types.ChainMetadata{ + MCMAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + }, + root: [32]byte{1, 2, 3}, + validUntil: 4130013354, + sortedSignatures: []types.Signature{ // TODO: "failed to encode signatures: failed to recover public key: recovery failed" + makeTestSignature("0xabcdef1234567890"), + makeTestSignature("0xabcdef1234567890"), + }, + mockSetup: func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) { + // Mock CurrentMasterchainInfo + api.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + // Mock WaitForBlock + client.EXPECT().GetAccount(mock.Anything, mock.Anything, mock.Anything). + Return(&tlb.Account{}, nil) + + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(ton.NewExecutionResult([]any{big.NewInt(5)}), nil) + + api.EXPECT().WaitForBlock(mock.Anything). + Return(client) + + // Mock SendTransaction to return an error + api.EXPECT().SendExternalMessageWaitTransaction(mock.Anything, mock.Anything). + Return(&tlb.Transaction{Hash: []byte{1, 2, 3, 4, 14}}, &ton.BlockIDExt{}, []byte{}, errors.New("error during tx send")) + }, + wantTxHash: "", + wantErr: errors.New("failed to send transaction: error during tx send"), + }, + { + name: "failure - nil encoder", + encoder: nil, + mockSetup: func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) {}, + wantTxHash: "", + wantErrNew: errors.New("failed to create sdk.Executor - encoder (sdk.Encoder) is nil"), + }, + { + name: "failure in operation conversion due to invalid chain ID", + encoder: &mcmston.Encoder{ + ChainSelector: types.ChainSelector(1), + }, + mockSetup: func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) {}, + wantTxHash: "", + wantErr: errors.New("failed to convert to root metadata: invalid chain ID: 1"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + // Initialize the mock + chainID := chaintest.Chain7TONID + _api := ton_mocks.NewTonAPI(t) + walletOperator := must(tvm.NewRandomV5R1TestWallet(_api, chainID)) + + client := ton_mocks.NewAPIClientWrapped(t) + + if tt.mockSetup != nil { + tt.mockSetup(_api, client) + } + + executor, err := mcmston.NewExecutor(mcmston.ExecutorOpts{ + Encoder: tt.encoder, + Client: client, + Wallet: walletOperator, + Amount: tlb.MustFromTON("0.1"), + }) + if tt.wantErrNew != nil { + require.EqualError(t, err, tt.wantErrNew.Error()) + return + } + require.NoError(t, err) + + tx, err := executor.SetRoot(ctx, tt.metadata, + tt.proof, + tt.root, + tt.validUntil, + tt.sortedSignatures) + + require.Equal(t, tt.wantTxHash, tx.Hash) + if tt.wantErr != nil { + require.EqualError(t, err, tt.wantErr.Error()) + } else { + require.NoError(t, err) + } + }) + } +} + +func makeTestSignature(hexStr string) types.Signature { + // Private key to use for signing + pk, _ := crypto.GenerateKey() + + // Hash to sign + hash := common.HexToHash(hexStr) + sigBytes, _ := crypto.Sign(hash.Bytes(), pk) + + // Signature object for the hash + sig, _ := types.NewSignatureFromBytes(sigBytes) + + return sig +} diff --git a/sdk/ton/inspector.go b/sdk/ton/inspector.go new file mode 100644 index 000000000..f4a1550ec --- /dev/null +++ b/sdk/ton/inspector.go @@ -0,0 +1,104 @@ +package ton + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/ton" + + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +var _ sdk.Inspector = (*Inspector)(nil) + +// Inspector is an interface for inspecting on chain state of MCMS contracts. +type Inspector struct { + client ton.APIClientWrapped + + configTransformer ConfigTransformer +} + +// NewInspector creates a new Inspector for TON chains +func NewInspector(client ton.APIClientWrapped) sdk.Inspector { + return &Inspector{ + client: client, + configTransformer: NewConfigTransformer(), + } +} + +// ParseAddrGetBlock parses the given address string into a TON address and retrieves the current masterchain block info. +func ParseAddrGetBlock(ctx context.Context, client ton.APIClientWrapped, _address string) (*address.Address, *ton.BlockIDExt, error) { + // Map to Ton Address type (mcms.address) + addr, err := address.ParseAddr(_address) + if err != nil { + return nil, &ton.BlockIDExt{}, fmt.Errorf("invalid address: %w", err) + } + + block, err := client.CurrentMasterchainInfo(ctx) + if err != nil { + return nil, &ton.BlockIDExt{}, fmt.Errorf("failed to get current masterchain info: %w", err) + } + + return addr, block, nil +} + +func (i Inspector) GetConfig(ctx context.Context, _address string) (*types.Config, error) { + addr, block, err := ParseAddrGetBlock(ctx, i.client, _address) + if err != nil { + return nil, err + } + + _config, err := tvm.CallGetter(ctx, i.client, block, addr, mcms.GetConfig) + if err != nil { + return nil, err + } + + return i.configTransformer.ToConfig(_config) +} + +func (i Inspector) GetOpCount(ctx context.Context, _address string) (uint64, error) { + addr, block, err := ParseAddrGetBlock(ctx, i.client, _address) + if err != nil { + return 0, err + } + + return tvm.CallGetter(ctx, i.client, block, addr, mcms.GetOpCount) +} + +func (i Inspector) GetRoot(ctx context.Context, _address string) (common.Hash, uint32, error) { + addr, block, err := ParseAddrGetBlock(ctx, i.client, _address) + if err != nil { + return [32]byte{}, 0, err + } + + r, err := tvm.CallGetter(ctx, i.client, block, addr, mcms.GetRoot) + if err != nil { + return [32]byte{}, 0, err + } + + return common.BigToHash(r.Root), r.ValidUntil, nil +} + +func (i Inspector) GetRootMetadata(ctx context.Context, _address string) (types.ChainMetadata, error) { + addr, block, err := ParseAddrGetBlock(ctx, i.client, _address) + if err != nil { + return types.ChainMetadata{}, err + } + + rm, err := tvm.CallGetter(ctx, i.client, block, addr, mcms.GetRootMetadata) + if err != nil { + return types.ChainMetadata{}, err + } + + return types.ChainMetadata{ + StartingOpCount: rm.PreOpCount, + MCMAddress: _address, + }, nil +} diff --git a/sdk/ton/inspector_test.go b/sdk/ton/inspector_test.go new file mode 100644 index 000000000..a115d3acb --- /dev/null +++ b/sdk/ton/inspector_test.go @@ -0,0 +1,386 @@ +package ton_test + +import ( + "context" + "errors" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/mcms" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" + + "github.com/smartcontractkit/mcms/internal/testutils" + "github.com/smartcontractkit/mcms/types" + + mcmston "github.com/smartcontractkit/mcms/sdk/ton" + ton_mocks "github.com/smartcontractkit/mcms/sdk/ton/mocks" +) + +func TestInspector_GetConfig(t *testing.T) { + t.Parallel() + + signers := testutils.MakeNewECDSASigners(8) + + ctx := context.Background() + tests := []struct { + name string + address string + mockResult mcms.Config + mockError error + want *types.Config + wantErr error + }{ + { + name: "getConfig call success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockResult: mcms.Config{ + Signers: must(tlbe.NewDictFromSlice[uint8]([]mcms.Signer{ + {Address: AsUint160Addr(signers[0]), Index: 0, Group: 0}, + {Address: AsUint160Addr(signers[1]), Index: 1, Group: 0}, + {Address: AsUint160Addr(signers[2]), Index: 2, Group: 0}, + {Address: AsUint160Addr(signers[3]), Index: 0, Group: 1}, + {Address: AsUint160Addr(signers[4]), Index: 1, Group: 1}, + {Address: AsUint160Addr(signers[5]), Index: 2, Group: 1}, + })), + GroupQuorums: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 3, + 2, + })), // Valid configuration + GroupParents: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 0, + 0, + })), + }, + want: &types.Config{ + Quorum: 3, + Signers: []common.Address{ + signers[0].Address(), + signers[1].Address(), + signers[2].Address(), + }, + GroupSigners: []types.Config{ + { + Quorum: 2, + Signers: []common.Address{ + signers[3].Address(), + signers[4].Address(), + signers[5].Address(), + }, + GroupSigners: []types.Config{}, + }, + }, + }, + }, + { + name: "CallContract error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockError: errors.New("call to contract failed"), + want: nil, + wantErr: errors.New("tvm: failed to run get method \"getConfig\": call to contract failed"), + }, + { + name: "Empty Signers list", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockResult: mcms.Config{ + Signers: must(tlbe.NewDictFromSlice[uint8]([]mcms.Signer{})), + GroupQuorums: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 3, + 2, + })), + GroupParents: must(tlbe.NewDictFromSlice[uint8]([]uint8{ + 0, + 0, + })), + }, + want: nil, + wantErr: errors.New("invalid MCMS config: Quorum must be less than or equal to the number of signers and groups"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + // Create a new mock client and inspector for each test case + client := ton_mocks.NewAPIClientWrapped(t) + + // Mock the contract call based on the test case + // Mock CurrentMasterchainInfo + client.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + if tt.mockError == nil { + // Encode the expected return value for a successful call + r := ton.NewExecutionResult([]any{ + must(tt.mockResult.Signers.AsDictionary()).AsCell(), + must(tt.mockResult.GroupQuorums.AsDictionary()).AsCell(), + must(tt.mockResult.GroupParents.AsDictionary()).AsCell(), + }) + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(r, nil).Once() + } else { + // If there's an error, mock it on the first CallContract call + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(nil, tt.mockError).Once() + } + + // Instantiate Inspector with the mock client + inspector := mcmston.NewInspector(client) + + // Call GetConfig and capture the got + got, err := inspector.GetConfig(ctx, tt.address) + + // Assertions for want error or successful got + if tt.wantErr != nil { + require.Error(t, err) + require.EqualError(t, err, tt.wantErr.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got) + } + + // Verify CallContract was called as want + client.AssertExpectations(t) + }) + } +} + +func TestInspector_GetOpCount(t *testing.T) { + t.Parallel() + + ctx := context.Background() + tests := []struct { + name string + address string + mockResult *big.Int + mockError error + want uint64 + wantErr error + }{ + { + name: "GetOpCount success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockResult: big.NewInt(42), // Arbitrary successful op count + want: 42, + }, + { + name: "CallContract error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockError: errors.New("call to contract failed"), + want: 0, + wantErr: errors.New("tvm: failed to run get method \"getOpCount\": call to contract failed"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + // Create a new mock client and inspector for each test case + client := ton_mocks.NewAPIClientWrapped(t) + + // Mock the contract call based on the test case + // Mock CurrentMasterchainInfo + client.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + if tt.mockError == nil { + // Encode the expected return value for a successful call + r := ton.NewExecutionResult([]any{tt.mockResult}) + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(r, nil).Once() + } else { + // If there's an error, mock it on the first CallContract call + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(nil, tt.mockError).Once() + } + + // Instantiate Inspector with the mock client + inspector := mcmston.NewInspector(client) + + // Call GetOpCount and capture the got + got, err := inspector.GetOpCount(ctx, tt.address) + + // Assertions for want error or successful got + if tt.wantErr != nil { + require.Error(t, err) + require.EqualError(t, err, tt.wantErr.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got) + } + + // Verify CallContract was called as want + client.AssertExpectations(t) + }) + } +} + +func TestInspector_GetRoot(t *testing.T) { + t.Parallel() + + ctx := context.Background() + tests := []struct { + name string + address string + mockResult []*big.Int + mockError error + wantRoot common.Hash + wantValidUntil uint32 + wantErr error + }{ + { + name: "GetRoot success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockResult: []*big.Int{ + new(big.Int).SetBytes(common.HexToHash("0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef").Bytes()), + big.NewInt(1234567890), + }, + wantRoot: common.HexToHash("0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef"), + wantValidUntil: 1234567890, + }, + { + name: "CallContract error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockError: errors.New("call to contract failed"), + wantErr: errors.New("tvm: failed to run get method \"getRoot\": call to contract failed"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + // Create a new mock client and inspector for each test case + client := ton_mocks.NewAPIClientWrapped(t) + + // Mock the contract call based on the test case + // Mock CurrentMasterchainInfo + client.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + if tt.mockError == nil { + // Encode the expected return value for a successful call + r := ton.NewExecutionResult([]any{tt.mockResult[0], tt.mockResult[1]}) + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(r, nil).Once() + } else { + // If there's an error, mock it on the first CallContract call + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(nil, tt.mockError).Once() + } + + // Instantiate Inspector with the mock client + inspector := mcmston.NewInspector(client) + + // Call GetRoot and capture the result + got, validUntil, err := inspector.GetRoot(ctx, tt.address) + + // Assertions for want error or successful result + if tt.wantErr != nil { + require.Error(t, err) + require.EqualError(t, err, tt.wantErr.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.wantRoot, got) + assert.Equal(t, tt.wantValidUntil, validUntil) + } + + // Verify CallContract was called as want + client.AssertExpectations(t) + }) + } +} + +func TestInspector_GetRootMetadata(t *testing.T) { + t.Parallel() + + ctx := context.Background() + tests := []struct { + name string + address string + mockResult mcms.RootMetadata + mockError error + want types.ChainMetadata + wantErr error + }{ + { + name: "GetRootMetadata success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockResult: mcms.RootMetadata{ + ChainID: big.NewInt(1), + MultiSig: address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8"), + PreOpCount: 123, + PostOpCount: 456, + OverridePreviousRoot: false, + }, + want: types.ChainMetadata{ + StartingOpCount: 123, + MCMAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + }, + }, + { + name: "CallContract error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockError: errors.New("call to contract failed"), + wantErr: errors.New("tvm: failed to run get method \"getRootMetadata\": call to contract failed"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + // Create a new mock client and inspector for each test case + client := ton_mocks.NewAPIClientWrapped(t) + + // Mock the contract call based on the test case + // Mock CurrentMasterchainInfo + client.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + if tt.mockError == nil { + r := ton.NewExecutionResult([]any{ + tt.mockResult.ChainID, + cell.BeginCell().MustStoreAddr(tt.mockResult.MultiSig).ToSlice(), + new(big.Int).SetUint64(tt.mockResult.PreOpCount), + new(big.Int).SetUint64(tt.mockResult.PostOpCount), + big.NewInt(0), // OverridePreviousRoot as int (ignored) + }) + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(r, nil).Once() + } else { + // If there's an error, mock it on the first CallContract call + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(nil, tt.mockError).Once() + } + + // Instantiate Inspector with the mock client + inspector := mcmston.NewInspector(client) + + // Call GetRootMetadata and capture the got + got, err := inspector.GetRootMetadata(ctx, tt.address) + + // Assertions for want error or successful got + if tt.wantErr != nil { + require.Error(t, err) + require.EqualError(t, err, tt.wantErr.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got) + } + + // Verify CallContract was called as want + client.AssertExpectations(t) + }) + } +} diff --git a/sdk/ton/mocks/api.go b/sdk/ton/mocks/api.go new file mode 100644 index 000000000..f37411f17 --- /dev/null +++ b/sdk/ton/mocks/api.go @@ -0,0 +1,1570 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mock_ton + +import ( + address "github.com/xssnick/tonutils-go/address" + cell "github.com/xssnick/tonutils-go/tvm/cell" + + context "context" + + liteclient "github.com/xssnick/tonutils-go/liteclient" + + mock "github.com/stretchr/testify/mock" + + time "time" + + tlb "github.com/xssnick/tonutils-go/tlb" + + ton "github.com/xssnick/tonutils-go/ton" +) + +// APIClientWrapped is an autogenerated mock type for the APIClientWrapped type +type APIClientWrapped struct { + mock.Mock +} + +type APIClientWrapped_Expecter struct { + mock *mock.Mock +} + +func (_m *APIClientWrapped) EXPECT() *APIClientWrapped_Expecter { + return &APIClientWrapped_Expecter{mock: &_m.Mock} +} + +// Client provides a mock function with no fields +func (_m *APIClientWrapped) Client() ton.LiteClient { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Client") + } + + var r0 ton.LiteClient + if rf, ok := ret.Get(0).(func() ton.LiteClient); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(ton.LiteClient) + } + } + + return r0 +} + +// APIClientWrapped_Client_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Client' +type APIClientWrapped_Client_Call struct { + *mock.Call +} + +// Client is a helper method to define mock.On call +func (_e *APIClientWrapped_Expecter) Client() *APIClientWrapped_Client_Call { + return &APIClientWrapped_Client_Call{Call: _e.mock.On("Client")} +} + +func (_c *APIClientWrapped_Client_Call) Run(run func()) *APIClientWrapped_Client_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *APIClientWrapped_Client_Call) Return(_a0 ton.LiteClient) *APIClientWrapped_Client_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *APIClientWrapped_Client_Call) RunAndReturn(run func() ton.LiteClient) *APIClientWrapped_Client_Call { + _c.Call.Return(run) + return _c +} + +// CurrentMasterchainInfo provides a mock function with given fields: ctx +func (_m *APIClientWrapped) CurrentMasterchainInfo(ctx context.Context) (*tlb.BlockInfo, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for CurrentMasterchainInfo") + } + + var r0 *tlb.BlockInfo + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*tlb.BlockInfo, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *tlb.BlockInfo); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.BlockInfo) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_CurrentMasterchainInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CurrentMasterchainInfo' +type APIClientWrapped_CurrentMasterchainInfo_Call struct { + *mock.Call +} + +// CurrentMasterchainInfo is a helper method to define mock.On call +// - ctx context.Context +func (_e *APIClientWrapped_Expecter) CurrentMasterchainInfo(ctx interface{}) *APIClientWrapped_CurrentMasterchainInfo_Call { + return &APIClientWrapped_CurrentMasterchainInfo_Call{Call: _e.mock.On("CurrentMasterchainInfo", ctx)} +} + +func (_c *APIClientWrapped_CurrentMasterchainInfo_Call) Run(run func(ctx context.Context)) *APIClientWrapped_CurrentMasterchainInfo_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *APIClientWrapped_CurrentMasterchainInfo_Call) Return(_a0 *tlb.BlockInfo, err error) *APIClientWrapped_CurrentMasterchainInfo_Call { + _c.Call.Return(_a0, err) + return _c +} + +func (_c *APIClientWrapped_CurrentMasterchainInfo_Call) RunAndReturn(run func(context.Context) (*tlb.BlockInfo, error)) *APIClientWrapped_CurrentMasterchainInfo_Call { + _c.Call.Return(run) + return _c +} + +// FindLastTransactionByInMsgHash provides a mock function with given fields: ctx, addr, msgHash, maxTxNumToScan +func (_m *APIClientWrapped) FindLastTransactionByInMsgHash(ctx context.Context, addr *address.Address, msgHash []byte, maxTxNumToScan ...int) (*tlb.Transaction, error) { + _va := make([]interface{}, len(maxTxNumToScan)) + for _i := range maxTxNumToScan { + _va[_i] = maxTxNumToScan[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, addr, msgHash) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for FindLastTransactionByInMsgHash") + } + + var r0 *tlb.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *address.Address, []byte, ...int) (*tlb.Transaction, error)); ok { + return rf(ctx, addr, msgHash, maxTxNumToScan...) + } + if rf, ok := ret.Get(0).(func(context.Context, *address.Address, []byte, ...int) *tlb.Transaction); ok { + r0 = rf(ctx, addr, msgHash, maxTxNumToScan...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *address.Address, []byte, ...int) error); ok { + r1 = rf(ctx, addr, msgHash, maxTxNumToScan...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_FindLastTransactionByInMsgHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindLastTransactionByInMsgHash' +type APIClientWrapped_FindLastTransactionByInMsgHash_Call struct { + *mock.Call +} + +// FindLastTransactionByInMsgHash is a helper method to define mock.On call +// - ctx context.Context +// - addr *address.Address +// - msgHash []byte +// - maxTxNumToScan ...int +func (_e *APIClientWrapped_Expecter) FindLastTransactionByInMsgHash(ctx interface{}, addr interface{}, msgHash interface{}, maxTxNumToScan ...interface{}) *APIClientWrapped_FindLastTransactionByInMsgHash_Call { + return &APIClientWrapped_FindLastTransactionByInMsgHash_Call{Call: _e.mock.On("FindLastTransactionByInMsgHash", + append([]interface{}{ctx, addr, msgHash}, maxTxNumToScan...)...)} +} + +func (_c *APIClientWrapped_FindLastTransactionByInMsgHash_Call) Run(run func(ctx context.Context, addr *address.Address, msgHash []byte, maxTxNumToScan ...int)) *APIClientWrapped_FindLastTransactionByInMsgHash_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]int, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(int) + } + } + run(args[0].(context.Context), args[1].(*address.Address), args[2].([]byte), variadicArgs...) + }) + return _c +} + +func (_c *APIClientWrapped_FindLastTransactionByInMsgHash_Call) Return(_a0 *tlb.Transaction, _a1 error) *APIClientWrapped_FindLastTransactionByInMsgHash_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_FindLastTransactionByInMsgHash_Call) RunAndReturn(run func(context.Context, *address.Address, []byte, ...int) (*tlb.Transaction, error)) *APIClientWrapped_FindLastTransactionByInMsgHash_Call { + _c.Call.Return(run) + return _c +} + +// FindLastTransactionByOutMsgHash provides a mock function with given fields: ctx, addr, msgHash, maxTxNumToScan +func (_m *APIClientWrapped) FindLastTransactionByOutMsgHash(ctx context.Context, addr *address.Address, msgHash []byte, maxTxNumToScan ...int) (*tlb.Transaction, error) { + _va := make([]interface{}, len(maxTxNumToScan)) + for _i := range maxTxNumToScan { + _va[_i] = maxTxNumToScan[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, addr, msgHash) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for FindLastTransactionByOutMsgHash") + } + + var r0 *tlb.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *address.Address, []byte, ...int) (*tlb.Transaction, error)); ok { + return rf(ctx, addr, msgHash, maxTxNumToScan...) + } + if rf, ok := ret.Get(0).(func(context.Context, *address.Address, []byte, ...int) *tlb.Transaction); ok { + r0 = rf(ctx, addr, msgHash, maxTxNumToScan...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *address.Address, []byte, ...int) error); ok { + r1 = rf(ctx, addr, msgHash, maxTxNumToScan...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_FindLastTransactionByOutMsgHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindLastTransactionByOutMsgHash' +type APIClientWrapped_FindLastTransactionByOutMsgHash_Call struct { + *mock.Call +} + +// FindLastTransactionByOutMsgHash is a helper method to define mock.On call +// - ctx context.Context +// - addr *address.Address +// - msgHash []byte +// - maxTxNumToScan ...int +func (_e *APIClientWrapped_Expecter) FindLastTransactionByOutMsgHash(ctx interface{}, addr interface{}, msgHash interface{}, maxTxNumToScan ...interface{}) *APIClientWrapped_FindLastTransactionByOutMsgHash_Call { + return &APIClientWrapped_FindLastTransactionByOutMsgHash_Call{Call: _e.mock.On("FindLastTransactionByOutMsgHash", + append([]interface{}{ctx, addr, msgHash}, maxTxNumToScan...)...)} +} + +func (_c *APIClientWrapped_FindLastTransactionByOutMsgHash_Call) Run(run func(ctx context.Context, addr *address.Address, msgHash []byte, maxTxNumToScan ...int)) *APIClientWrapped_FindLastTransactionByOutMsgHash_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]int, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(int) + } + } + run(args[0].(context.Context), args[1].(*address.Address), args[2].([]byte), variadicArgs...) + }) + return _c +} + +func (_c *APIClientWrapped_FindLastTransactionByOutMsgHash_Call) Return(_a0 *tlb.Transaction, _a1 error) *APIClientWrapped_FindLastTransactionByOutMsgHash_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_FindLastTransactionByOutMsgHash_Call) RunAndReturn(run func(context.Context, *address.Address, []byte, ...int) (*tlb.Transaction, error)) *APIClientWrapped_FindLastTransactionByOutMsgHash_Call { + _c.Call.Return(run) + return _c +} + +// GetAccount provides a mock function with given fields: ctx, block, addr +func (_m *APIClientWrapped) GetAccount(ctx context.Context, block *tlb.BlockInfo, addr *address.Address) (*tlb.Account, error) { + ret := _m.Called(ctx, block, addr) + + if len(ret) == 0 { + panic("no return value specified for GetAccount") + } + + var r0 *tlb.Account + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, *address.Address) (*tlb.Account, error)); ok { + return rf(ctx, block, addr) + } + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, *address.Address) *tlb.Account); ok { + r0 = rf(ctx, block, addr) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.Account) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *tlb.BlockInfo, *address.Address) error); ok { + r1 = rf(ctx, block, addr) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_GetAccount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAccount' +type APIClientWrapped_GetAccount_Call struct { + *mock.Call +} + +// GetAccount is a helper method to define mock.On call +// - ctx context.Context +// - block *tlb.BlockInfo +// - addr *address.Address +func (_e *APIClientWrapped_Expecter) GetAccount(ctx interface{}, block interface{}, addr interface{}) *APIClientWrapped_GetAccount_Call { + return &APIClientWrapped_GetAccount_Call{Call: _e.mock.On("GetAccount", ctx, block, addr)} +} + +func (_c *APIClientWrapped_GetAccount_Call) Run(run func(ctx context.Context, block *tlb.BlockInfo, addr *address.Address)) *APIClientWrapped_GetAccount_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*tlb.BlockInfo), args[2].(*address.Address)) + }) + return _c +} + +func (_c *APIClientWrapped_GetAccount_Call) Return(_a0 *tlb.Account, _a1 error) *APIClientWrapped_GetAccount_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_GetAccount_Call) RunAndReturn(run func(context.Context, *tlb.BlockInfo, *address.Address) (*tlb.Account, error)) *APIClientWrapped_GetAccount_Call { + _c.Call.Return(run) + return _c +} + +// GetBlockData provides a mock function with given fields: ctx, block +func (_m *APIClientWrapped) GetBlockData(ctx context.Context, block *tlb.BlockInfo) (*tlb.Block, error) { + ret := _m.Called(ctx, block) + + if len(ret) == 0 { + panic("no return value specified for GetBlockData") + } + + var r0 *tlb.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo) (*tlb.Block, error)); ok { + return rf(ctx, block) + } + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo) *tlb.Block); ok { + r0 = rf(ctx, block) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *tlb.BlockInfo) error); ok { + r1 = rf(ctx, block) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_GetBlockData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBlockData' +type APIClientWrapped_GetBlockData_Call struct { + *mock.Call +} + +// GetBlockData is a helper method to define mock.On call +// - ctx context.Context +// - block *tlb.BlockInfo +func (_e *APIClientWrapped_Expecter) GetBlockData(ctx interface{}, block interface{}) *APIClientWrapped_GetBlockData_Call { + return &APIClientWrapped_GetBlockData_Call{Call: _e.mock.On("GetBlockData", ctx, block)} +} + +func (_c *APIClientWrapped_GetBlockData_Call) Run(run func(ctx context.Context, block *tlb.BlockInfo)) *APIClientWrapped_GetBlockData_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*tlb.BlockInfo)) + }) + return _c +} + +func (_c *APIClientWrapped_GetBlockData_Call) Return(_a0 *tlb.Block, _a1 error) *APIClientWrapped_GetBlockData_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_GetBlockData_Call) RunAndReturn(run func(context.Context, *tlb.BlockInfo) (*tlb.Block, error)) *APIClientWrapped_GetBlockData_Call { + _c.Call.Return(run) + return _c +} + +// GetBlockProof provides a mock function with given fields: ctx, known, target +func (_m *APIClientWrapped) GetBlockProof(ctx context.Context, known *tlb.BlockInfo, target *tlb.BlockInfo) (*ton.PartialBlockProof, error) { + ret := _m.Called(ctx, known, target) + + if len(ret) == 0 { + panic("no return value specified for GetBlockProof") + } + + var r0 *ton.PartialBlockProof + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, *tlb.BlockInfo) (*ton.PartialBlockProof, error)); ok { + return rf(ctx, known, target) + } + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, *tlb.BlockInfo) *ton.PartialBlockProof); ok { + r0 = rf(ctx, known, target) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ton.PartialBlockProof) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *tlb.BlockInfo, *tlb.BlockInfo) error); ok { + r1 = rf(ctx, known, target) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_GetBlockProof_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBlockProof' +type APIClientWrapped_GetBlockProof_Call struct { + *mock.Call +} + +// GetBlockProof is a helper method to define mock.On call +// - ctx context.Context +// - known *tlb.BlockInfo +// - target *tlb.BlockInfo +func (_e *APIClientWrapped_Expecter) GetBlockProof(ctx interface{}, known interface{}, target interface{}) *APIClientWrapped_GetBlockProof_Call { + return &APIClientWrapped_GetBlockProof_Call{Call: _e.mock.On("GetBlockProof", ctx, known, target)} +} + +func (_c *APIClientWrapped_GetBlockProof_Call) Run(run func(ctx context.Context, known *tlb.BlockInfo, target *tlb.BlockInfo)) *APIClientWrapped_GetBlockProof_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*tlb.BlockInfo), args[2].(*tlb.BlockInfo)) + }) + return _c +} + +func (_c *APIClientWrapped_GetBlockProof_Call) Return(_a0 *ton.PartialBlockProof, _a1 error) *APIClientWrapped_GetBlockProof_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_GetBlockProof_Call) RunAndReturn(run func(context.Context, *tlb.BlockInfo, *tlb.BlockInfo) (*ton.PartialBlockProof, error)) *APIClientWrapped_GetBlockProof_Call { + _c.Call.Return(run) + return _c +} + +// GetBlockShardsInfo provides a mock function with given fields: ctx, master +func (_m *APIClientWrapped) GetBlockShardsInfo(ctx context.Context, master *tlb.BlockInfo) ([]*tlb.BlockInfo, error) { + ret := _m.Called(ctx, master) + + if len(ret) == 0 { + panic("no return value specified for GetBlockShardsInfo") + } + + var r0 []*tlb.BlockInfo + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo) ([]*tlb.BlockInfo, error)); ok { + return rf(ctx, master) + } + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo) []*tlb.BlockInfo); ok { + r0 = rf(ctx, master) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*tlb.BlockInfo) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *tlb.BlockInfo) error); ok { + r1 = rf(ctx, master) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_GetBlockShardsInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBlockShardsInfo' +type APIClientWrapped_GetBlockShardsInfo_Call struct { + *mock.Call +} + +// GetBlockShardsInfo is a helper method to define mock.On call +// - ctx context.Context +// - master *tlb.BlockInfo +func (_e *APIClientWrapped_Expecter) GetBlockShardsInfo(ctx interface{}, master interface{}) *APIClientWrapped_GetBlockShardsInfo_Call { + return &APIClientWrapped_GetBlockShardsInfo_Call{Call: _e.mock.On("GetBlockShardsInfo", ctx, master)} +} + +func (_c *APIClientWrapped_GetBlockShardsInfo_Call) Run(run func(ctx context.Context, master *tlb.BlockInfo)) *APIClientWrapped_GetBlockShardsInfo_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*tlb.BlockInfo)) + }) + return _c +} + +func (_c *APIClientWrapped_GetBlockShardsInfo_Call) Return(_a0 []*tlb.BlockInfo, _a1 error) *APIClientWrapped_GetBlockShardsInfo_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_GetBlockShardsInfo_Call) RunAndReturn(run func(context.Context, *tlb.BlockInfo) ([]*tlb.BlockInfo, error)) *APIClientWrapped_GetBlockShardsInfo_Call { + _c.Call.Return(run) + return _c +} + +// GetBlockTransactionsV2 provides a mock function with given fields: ctx, block, count, after +func (_m *APIClientWrapped) GetBlockTransactionsV2(ctx context.Context, block *tlb.BlockInfo, count uint32, after ...*ton.TransactionID3) ([]ton.TransactionShortInfo, bool, error) { + _va := make([]interface{}, len(after)) + for _i := range after { + _va[_i] = after[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, block, count) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetBlockTransactionsV2") + } + + var r0 []ton.TransactionShortInfo + var r1 bool + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, uint32, ...*ton.TransactionID3) ([]ton.TransactionShortInfo, bool, error)); ok { + return rf(ctx, block, count, after...) + } + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, uint32, ...*ton.TransactionID3) []ton.TransactionShortInfo); ok { + r0 = rf(ctx, block, count, after...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]ton.TransactionShortInfo) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *tlb.BlockInfo, uint32, ...*ton.TransactionID3) bool); ok { + r1 = rf(ctx, block, count, after...) + } else { + r1 = ret.Get(1).(bool) + } + + if rf, ok := ret.Get(2).(func(context.Context, *tlb.BlockInfo, uint32, ...*ton.TransactionID3) error); ok { + r2 = rf(ctx, block, count, after...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// APIClientWrapped_GetBlockTransactionsV2_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBlockTransactionsV2' +type APIClientWrapped_GetBlockTransactionsV2_Call struct { + *mock.Call +} + +// GetBlockTransactionsV2 is a helper method to define mock.On call +// - ctx context.Context +// - block *tlb.BlockInfo +// - count uint32 +// - after ...*ton.TransactionID3 +func (_e *APIClientWrapped_Expecter) GetBlockTransactionsV2(ctx interface{}, block interface{}, count interface{}, after ...interface{}) *APIClientWrapped_GetBlockTransactionsV2_Call { + return &APIClientWrapped_GetBlockTransactionsV2_Call{Call: _e.mock.On("GetBlockTransactionsV2", + append([]interface{}{ctx, block, count}, after...)...)} +} + +func (_c *APIClientWrapped_GetBlockTransactionsV2_Call) Run(run func(ctx context.Context, block *tlb.BlockInfo, count uint32, after ...*ton.TransactionID3)) *APIClientWrapped_GetBlockTransactionsV2_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]*ton.TransactionID3, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(*ton.TransactionID3) + } + } + run(args[0].(context.Context), args[1].(*tlb.BlockInfo), args[2].(uint32), variadicArgs...) + }) + return _c +} + +func (_c *APIClientWrapped_GetBlockTransactionsV2_Call) Return(_a0 []ton.TransactionShortInfo, _a1 bool, _a2 error) *APIClientWrapped_GetBlockTransactionsV2_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *APIClientWrapped_GetBlockTransactionsV2_Call) RunAndReturn(run func(context.Context, *tlb.BlockInfo, uint32, ...*ton.TransactionID3) ([]ton.TransactionShortInfo, bool, error)) *APIClientWrapped_GetBlockTransactionsV2_Call { + _c.Call.Return(run) + return _c +} + +// GetBlockchainConfig provides a mock function with given fields: ctx, block, onlyParams +func (_m *APIClientWrapped) GetBlockchainConfig(ctx context.Context, block *tlb.BlockInfo, onlyParams ...int32) (*ton.BlockchainConfig, error) { + _va := make([]interface{}, len(onlyParams)) + for _i := range onlyParams { + _va[_i] = onlyParams[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, block) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetBlockchainConfig") + } + + var r0 *ton.BlockchainConfig + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, ...int32) (*ton.BlockchainConfig, error)); ok { + return rf(ctx, block, onlyParams...) + } + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, ...int32) *ton.BlockchainConfig); ok { + r0 = rf(ctx, block, onlyParams...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ton.BlockchainConfig) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *tlb.BlockInfo, ...int32) error); ok { + r1 = rf(ctx, block, onlyParams...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_GetBlockchainConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBlockchainConfig' +type APIClientWrapped_GetBlockchainConfig_Call struct { + *mock.Call +} + +// GetBlockchainConfig is a helper method to define mock.On call +// - ctx context.Context +// - block *tlb.BlockInfo +// - onlyParams ...int32 +func (_e *APIClientWrapped_Expecter) GetBlockchainConfig(ctx interface{}, block interface{}, onlyParams ...interface{}) *APIClientWrapped_GetBlockchainConfig_Call { + return &APIClientWrapped_GetBlockchainConfig_Call{Call: _e.mock.On("GetBlockchainConfig", + append([]interface{}{ctx, block}, onlyParams...)...)} +} + +func (_c *APIClientWrapped_GetBlockchainConfig_Call) Run(run func(ctx context.Context, block *tlb.BlockInfo, onlyParams ...int32)) *APIClientWrapped_GetBlockchainConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]int32, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(int32) + } + } + run(args[0].(context.Context), args[1].(*tlb.BlockInfo), variadicArgs...) + }) + return _c +} + +func (_c *APIClientWrapped_GetBlockchainConfig_Call) Return(_a0 *ton.BlockchainConfig, _a1 error) *APIClientWrapped_GetBlockchainConfig_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_GetBlockchainConfig_Call) RunAndReturn(run func(context.Context, *tlb.BlockInfo, ...int32) (*ton.BlockchainConfig, error)) *APIClientWrapped_GetBlockchainConfig_Call { + _c.Call.Return(run) + return _c +} + +// GetLibraries provides a mock function with given fields: ctx, list +func (_m *APIClientWrapped) GetLibraries(ctx context.Context, list ...[]byte) ([]*cell.Cell, error) { + _va := make([]interface{}, len(list)) + for _i := range list { + _va[_i] = list[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetLibraries") + } + + var r0 []*cell.Cell + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, ...[]byte) ([]*cell.Cell, error)); ok { + return rf(ctx, list...) + } + if rf, ok := ret.Get(0).(func(context.Context, ...[]byte) []*cell.Cell); ok { + r0 = rf(ctx, list...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*cell.Cell) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, ...[]byte) error); ok { + r1 = rf(ctx, list...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_GetLibraries_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLibraries' +type APIClientWrapped_GetLibraries_Call struct { + *mock.Call +} + +// GetLibraries is a helper method to define mock.On call +// - ctx context.Context +// - list ...[]byte +func (_e *APIClientWrapped_Expecter) GetLibraries(ctx interface{}, list ...interface{}) *APIClientWrapped_GetLibraries_Call { + return &APIClientWrapped_GetLibraries_Call{Call: _e.mock.On("GetLibraries", + append([]interface{}{ctx}, list...)...)} +} + +func (_c *APIClientWrapped_GetLibraries_Call) Run(run func(ctx context.Context, list ...[]byte)) *APIClientWrapped_GetLibraries_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([][]byte, len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.([]byte) + } + } + run(args[0].(context.Context), variadicArgs...) + }) + return _c +} + +func (_c *APIClientWrapped_GetLibraries_Call) Return(_a0 []*cell.Cell, _a1 error) *APIClientWrapped_GetLibraries_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_GetLibraries_Call) RunAndReturn(run func(context.Context, ...[]byte) ([]*cell.Cell, error)) *APIClientWrapped_GetLibraries_Call { + _c.Call.Return(run) + return _c +} + +// GetMasterchainInfo provides a mock function with given fields: ctx +func (_m *APIClientWrapped) GetMasterchainInfo(ctx context.Context) (*tlb.BlockInfo, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetMasterchainInfo") + } + + var r0 *tlb.BlockInfo + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*tlb.BlockInfo, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *tlb.BlockInfo); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.BlockInfo) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_GetMasterchainInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetMasterchainInfo' +type APIClientWrapped_GetMasterchainInfo_Call struct { + *mock.Call +} + +// GetMasterchainInfo is a helper method to define mock.On call +// - ctx context.Context +func (_e *APIClientWrapped_Expecter) GetMasterchainInfo(ctx interface{}) *APIClientWrapped_GetMasterchainInfo_Call { + return &APIClientWrapped_GetMasterchainInfo_Call{Call: _e.mock.On("GetMasterchainInfo", ctx)} +} + +func (_c *APIClientWrapped_GetMasterchainInfo_Call) Run(run func(ctx context.Context)) *APIClientWrapped_GetMasterchainInfo_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *APIClientWrapped_GetMasterchainInfo_Call) Return(_a0 *tlb.BlockInfo, _a1 error) *APIClientWrapped_GetMasterchainInfo_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_GetMasterchainInfo_Call) RunAndReturn(run func(context.Context) (*tlb.BlockInfo, error)) *APIClientWrapped_GetMasterchainInfo_Call { + _c.Call.Return(run) + return _c +} + +// GetTime provides a mock function with given fields: ctx +func (_m *APIClientWrapped) GetTime(ctx context.Context) (uint32, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetTime") + } + + var r0 uint32 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (uint32, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) uint32); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(uint32) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_GetTime_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTime' +type APIClientWrapped_GetTime_Call struct { + *mock.Call +} + +// GetTime is a helper method to define mock.On call +// - ctx context.Context +func (_e *APIClientWrapped_Expecter) GetTime(ctx interface{}) *APIClientWrapped_GetTime_Call { + return &APIClientWrapped_GetTime_Call{Call: _e.mock.On("GetTime", ctx)} +} + +func (_c *APIClientWrapped_GetTime_Call) Run(run func(ctx context.Context)) *APIClientWrapped_GetTime_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *APIClientWrapped_GetTime_Call) Return(_a0 uint32, _a1 error) *APIClientWrapped_GetTime_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_GetTime_Call) RunAndReturn(run func(context.Context) (uint32, error)) *APIClientWrapped_GetTime_Call { + _c.Call.Return(run) + return _c +} + +// GetTransaction provides a mock function with given fields: ctx, block, addr, lt +func (_m *APIClientWrapped) GetTransaction(ctx context.Context, block *tlb.BlockInfo, addr *address.Address, lt uint64) (*tlb.Transaction, error) { + ret := _m.Called(ctx, block, addr, lt) + + if len(ret) == 0 { + panic("no return value specified for GetTransaction") + } + + var r0 *tlb.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, *address.Address, uint64) (*tlb.Transaction, error)); ok { + return rf(ctx, block, addr, lt) + } + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, *address.Address, uint64) *tlb.Transaction); ok { + r0 = rf(ctx, block, addr, lt) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *tlb.BlockInfo, *address.Address, uint64) error); ok { + r1 = rf(ctx, block, addr, lt) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_GetTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransaction' +type APIClientWrapped_GetTransaction_Call struct { + *mock.Call +} + +// GetTransaction is a helper method to define mock.On call +// - ctx context.Context +// - block *tlb.BlockInfo +// - addr *address.Address +// - lt uint64 +func (_e *APIClientWrapped_Expecter) GetTransaction(ctx interface{}, block interface{}, addr interface{}, lt interface{}) *APIClientWrapped_GetTransaction_Call { + return &APIClientWrapped_GetTransaction_Call{Call: _e.mock.On("GetTransaction", ctx, block, addr, lt)} +} + +func (_c *APIClientWrapped_GetTransaction_Call) Run(run func(ctx context.Context, block *tlb.BlockInfo, addr *address.Address, lt uint64)) *APIClientWrapped_GetTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*tlb.BlockInfo), args[2].(*address.Address), args[3].(uint64)) + }) + return _c +} + +func (_c *APIClientWrapped_GetTransaction_Call) Return(_a0 *tlb.Transaction, _a1 error) *APIClientWrapped_GetTransaction_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_GetTransaction_Call) RunAndReturn(run func(context.Context, *tlb.BlockInfo, *address.Address, uint64) (*tlb.Transaction, error)) *APIClientWrapped_GetTransaction_Call { + _c.Call.Return(run) + return _c +} + +// ListTransactions provides a mock function with given fields: ctx, addr, num, lt, txHash +func (_m *APIClientWrapped) ListTransactions(ctx context.Context, addr *address.Address, num uint32, lt uint64, txHash []byte) ([]*tlb.Transaction, error) { + ret := _m.Called(ctx, addr, num, lt, txHash) + + if len(ret) == 0 { + panic("no return value specified for ListTransactions") + } + + var r0 []*tlb.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *address.Address, uint32, uint64, []byte) ([]*tlb.Transaction, error)); ok { + return rf(ctx, addr, num, lt, txHash) + } + if rf, ok := ret.Get(0).(func(context.Context, *address.Address, uint32, uint64, []byte) []*tlb.Transaction); ok { + r0 = rf(ctx, addr, num, lt, txHash) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*tlb.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *address.Address, uint32, uint64, []byte) error); ok { + r1 = rf(ctx, addr, num, lt, txHash) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_ListTransactions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListTransactions' +type APIClientWrapped_ListTransactions_Call struct { + *mock.Call +} + +// ListTransactions is a helper method to define mock.On call +// - ctx context.Context +// - addr *address.Address +// - num uint32 +// - lt uint64 +// - txHash []byte +func (_e *APIClientWrapped_Expecter) ListTransactions(ctx interface{}, addr interface{}, num interface{}, lt interface{}, txHash interface{}) *APIClientWrapped_ListTransactions_Call { + return &APIClientWrapped_ListTransactions_Call{Call: _e.mock.On("ListTransactions", ctx, addr, num, lt, txHash)} +} + +func (_c *APIClientWrapped_ListTransactions_Call) Run(run func(ctx context.Context, addr *address.Address, num uint32, lt uint64, txHash []byte)) *APIClientWrapped_ListTransactions_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*address.Address), args[2].(uint32), args[3].(uint64), args[4].([]byte)) + }) + return _c +} + +func (_c *APIClientWrapped_ListTransactions_Call) Return(_a0 []*tlb.Transaction, _a1 error) *APIClientWrapped_ListTransactions_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_ListTransactions_Call) RunAndReturn(run func(context.Context, *address.Address, uint32, uint64, []byte) ([]*tlb.Transaction, error)) *APIClientWrapped_ListTransactions_Call { + _c.Call.Return(run) + return _c +} + +// LookupBlock provides a mock function with given fields: ctx, workchain, shard, seqno +func (_m *APIClientWrapped) LookupBlock(ctx context.Context, workchain int32, shard int64, seqno uint32) (*tlb.BlockInfo, error) { + ret := _m.Called(ctx, workchain, shard, seqno) + + if len(ret) == 0 { + panic("no return value specified for LookupBlock") + } + + var r0 *tlb.BlockInfo + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int32, int64, uint32) (*tlb.BlockInfo, error)); ok { + return rf(ctx, workchain, shard, seqno) + } + if rf, ok := ret.Get(0).(func(context.Context, int32, int64, uint32) *tlb.BlockInfo); ok { + r0 = rf(ctx, workchain, shard, seqno) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.BlockInfo) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, int32, int64, uint32) error); ok { + r1 = rf(ctx, workchain, shard, seqno) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_LookupBlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LookupBlock' +type APIClientWrapped_LookupBlock_Call struct { + *mock.Call +} + +// LookupBlock is a helper method to define mock.On call +// - ctx context.Context +// - workchain int32 +// - shard int64 +// - seqno uint32 +func (_e *APIClientWrapped_Expecter) LookupBlock(ctx interface{}, workchain interface{}, shard interface{}, seqno interface{}) *APIClientWrapped_LookupBlock_Call { + return &APIClientWrapped_LookupBlock_Call{Call: _e.mock.On("LookupBlock", ctx, workchain, shard, seqno)} +} + +func (_c *APIClientWrapped_LookupBlock_Call) Run(run func(ctx context.Context, workchain int32, shard int64, seqno uint32)) *APIClientWrapped_LookupBlock_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int32), args[2].(int64), args[3].(uint32)) + }) + return _c +} + +func (_c *APIClientWrapped_LookupBlock_Call) Return(_a0 *tlb.BlockInfo, _a1 error) *APIClientWrapped_LookupBlock_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_LookupBlock_Call) RunAndReturn(run func(context.Context, int32, int64, uint32) (*tlb.BlockInfo, error)) *APIClientWrapped_LookupBlock_Call { + _c.Call.Return(run) + return _c +} + +// RunGetMethod provides a mock function with given fields: ctx, blockInfo, addr, method, params +func (_m *APIClientWrapped) RunGetMethod(ctx context.Context, blockInfo *tlb.BlockInfo, addr *address.Address, method string, params ...interface{}) (*ton.ExecutionResult, error) { + var _ca []interface{} + _ca = append(_ca, ctx, blockInfo, addr, method) + _ca = append(_ca, params...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for RunGetMethod") + } + + var r0 *ton.ExecutionResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, *address.Address, string, ...interface{}) (*ton.ExecutionResult, error)); ok { + return rf(ctx, blockInfo, addr, method, params...) + } + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, *address.Address, string, ...interface{}) *ton.ExecutionResult); ok { + r0 = rf(ctx, blockInfo, addr, method, params...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ton.ExecutionResult) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *tlb.BlockInfo, *address.Address, string, ...interface{}) error); ok { + r1 = rf(ctx, blockInfo, addr, method, params...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// APIClientWrapped_RunGetMethod_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RunGetMethod' +type APIClientWrapped_RunGetMethod_Call struct { + *mock.Call +} + +// RunGetMethod is a helper method to define mock.On call +// - ctx context.Context +// - blockInfo *tlb.BlockInfo +// - addr *address.Address +// - method string +// - params ...interface{} +func (_e *APIClientWrapped_Expecter) RunGetMethod(ctx interface{}, blockInfo interface{}, addr interface{}, method interface{}, params ...interface{}) *APIClientWrapped_RunGetMethod_Call { + return &APIClientWrapped_RunGetMethod_Call{Call: _e.mock.On("RunGetMethod", + append([]interface{}{ctx, blockInfo, addr, method}, params...)...)} +} + +func (_c *APIClientWrapped_RunGetMethod_Call) Run(run func(ctx context.Context, blockInfo *tlb.BlockInfo, addr *address.Address, method string, params ...interface{})) *APIClientWrapped_RunGetMethod_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]interface{}, len(args)-4) + for i, a := range args[4:] { + if a != nil { + variadicArgs[i] = a.(interface{}) + } + } + run(args[0].(context.Context), args[1].(*tlb.BlockInfo), args[2].(*address.Address), args[3].(string), variadicArgs...) + }) + return _c +} + +func (_c *APIClientWrapped_RunGetMethod_Call) Return(_a0 *ton.ExecutionResult, _a1 error) *APIClientWrapped_RunGetMethod_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *APIClientWrapped_RunGetMethod_Call) RunAndReturn(run func(context.Context, *tlb.BlockInfo, *address.Address, string, ...interface{}) (*ton.ExecutionResult, error)) *APIClientWrapped_RunGetMethod_Call { + _c.Call.Return(run) + return _c +} + +// SendExternalMessage provides a mock function with given fields: ctx, msg +func (_m *APIClientWrapped) SendExternalMessage(ctx context.Context, msg *tlb.ExternalMessage) error { + ret := _m.Called(ctx, msg) + + if len(ret) == 0 { + panic("no return value specified for SendExternalMessage") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.ExternalMessage) error); ok { + r0 = rf(ctx, msg) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// APIClientWrapped_SendExternalMessage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendExternalMessage' +type APIClientWrapped_SendExternalMessage_Call struct { + *mock.Call +} + +// SendExternalMessage is a helper method to define mock.On call +// - ctx context.Context +// - msg *tlb.ExternalMessage +func (_e *APIClientWrapped_Expecter) SendExternalMessage(ctx interface{}, msg interface{}) *APIClientWrapped_SendExternalMessage_Call { + return &APIClientWrapped_SendExternalMessage_Call{Call: _e.mock.On("SendExternalMessage", ctx, msg)} +} + +func (_c *APIClientWrapped_SendExternalMessage_Call) Run(run func(ctx context.Context, msg *tlb.ExternalMessage)) *APIClientWrapped_SendExternalMessage_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*tlb.ExternalMessage)) + }) + return _c +} + +func (_c *APIClientWrapped_SendExternalMessage_Call) Return(_a0 error) *APIClientWrapped_SendExternalMessage_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *APIClientWrapped_SendExternalMessage_Call) RunAndReturn(run func(context.Context, *tlb.ExternalMessage) error) *APIClientWrapped_SendExternalMessage_Call { + _c.Call.Return(run) + return _c +} + +// SendExternalMessageWaitTransaction provides a mock function with given fields: ctx, msg +func (_m *APIClientWrapped) SendExternalMessageWaitTransaction(ctx context.Context, msg *tlb.ExternalMessage) (*tlb.Transaction, *tlb.BlockInfo, []byte, error) { + ret := _m.Called(ctx, msg) + + if len(ret) == 0 { + panic("no return value specified for SendExternalMessageWaitTransaction") + } + + var r0 *tlb.Transaction + var r1 *tlb.BlockInfo + var r2 []byte + var r3 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.ExternalMessage) (*tlb.Transaction, *tlb.BlockInfo, []byte, error)); ok { + return rf(ctx, msg) + } + if rf, ok := ret.Get(0).(func(context.Context, *tlb.ExternalMessage) *tlb.Transaction); ok { + r0 = rf(ctx, msg) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *tlb.ExternalMessage) *tlb.BlockInfo); ok { + r1 = rf(ctx, msg) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*tlb.BlockInfo) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, *tlb.ExternalMessage) []byte); ok { + r2 = rf(ctx, msg) + } else { + if ret.Get(2) != nil { + r2 = ret.Get(2).([]byte) + } + } + + if rf, ok := ret.Get(3).(func(context.Context, *tlb.ExternalMessage) error); ok { + r3 = rf(ctx, msg) + } else { + r3 = ret.Error(3) + } + + return r0, r1, r2, r3 +} + +// APIClientWrapped_SendExternalMessageWaitTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendExternalMessageWaitTransaction' +type APIClientWrapped_SendExternalMessageWaitTransaction_Call struct { + *mock.Call +} + +// SendExternalMessageWaitTransaction is a helper method to define mock.On call +// - ctx context.Context +// - msg *tlb.ExternalMessage +func (_e *APIClientWrapped_Expecter) SendExternalMessageWaitTransaction(ctx interface{}, msg interface{}) *APIClientWrapped_SendExternalMessageWaitTransaction_Call { + return &APIClientWrapped_SendExternalMessageWaitTransaction_Call{Call: _e.mock.On("SendExternalMessageWaitTransaction", ctx, msg)} +} + +func (_c *APIClientWrapped_SendExternalMessageWaitTransaction_Call) Run(run func(ctx context.Context, msg *tlb.ExternalMessage)) *APIClientWrapped_SendExternalMessageWaitTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*tlb.ExternalMessage)) + }) + return _c +} + +func (_c *APIClientWrapped_SendExternalMessageWaitTransaction_Call) Return(_a0 *tlb.Transaction, _a1 *tlb.BlockInfo, _a2 []byte, _a3 error) *APIClientWrapped_SendExternalMessageWaitTransaction_Call { + _c.Call.Return(_a0, _a1, _a2, _a3) + return _c +} + +func (_c *APIClientWrapped_SendExternalMessageWaitTransaction_Call) RunAndReturn(run func(context.Context, *tlb.ExternalMessage) (*tlb.Transaction, *tlb.BlockInfo, []byte, error)) *APIClientWrapped_SendExternalMessageWaitTransaction_Call { + _c.Call.Return(run) + return _c +} + +// SetTrustedBlock provides a mock function with given fields: block +func (_m *APIClientWrapped) SetTrustedBlock(block *tlb.BlockInfo) { + _m.Called(block) +} + +// APIClientWrapped_SetTrustedBlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetTrustedBlock' +type APIClientWrapped_SetTrustedBlock_Call struct { + *mock.Call +} + +// SetTrustedBlock is a helper method to define mock.On call +// - block *tlb.BlockInfo +func (_e *APIClientWrapped_Expecter) SetTrustedBlock(block interface{}) *APIClientWrapped_SetTrustedBlock_Call { + return &APIClientWrapped_SetTrustedBlock_Call{Call: _e.mock.On("SetTrustedBlock", block)} +} + +func (_c *APIClientWrapped_SetTrustedBlock_Call) Run(run func(block *tlb.BlockInfo)) *APIClientWrapped_SetTrustedBlock_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*tlb.BlockInfo)) + }) + return _c +} + +func (_c *APIClientWrapped_SetTrustedBlock_Call) Return() *APIClientWrapped_SetTrustedBlock_Call { + _c.Call.Return() + return _c +} + +func (_c *APIClientWrapped_SetTrustedBlock_Call) RunAndReturn(run func(*tlb.BlockInfo)) *APIClientWrapped_SetTrustedBlock_Call { + _c.Run(run) + return _c +} + +// SetTrustedBlockFromConfig provides a mock function with given fields: cfg +func (_m *APIClientWrapped) SetTrustedBlockFromConfig(cfg *liteclient.GlobalConfig) { + _m.Called(cfg) +} + +// APIClientWrapped_SetTrustedBlockFromConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetTrustedBlockFromConfig' +type APIClientWrapped_SetTrustedBlockFromConfig_Call struct { + *mock.Call +} + +// SetTrustedBlockFromConfig is a helper method to define mock.On call +// - cfg *liteclient.GlobalConfig +func (_e *APIClientWrapped_Expecter) SetTrustedBlockFromConfig(cfg interface{}) *APIClientWrapped_SetTrustedBlockFromConfig_Call { + return &APIClientWrapped_SetTrustedBlockFromConfig_Call{Call: _e.mock.On("SetTrustedBlockFromConfig", cfg)} +} + +func (_c *APIClientWrapped_SetTrustedBlockFromConfig_Call) Run(run func(cfg *liteclient.GlobalConfig)) *APIClientWrapped_SetTrustedBlockFromConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*liteclient.GlobalConfig)) + }) + return _c +} + +func (_c *APIClientWrapped_SetTrustedBlockFromConfig_Call) Return() *APIClientWrapped_SetTrustedBlockFromConfig_Call { + _c.Call.Return() + return _c +} + +func (_c *APIClientWrapped_SetTrustedBlockFromConfig_Call) RunAndReturn(run func(*liteclient.GlobalConfig)) *APIClientWrapped_SetTrustedBlockFromConfig_Call { + _c.Run(run) + return _c +} + +// SubscribeOnTransactions provides a mock function with given fields: workerCtx, addr, lastProcessedLT, channel +func (_m *APIClientWrapped) SubscribeOnTransactions(workerCtx context.Context, addr *address.Address, lastProcessedLT uint64, channel chan<- *tlb.Transaction) { + _m.Called(workerCtx, addr, lastProcessedLT, channel) +} + +// APIClientWrapped_SubscribeOnTransactions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscribeOnTransactions' +type APIClientWrapped_SubscribeOnTransactions_Call struct { + *mock.Call +} + +// SubscribeOnTransactions is a helper method to define mock.On call +// - workerCtx context.Context +// - addr *address.Address +// - lastProcessedLT uint64 +// - channel chan<- *tlb.Transaction +func (_e *APIClientWrapped_Expecter) SubscribeOnTransactions(workerCtx interface{}, addr interface{}, lastProcessedLT interface{}, channel interface{}) *APIClientWrapped_SubscribeOnTransactions_Call { + return &APIClientWrapped_SubscribeOnTransactions_Call{Call: _e.mock.On("SubscribeOnTransactions", workerCtx, addr, lastProcessedLT, channel)} +} + +func (_c *APIClientWrapped_SubscribeOnTransactions_Call) Run(run func(workerCtx context.Context, addr *address.Address, lastProcessedLT uint64, channel chan<- *tlb.Transaction)) *APIClientWrapped_SubscribeOnTransactions_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*address.Address), args[2].(uint64), args[3].(chan<- *tlb.Transaction)) + }) + return _c +} + +func (_c *APIClientWrapped_SubscribeOnTransactions_Call) Return() *APIClientWrapped_SubscribeOnTransactions_Call { + _c.Call.Return() + return _c +} + +func (_c *APIClientWrapped_SubscribeOnTransactions_Call) RunAndReturn(run func(context.Context, *address.Address, uint64, chan<- *tlb.Transaction)) *APIClientWrapped_SubscribeOnTransactions_Call { + _c.Run(run) + return _c +} + +// VerifyProofChain provides a mock function with given fields: ctx, from, to +func (_m *APIClientWrapped) VerifyProofChain(ctx context.Context, from *tlb.BlockInfo, to *tlb.BlockInfo) error { + ret := _m.Called(ctx, from, to) + + if len(ret) == 0 { + panic("no return value specified for VerifyProofChain") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.BlockInfo, *tlb.BlockInfo) error); ok { + r0 = rf(ctx, from, to) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// APIClientWrapped_VerifyProofChain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'VerifyProofChain' +type APIClientWrapped_VerifyProofChain_Call struct { + *mock.Call +} + +// VerifyProofChain is a helper method to define mock.On call +// - ctx context.Context +// - from *tlb.BlockInfo +// - to *tlb.BlockInfo +func (_e *APIClientWrapped_Expecter) VerifyProofChain(ctx interface{}, from interface{}, to interface{}) *APIClientWrapped_VerifyProofChain_Call { + return &APIClientWrapped_VerifyProofChain_Call{Call: _e.mock.On("VerifyProofChain", ctx, from, to)} +} + +func (_c *APIClientWrapped_VerifyProofChain_Call) Run(run func(ctx context.Context, from *tlb.BlockInfo, to *tlb.BlockInfo)) *APIClientWrapped_VerifyProofChain_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*tlb.BlockInfo), args[2].(*tlb.BlockInfo)) + }) + return _c +} + +func (_c *APIClientWrapped_VerifyProofChain_Call) Return(_a0 error) *APIClientWrapped_VerifyProofChain_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *APIClientWrapped_VerifyProofChain_Call) RunAndReturn(run func(context.Context, *tlb.BlockInfo, *tlb.BlockInfo) error) *APIClientWrapped_VerifyProofChain_Call { + _c.Call.Return(run) + return _c +} + +// WaitForBlock provides a mock function with given fields: seqno +func (_m *APIClientWrapped) WaitForBlock(seqno uint32) ton.APIClientWrapped { + ret := _m.Called(seqno) + + if len(ret) == 0 { + panic("no return value specified for WaitForBlock") + } + + var r0 ton.APIClientWrapped + if rf, ok := ret.Get(0).(func(uint32) ton.APIClientWrapped); ok { + r0 = rf(seqno) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(ton.APIClientWrapped) + } + } + + return r0 +} + +// APIClientWrapped_WaitForBlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WaitForBlock' +type APIClientWrapped_WaitForBlock_Call struct { + *mock.Call +} + +// WaitForBlock is a helper method to define mock.On call +// - seqno uint32 +func (_e *APIClientWrapped_Expecter) WaitForBlock(seqno interface{}) *APIClientWrapped_WaitForBlock_Call { + return &APIClientWrapped_WaitForBlock_Call{Call: _e.mock.On("WaitForBlock", seqno)} +} + +func (_c *APIClientWrapped_WaitForBlock_Call) Run(run func(seqno uint32)) *APIClientWrapped_WaitForBlock_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(uint32)) + }) + return _c +} + +func (_c *APIClientWrapped_WaitForBlock_Call) Return(_a0 ton.APIClientWrapped) *APIClientWrapped_WaitForBlock_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *APIClientWrapped_WaitForBlock_Call) RunAndReturn(run func(uint32) ton.APIClientWrapped) *APIClientWrapped_WaitForBlock_Call { + _c.Call.Return(run) + return _c +} + +// WithRetry provides a mock function with given fields: maxRetries +func (_m *APIClientWrapped) WithRetry(maxRetries ...int) ton.APIClientWrapped { + _va := make([]interface{}, len(maxRetries)) + for _i := range maxRetries { + _va[_i] = maxRetries[_i] + } + var _ca []interface{} + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for WithRetry") + } + + var r0 ton.APIClientWrapped + if rf, ok := ret.Get(0).(func(...int) ton.APIClientWrapped); ok { + r0 = rf(maxRetries...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(ton.APIClientWrapped) + } + } + + return r0 +} + +// APIClientWrapped_WithRetry_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WithRetry' +type APIClientWrapped_WithRetry_Call struct { + *mock.Call +} + +// WithRetry is a helper method to define mock.On call +// - maxRetries ...int +func (_e *APIClientWrapped_Expecter) WithRetry(maxRetries ...interface{}) *APIClientWrapped_WithRetry_Call { + return &APIClientWrapped_WithRetry_Call{Call: _e.mock.On("WithRetry", + append([]interface{}{}, maxRetries...)...)} +} + +func (_c *APIClientWrapped_WithRetry_Call) Run(run func(maxRetries ...int)) *APIClientWrapped_WithRetry_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]int, len(args)-0) + for i, a := range args[0:] { + if a != nil { + variadicArgs[i] = a.(int) + } + } + run(variadicArgs...) + }) + return _c +} + +func (_c *APIClientWrapped_WithRetry_Call) Return(_a0 ton.APIClientWrapped) *APIClientWrapped_WithRetry_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *APIClientWrapped_WithRetry_Call) RunAndReturn(run func(...int) ton.APIClientWrapped) *APIClientWrapped_WithRetry_Call { + _c.Call.Return(run) + return _c +} + +// WithTimeout provides a mock function with given fields: timeout +func (_m *APIClientWrapped) WithTimeout(timeout time.Duration) ton.APIClientWrapped { + ret := _m.Called(timeout) + + if len(ret) == 0 { + panic("no return value specified for WithTimeout") + } + + var r0 ton.APIClientWrapped + if rf, ok := ret.Get(0).(func(time.Duration) ton.APIClientWrapped); ok { + r0 = rf(timeout) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(ton.APIClientWrapped) + } + } + + return r0 +} + +// APIClientWrapped_WithTimeout_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WithTimeout' +type APIClientWrapped_WithTimeout_Call struct { + *mock.Call +} + +// WithTimeout is a helper method to define mock.On call +// - timeout time.Duration +func (_e *APIClientWrapped_Expecter) WithTimeout(timeout interface{}) *APIClientWrapped_WithTimeout_Call { + return &APIClientWrapped_WithTimeout_Call{Call: _e.mock.On("WithTimeout", timeout)} +} + +func (_c *APIClientWrapped_WithTimeout_Call) Run(run func(timeout time.Duration)) *APIClientWrapped_WithTimeout_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(time.Duration)) + }) + return _c +} + +func (_c *APIClientWrapped_WithTimeout_Call) Return(_a0 ton.APIClientWrapped) *APIClientWrapped_WithTimeout_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *APIClientWrapped_WithTimeout_Call) RunAndReturn(run func(time.Duration) ton.APIClientWrapped) *APIClientWrapped_WithTimeout_Call { + _c.Call.Return(run) + return _c +} + +// NewAPIClientWrapped creates a new instance of APIClientWrapped. 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 NewAPIClientWrapped(t interface { + mock.TestingT + Cleanup(func()) +}) *APIClientWrapped { + mock := &APIClientWrapped{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sdk/ton/mocks/wallet.go b/sdk/ton/mocks/wallet.go new file mode 100644 index 000000000..f70937e22 --- /dev/null +++ b/sdk/ton/mocks/wallet.go @@ -0,0 +1,347 @@ +// Code generated by mockery v2.53.5. DO NOT EDIT. + +package mock_ton + +import ( + context "context" + + address "github.com/xssnick/tonutils-go/address" + + mock "github.com/stretchr/testify/mock" + + tlb "github.com/xssnick/tonutils-go/tlb" + + ton "github.com/xssnick/tonutils-go/ton" +) + +// TonAPI is an autogenerated mock type for the TonAPI type +type TonAPI struct { + mock.Mock +} + +type TonAPI_Expecter struct { + mock *mock.Mock +} + +func (_m *TonAPI) EXPECT() *TonAPI_Expecter { + return &TonAPI_Expecter{mock: &_m.Mock} +} + +// CurrentMasterchainInfo provides a mock function with given fields: ctx +func (_m *TonAPI) CurrentMasterchainInfo(ctx context.Context) (*tlb.BlockInfo, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for CurrentMasterchainInfo") + } + + var r0 *tlb.BlockInfo + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*tlb.BlockInfo, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *tlb.BlockInfo); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.BlockInfo) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TonAPI_CurrentMasterchainInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CurrentMasterchainInfo' +type TonAPI_CurrentMasterchainInfo_Call struct { + *mock.Call +} + +// CurrentMasterchainInfo is a helper method to define mock.On call +// - ctx context.Context +func (_e *TonAPI_Expecter) CurrentMasterchainInfo(ctx interface{}) *TonAPI_CurrentMasterchainInfo_Call { + return &TonAPI_CurrentMasterchainInfo_Call{Call: _e.mock.On("CurrentMasterchainInfo", ctx)} +} + +func (_c *TonAPI_CurrentMasterchainInfo_Call) Run(run func(ctx context.Context)) *TonAPI_CurrentMasterchainInfo_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *TonAPI_CurrentMasterchainInfo_Call) Return(_a0 *tlb.BlockInfo, _a1 error) *TonAPI_CurrentMasterchainInfo_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TonAPI_CurrentMasterchainInfo_Call) RunAndReturn(run func(context.Context) (*tlb.BlockInfo, error)) *TonAPI_CurrentMasterchainInfo_Call { + _c.Call.Return(run) + return _c +} + +// FindLastTransactionByInMsgHash provides a mock function with given fields: ctx, addr, msgHash, maxTxNumToScan +func (_m *TonAPI) FindLastTransactionByInMsgHash(ctx context.Context, addr *address.Address, msgHash []byte, maxTxNumToScan ...int) (*tlb.Transaction, error) { + _va := make([]interface{}, len(maxTxNumToScan)) + for _i := range maxTxNumToScan { + _va[_i] = maxTxNumToScan[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, addr, msgHash) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for FindLastTransactionByInMsgHash") + } + + var r0 *tlb.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *address.Address, []byte, ...int) (*tlb.Transaction, error)); ok { + return rf(ctx, addr, msgHash, maxTxNumToScan...) + } + if rf, ok := ret.Get(0).(func(context.Context, *address.Address, []byte, ...int) *tlb.Transaction); ok { + r0 = rf(ctx, addr, msgHash, maxTxNumToScan...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *address.Address, []byte, ...int) error); ok { + r1 = rf(ctx, addr, msgHash, maxTxNumToScan...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TonAPI_FindLastTransactionByInMsgHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindLastTransactionByInMsgHash' +type TonAPI_FindLastTransactionByInMsgHash_Call struct { + *mock.Call +} + +// FindLastTransactionByInMsgHash is a helper method to define mock.On call +// - ctx context.Context +// - addr *address.Address +// - msgHash []byte +// - maxTxNumToScan ...int +func (_e *TonAPI_Expecter) FindLastTransactionByInMsgHash(ctx interface{}, addr interface{}, msgHash interface{}, maxTxNumToScan ...interface{}) *TonAPI_FindLastTransactionByInMsgHash_Call { + return &TonAPI_FindLastTransactionByInMsgHash_Call{Call: _e.mock.On("FindLastTransactionByInMsgHash", + append([]interface{}{ctx, addr, msgHash}, maxTxNumToScan...)...)} +} + +func (_c *TonAPI_FindLastTransactionByInMsgHash_Call) Run(run func(ctx context.Context, addr *address.Address, msgHash []byte, maxTxNumToScan ...int)) *TonAPI_FindLastTransactionByInMsgHash_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]int, len(args)-3) + for i, a := range args[3:] { + if a != nil { + variadicArgs[i] = a.(int) + } + } + run(args[0].(context.Context), args[1].(*address.Address), args[2].([]byte), variadicArgs...) + }) + return _c +} + +func (_c *TonAPI_FindLastTransactionByInMsgHash_Call) Return(_a0 *tlb.Transaction, _a1 error) *TonAPI_FindLastTransactionByInMsgHash_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TonAPI_FindLastTransactionByInMsgHash_Call) RunAndReturn(run func(context.Context, *address.Address, []byte, ...int) (*tlb.Transaction, error)) *TonAPI_FindLastTransactionByInMsgHash_Call { + _c.Call.Return(run) + return _c +} + +// SendExternalMessage provides a mock function with given fields: ctx, msg +func (_m *TonAPI) SendExternalMessage(ctx context.Context, msg *tlb.ExternalMessage) error { + ret := _m.Called(ctx, msg) + + if len(ret) == 0 { + panic("no return value specified for SendExternalMessage") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.ExternalMessage) error); ok { + r0 = rf(ctx, msg) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// TonAPI_SendExternalMessage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendExternalMessage' +type TonAPI_SendExternalMessage_Call struct { + *mock.Call +} + +// SendExternalMessage is a helper method to define mock.On call +// - ctx context.Context +// - msg *tlb.ExternalMessage +func (_e *TonAPI_Expecter) SendExternalMessage(ctx interface{}, msg interface{}) *TonAPI_SendExternalMessage_Call { + return &TonAPI_SendExternalMessage_Call{Call: _e.mock.On("SendExternalMessage", ctx, msg)} +} + +func (_c *TonAPI_SendExternalMessage_Call) Run(run func(ctx context.Context, msg *tlb.ExternalMessage)) *TonAPI_SendExternalMessage_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*tlb.ExternalMessage)) + }) + return _c +} + +func (_c *TonAPI_SendExternalMessage_Call) Return(_a0 error) *TonAPI_SendExternalMessage_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TonAPI_SendExternalMessage_Call) RunAndReturn(run func(context.Context, *tlb.ExternalMessage) error) *TonAPI_SendExternalMessage_Call { + _c.Call.Return(run) + return _c +} + +// SendExternalMessageWaitTransaction provides a mock function with given fields: ctx, ext +func (_m *TonAPI) SendExternalMessageWaitTransaction(ctx context.Context, ext *tlb.ExternalMessage) (*tlb.Transaction, *tlb.BlockInfo, []byte, error) { + ret := _m.Called(ctx, ext) + + if len(ret) == 0 { + panic("no return value specified for SendExternalMessageWaitTransaction") + } + + var r0 *tlb.Transaction + var r1 *tlb.BlockInfo + var r2 []byte + var r3 error + if rf, ok := ret.Get(0).(func(context.Context, *tlb.ExternalMessage) (*tlb.Transaction, *tlb.BlockInfo, []byte, error)); ok { + return rf(ctx, ext) + } + if rf, ok := ret.Get(0).(func(context.Context, *tlb.ExternalMessage) *tlb.Transaction); ok { + r0 = rf(ctx, ext) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*tlb.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *tlb.ExternalMessage) *tlb.BlockInfo); ok { + r1 = rf(ctx, ext) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*tlb.BlockInfo) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, *tlb.ExternalMessage) []byte); ok { + r2 = rf(ctx, ext) + } else { + if ret.Get(2) != nil { + r2 = ret.Get(2).([]byte) + } + } + + if rf, ok := ret.Get(3).(func(context.Context, *tlb.ExternalMessage) error); ok { + r3 = rf(ctx, ext) + } else { + r3 = ret.Error(3) + } + + return r0, r1, r2, r3 +} + +// TonAPI_SendExternalMessageWaitTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendExternalMessageWaitTransaction' +type TonAPI_SendExternalMessageWaitTransaction_Call struct { + *mock.Call +} + +// SendExternalMessageWaitTransaction is a helper method to define mock.On call +// - ctx context.Context +// - ext *tlb.ExternalMessage +func (_e *TonAPI_Expecter) SendExternalMessageWaitTransaction(ctx interface{}, ext interface{}) *TonAPI_SendExternalMessageWaitTransaction_Call { + return &TonAPI_SendExternalMessageWaitTransaction_Call{Call: _e.mock.On("SendExternalMessageWaitTransaction", ctx, ext)} +} + +func (_c *TonAPI_SendExternalMessageWaitTransaction_Call) Run(run func(ctx context.Context, ext *tlb.ExternalMessage)) *TonAPI_SendExternalMessageWaitTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*tlb.ExternalMessage)) + }) + return _c +} + +func (_c *TonAPI_SendExternalMessageWaitTransaction_Call) Return(_a0 *tlb.Transaction, _a1 *tlb.BlockInfo, _a2 []byte, _a3 error) *TonAPI_SendExternalMessageWaitTransaction_Call { + _c.Call.Return(_a0, _a1, _a2, _a3) + return _c +} + +func (_c *TonAPI_SendExternalMessageWaitTransaction_Call) RunAndReturn(run func(context.Context, *tlb.ExternalMessage) (*tlb.Transaction, *tlb.BlockInfo, []byte, error)) *TonAPI_SendExternalMessageWaitTransaction_Call { + _c.Call.Return(run) + return _c +} + +// WaitForBlock provides a mock function with given fields: seqno +func (_m *TonAPI) WaitForBlock(seqno uint32) ton.APIClientWrapped { + ret := _m.Called(seqno) + + if len(ret) == 0 { + panic("no return value specified for WaitForBlock") + } + + var r0 ton.APIClientWrapped + if rf, ok := ret.Get(0).(func(uint32) ton.APIClientWrapped); ok { + r0 = rf(seqno) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(ton.APIClientWrapped) + } + } + + return r0 +} + +// TonAPI_WaitForBlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WaitForBlock' +type TonAPI_WaitForBlock_Call struct { + *mock.Call +} + +// WaitForBlock is a helper method to define mock.On call +// - seqno uint32 +func (_e *TonAPI_Expecter) WaitForBlock(seqno interface{}) *TonAPI_WaitForBlock_Call { + return &TonAPI_WaitForBlock_Call{Call: _e.mock.On("WaitForBlock", seqno)} +} + +func (_c *TonAPI_WaitForBlock_Call) Run(run func(seqno uint32)) *TonAPI_WaitForBlock_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(uint32)) + }) + return _c +} + +func (_c *TonAPI_WaitForBlock_Call) Return(_a0 ton.APIClientWrapped) *TonAPI_WaitForBlock_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TonAPI_WaitForBlock_Call) RunAndReturn(run func(uint32) ton.APIClientWrapped) *TonAPI_WaitForBlock_Call { + _c.Call.Return(run) + return _c +} + +// NewTonAPI creates a new instance of TonAPI. 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 NewTonAPI(t interface { + mock.TestingT + Cleanup(func()) +}) *TonAPI { + mock := &TonAPI{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sdk/ton/timelock_converter.go b/sdk/ton/timelock_converter.go new file mode 100644 index 000000000..784cbc581 --- /dev/null +++ b/sdk/ton/timelock_converter.go @@ -0,0 +1,168 @@ +package ton + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/smartcontractkit/mcms/sdk" + sdkerrors "github.com/smartcontractkit/mcms/sdk/errors" + "github.com/smartcontractkit/mcms/types" + + "github.com/ethereum/go-ethereum/common" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/timelock" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +// Default amount to send with timelock transactions (to cover gas fees) +var DefaultSendAmount = tlb.MustFromTON("0.15") + +var _ sdk.TimelockConverter = (*timelockConverter)(nil) + +type timelockConverter struct { + // Transaction opts + amount tlb.Coins +} + +// NewTimelockConverter creates a new TimelockConverter +func NewTimelockConverter(amount tlb.Coins) sdk.TimelockConverter { + return &timelockConverter{ + amount: amount, + } +} + +func (t *timelockConverter) ConvertBatchToChainOperations( + _ context.Context, + metadata types.ChainMetadata, + bop types.BatchOperation, + timelockAddress string, + mcmAddress string, + delay types.Duration, + action types.TimelockAction, + predecessor common.Hash, + salt common.Hash, +) ([]types.Operation, common.Hash, error) { + // Create the list of RBACTimelockCall (batch of calls) and tags for the operations + calls, err := ConvertBatchToCalls(bop) + if err != nil { + return []types.Operation{}, common.Hash{}, fmt.Errorf("failed to convert batch to calls: %w", err) + } + + tags := make([]string, 0) + for _, tx := range bop.Transactions { + tags = append(tags, tx.Tags...) + } + + operationID, errHash := HashOperationBatch(calls, predecessor, salt) + if errHash != nil { + return []types.Operation{}, common.Hash{}, errHash + } + + qID, err := tvm.RandomQueryID() + if err != nil { + return []types.Operation{}, common.Hash{}, fmt.Errorf("failed to generate random query ID: %w", err) + } + + // Encode the data based on the operation + var data *cell.Cell + switch action { + case types.TimelockActionSchedule: + data, err = tlb.ToCell(timelock.ScheduleBatch{ + QueryID: qID, + + Calls: calls, + Predecessor: tlbe.NewUint256(predecessor.Big()), + Salt: tlbe.NewUint256(salt.Big()), + Delay: uint32(delay.Seconds()), + }) + case types.TimelockActionCancel: + data, err = tlb.ToCell(timelock.Cancel{ + QueryID: qID, + + ID: tlbe.NewUint256(operationID.Big()), + }) + case types.TimelockActionBypass: + data, err = tlb.ToCell(timelock.BypasserExecuteBatch{ + QueryID: qID, + + Calls: calls, + }) + default: + return []types.Operation{}, common.Hash{}, sdkerrors.NewInvalidTimelockOperationError(string(action)) + } + + if err != nil { + return []types.Operation{}, common.Hash{}, fmt.Errorf("failed to encode timelock action data: %w", err) + } + + // Map to Ton Address type + dstAddr, err := address.ParseAddr(timelockAddress) + if err != nil { + return []types.Operation{}, common.Hash{}, fmt.Errorf("invalid timelock address: %w", err) + } + + // Notice: EVM just sets 0 here, but on TON we need to set some value to cover gas fees + var tx types.Transaction + tx, err = NewTransaction(dstAddr, data.BeginParse(), t.amount.Nano(), "RBACTimelock", tags) + if err != nil { + return []types.Operation{}, common.Hash{}, fmt.Errorf("failed to create transaction: %w", err) + } + + op := types.Operation{ + ChainSelector: bop.ChainSelector, + Transaction: tx, + } + + return []types.Operation{op}, operationID, nil +} + +func ConvertBatchToCalls(bop types.BatchOperation) ([]timelock.Call, error) { + calls := make([]timelock.Call, len(bop.Transactions)) + for i, tx := range bop.Transactions { + // Unmarshal the AdditionalFields from the operation + var additionalFields AdditionalFields + if err := json.Unmarshal(tx.AdditionalFields, &additionalFields); err != nil { + return nil, fmt.Errorf("failed to unmarshal additional fields: %w", err) + } + + // Map to Ton Address type + to, err := address.ParseAddr(tx.To) + if err != nil { + return nil, fmt.Errorf("invalid target address: %w", err) + } + + datac, err := cell.FromBOC(tx.Data) + if err != nil { + return nil, fmt.Errorf("invalid cell BOC data: %w", err) + } + + calls[i] = timelock.Call{ + Target: to, + Data: datac, + Value: tlb.FromNanoTON(additionalFields.Value), + } + } + + return calls, nil +} + +// HashOperationBatch replicates the hash calculation from Solidity +func HashOperationBatch(calls []timelock.Call, predecessor, salt common.Hash) (common.Hash, error) { + ob, err := tlb.ToCell(timelock.OperationBatch{ + Calls: calls, + Predecessor: tlbe.NewUint256(predecessor.Big()), + Salt: tlbe.NewUint256(salt.Big()), + }) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to encode OperationBatch: %w", err) + } + + // Return the hash as a [32]byte array + return common.BytesToHash(ob.Hash()), nil +} diff --git a/sdk/ton/timelock_converter_test.go b/sdk/ton/timelock_converter_test.go new file mode 100644 index 000000000..34b9f31f5 --- /dev/null +++ b/sdk/ton/timelock_converter_test.go @@ -0,0 +1,156 @@ +package ton_test + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + + cselectors "github.com/smartcontractkit/chain-selectors" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" + + sdkerrors "github.com/smartcontractkit/mcms/sdk/errors" + "github.com/smartcontractkit/mcms/types" + + "github.com/smartcontractkit/mcms/sdk/ton" +) + +func TestTimelockConverter_ConvertBatchToChainOperation(t *testing.T) { + t.Parallel() + + ctx := context.Background() + timelockAddress := "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8" + mcmAddress := "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8" + zeroHash := common.Hash{} + + testOp := types.BatchOperation{ + Transactions: []types.Transaction{must(ton.NewTransaction( + address.MustParseAddr("EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8"), + cell.BeginCell().MustStoreBinarySnake([]byte("data")).ToSlice(), + new(big.Int).SetUint64(1000), + "RBACTimelock", + []string{"tag1", "tag2"}, + ))}, + ChainSelector: types.ChainSelector(cselectors.TON_TESTNET.Selector), + } + + testCases := []struct { + name string + metadata types.ChainMetadata + op types.BatchOperation + delay string + operation types.TimelockAction + predecessor common.Hash + salt common.Hash + wantErr string + expectedOpType string + }{ + { + name: "Schedule operation", + op: testOp, + delay: "1h", + operation: types.TimelockActionSchedule, + predecessor: zeroHash, + salt: zeroHash, + expectedOpType: "RBACTimelock", + }, + { + name: "Cancel operation", + op: testOp, + delay: "1h", + operation: types.TimelockActionCancel, + predecessor: zeroHash, + salt: zeroHash, + expectedOpType: "RBACTimelock", + }, + { + name: "Schedule operation", + op: testOp, + delay: "1h", + operation: types.TimelockActionBypass, + predecessor: zeroHash, + salt: zeroHash, + expectedOpType: "RBACTimelock", + }, + { + name: "Invalid operation", + op: testOp, + delay: "1h", + operation: types.TimelockAction("invalid"), + predecessor: zeroHash, + salt: zeroHash, + wantErr: sdkerrors.NewInvalidTimelockOperationError("invalid").Error(), + expectedOpType: "", + }, + { + name: "Invalid additional fields", + op: types.BatchOperation{ + Transactions: []types.Transaction{{ + OperationMetadata: types.OperationMetadata{ContractType: "RBACTimelock"}, + To: timelockAddress, + Data: []byte("0x1234"), + AdditionalFields: []byte("invalid"), + }}, + ChainSelector: types.ChainSelector(cselectors.TON_TESTNET.Selector), + }, + delay: "1h", + operation: types.TimelockActionSchedule, + predecessor: zeroHash, + salt: zeroHash, + wantErr: "failed to unmarshal additional fields: invalid character 'i' looking for beginning of value", + }, + { + name: "Invalid address in transaction", + op: types.BatchOperation{ + Transactions: []types.Transaction{{ + OperationMetadata: types.OperationMetadata{ContractType: "RBACTimelock"}, + To: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-", // invalid address + Data: []byte("0x1234"), + AdditionalFields: []byte("{\"value\":1000}"), + }}, + ChainSelector: types.ChainSelector(cselectors.TON_TESTNET.Selector), + }, + delay: "1h", + operation: types.TimelockActionSchedule, + predecessor: zeroHash, + salt: zeroHash, + wantErr: "failed to convert batch to calls: invalid target address: incorrect address data", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + converter := ton.NewTimelockConverter(ton.DefaultSendAmount) + chainOperations, operationID, err := converter.ConvertBatchToChainOperations( + ctx, + tc.metadata, + tc.op, + timelockAddress, + mcmAddress, + types.MustParseDuration(tc.delay), + tc.operation, + tc.predecessor, + tc.salt, + ) + + if tc.wantErr != "" { + require.Error(t, err) + require.ErrorContains(t, err, tc.wantErr) + } else { + require.NoError(t, err) + assert.NotEqual(t, common.Hash{}, operationID) + assert.Len(t, chainOperations, 1) + assert.Equal(t, timelockAddress, chainOperations[0].Transaction.To) + assert.Equal(t, tc.op.ChainSelector, chainOperations[0].ChainSelector) + } + }) + } +} diff --git a/sdk/ton/timelock_executor.go b/sdk/ton/timelock_executor.go new file mode 100644 index 000000000..7f0ab4e82 --- /dev/null +++ b/sdk/ton/timelock_executor.go @@ -0,0 +1,97 @@ +package ton + +import ( + "context" + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/samber/lo" + + "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/types" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/ton/wallet" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/timelock" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tlbe" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +var _ sdk.TimelockExecutor = (*timelockExecutor)(nil) + +// sdk.TimelockExecutor implementation for TON chains for accessing the RBACTimelock contract +type timelockExecutor struct { + sdk.TimelockInspector + wallet *wallet.Wallet + + // Transaction opts + amount tlb.Coins +} + +type TimelockExecutorOpts struct { + Client ton.APIClientWrapped + Wallet *wallet.Wallet + Amount tlb.Coins +} + +// NewTimelockExecutor creates a new TimelockExecutor +func NewTimelockExecutor(opts TimelockExecutorOpts) (sdk.TimelockExecutor, error) { + if lo.IsNil(opts.Client) { + return nil, errors.New("failed to create sdk.Executor - client (ton.APIClientWrapped) is nil") + } + + if opts.Wallet == nil { + return nil, errors.New("failed to create sdk.Executor - wallet (*wallet.Wallet) is nil") + } + + return &timelockExecutor{ + TimelockInspector: NewTimelockInspector(opts.Client), + wallet: opts.Wallet, + amount: opts.Amount, + }, nil +} + +func (e *timelockExecutor) Execute( + ctx context.Context, bop types.BatchOperation, timelockAddress string, predecessor common.Hash, salt common.Hash, +) (types.TransactionResult, error) { + // Map to Ton Address type + dstAddr, err := address.ParseAddr(timelockAddress) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("invalid timelock address: %w", err) + } + + calls, err := ConvertBatchToCalls(bop) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to convert batch to calls: %w", err) + } + + qID, err := tvm.RandomQueryID() + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to generate random query ID: %w", err) + } + + body, err := tlb.ToCell(timelock.ExecuteBatch{ + QueryID: qID, + + Calls: calls, + Predecessor: tlbe.NewUint256(predecessor.Big()), + Salt: tlbe.NewUint256(salt.Big()), + }) + if err != nil { + return types.TransactionResult{}, fmt.Errorf("failed to encode ExecuteBatch body: %w", err) + } + + skipSend := false // TODO: expose via executor options + + return SendTx(ctx, TxOpts{ + Wallet: e.wallet, + DstAddr: dstAddr, + Amount: e.amount, + Body: body, + SkipSend: skipSend, + }) +} diff --git a/sdk/ton/timelock_executor_test.go b/sdk/ton/timelock_executor_test.go new file mode 100644 index 000000000..fb211d184 --- /dev/null +++ b/sdk/ton/timelock_executor_test.go @@ -0,0 +1,203 @@ +package ton_test + +import ( + "context" + "encoding/json" + "errors" + "math/big" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + "github.com/smartcontractkit/mcms/internal/testutils/chaintest" + "github.com/smartcontractkit/mcms/types" + + mcmston "github.com/smartcontractkit/mcms/sdk/ton" + ton_mocks "github.com/smartcontractkit/mcms/sdk/ton/mocks" +) + +func TestTimelockExecutor_NewTimelockExecutor(t *testing.T) { + t.Parallel() + + chainID := chaintest.Chain7TONID + amount := tlb.MustFromTON("0.1") + + tests := []struct { + name string + mutate func(opts mcmston.TimelockExecutorOpts) mcmston.TimelockExecutorOpts + wantErr string + }{ + { + name: "success", + mutate: func(opts mcmston.TimelockExecutorOpts) mcmston.TimelockExecutorOpts { + return opts + }, + wantErr: "", + }, + { + name: "nil client", + mutate: func(opts mcmston.TimelockExecutorOpts) mcmston.TimelockExecutorOpts { + opts.Client = nil + + return opts + }, + wantErr: "failed to create sdk.Executor - client (ton.APIClientWrapped) is nil", + }, + { + name: "nil wallet", + mutate: func(opts mcmston.TimelockExecutorOpts) mcmston.TimelockExecutorOpts { + opts.Wallet = nil + + return opts + }, + wantErr: "failed to create sdk.Executor - wallet (*wallet.Wallet) is nil", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + _api := ton_mocks.NewTonAPI(t) + walletOperator := must(tvm.NewRandomV5R1TestWallet(_api, chainID)) + var client ton.APIClientWrapped = ton_mocks.NewAPIClientWrapped(t) + + opts := tt.mutate(mcmston.TimelockExecutorOpts{ + Client: client, + Wallet: walletOperator, + Amount: amount, + }) + + executor, err := mcmston.NewTimelockExecutor(opts) + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + require.Nil(t, executor) + + return + } + + require.NoError(t, err) + require.NotNil(t, executor) + }) + } +} + +func TestTimelockExecutor_Execute(t *testing.T) { + t.Parallel() + + ctx := context.Background() + + sharedMockSetup := func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) { + // Mock CurrentMasterchainInfo + api.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + // Mock WaitForBlock + client.EXPECT().GetAccount(mock.Anything, mock.Anything, mock.Anything). + Return(&tlb.Account{}, nil) + + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(ton.NewExecutionResult([]any{big.NewInt(5)}), nil) + + api.EXPECT().WaitForBlock(mock.Anything). + Return(client) + } + + tests := []struct { + name string + timelockAddress string + bop types.BatchOperation + predecessor common.Hash + salt common.Hash + mockSetup func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) + wantTxHash string + wantErr error + }{ + { + name: "success", + timelockAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + bop: types.BatchOperation{ + ChainSelector: chaintest.Chain7Selector, + Transactions: []types.Transaction{ + { + To: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + Data: cell.BeginCell().MustStoreBinarySnake([]byte{1, 2, 3}).EndCell().ToBOC(), + AdditionalFields: json.RawMessage(`{"value": 0}`)}, + }, + }, + mockSetup: func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) { + // Successful tx send + sharedMockSetup(api, client) + + // Mock SendTransaction to return (no error) + api.EXPECT().SendExternalMessageWaitTransaction(mock.Anything, mock.Anything). + Return(&tlb.Transaction{Hash: []byte{1, 2, 3, 4, 14}}, &ton.BlockIDExt{}, []byte{}, nil) + }, + wantTxHash: "010203040e", + wantErr: nil, + }, + { + name: "failure in tx execution", + timelockAddress: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + bop: types.BatchOperation{ + ChainSelector: chaintest.Chain7Selector, + Transactions: []types.Transaction{ + { + To: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + Data: cell.BeginCell().MustStoreBinarySnake([]byte{1, 2, 3}).EndCell().ToBOC(), + AdditionalFields: json.RawMessage(`{"value": 0}`)}, + }, + }, + mockSetup: func(api *ton_mocks.TonAPI, client *ton_mocks.APIClientWrapped) { + // Error tx send + sharedMockSetup(api, client) + + // Mock SendTransaction to return an error + api.EXPECT().SendExternalMessageWaitTransaction(mock.Anything, mock.Anything). + Return(&tlb.Transaction{Hash: []byte{1, 2, 3, 4, 14}}, &ton.BlockIDExt{}, []byte{}, errors.New("error during tx send")) + }, + wantTxHash: "", + wantErr: errors.New("failed to send transaction: error during tx send"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + // Initialize the mock + chainID := chaintest.Chain7TONID + _api := ton_mocks.NewTonAPI(t) + walletOperator := must(tvm.NewRandomV5R1TestWallet(_api, chainID)) + + client := ton_mocks.NewAPIClientWrapped(t) + + if tt.mockSetup != nil { + tt.mockSetup(_api, client) + } + + executor, err := mcmston.NewTimelockExecutor(mcmston.TimelockExecutorOpts{ + Client: client, + Wallet: walletOperator, + Amount: tlb.MustFromTON("0.1"), + }) + require.NoError(t, err) + + tx, err := executor.Execute(ctx, tt.bop, tt.timelockAddress, tt.predecessor, tt.salt) + require.Equal(t, tt.wantTxHash, tx.Hash) + if tt.wantErr != nil { + require.EqualError(t, err, tt.wantErr.Error()) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/sdk/ton/timelock_inspector.go b/sdk/ton/timelock_inspector.go new file mode 100644 index 000000000..fc7acdc18 --- /dev/null +++ b/sdk/ton/timelock_inspector.go @@ -0,0 +1,126 @@ +package ton + +import ( + "context" + "fmt" + "math/big" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/ton" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/lib/access/rbac" + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/timelock" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + "github.com/smartcontractkit/mcms/sdk" +) + +var _ sdk.TimelockInspector = (*TimelockInspector)(nil) + +// TimelockInspector is an Inspector implementation for TON, for accessing the MCMS-Timelock contract +type TimelockInspector struct { + client ton.APIClientWrapped +} + +func NewTimelockInspector(client ton.APIClientWrapped) sdk.TimelockInspector { + return &TimelockInspector{client} +} + +func (i TimelockInspector) GetMinDelay(ctx context.Context, _address string) (uint64, error) { + addr, block, err := ParseAddrGetBlock(ctx, i.client, _address) + if err != nil { + return 0, err + } + + return tvm.CallGetter(ctx, i.client, block, addr, timelock.GetMinDelay) +} + +// GetAdmins returns the list of addresses with the admin role +func (i TimelockInspector) GetAdmins(ctx context.Context, addr string) ([]string, error) { + return i.getRoleMembers(ctx, addr, [32]byte(timelock.RoleAdmin.Bytes())) +} + +// GetProposers returns the list of addresses with the proposer role +func (i TimelockInspector) GetProposers(ctx context.Context, addr string) ([]string, error) { + return i.getRoleMembers(ctx, addr, [32]byte(timelock.RoleProposer.Bytes())) +} + +// GetExecutors returns the list of addresses with the executor role +func (i TimelockInspector) GetExecutors(ctx context.Context, addr string) ([]string, error) { + return i.getRoleMembers(ctx, addr, [32]byte(timelock.RoleExecutor.Bytes())) +} + +// GetBypassers returns the list of addresses with the bypasser role +func (i TimelockInspector) GetBypassers(ctx context.Context, addr string) ([]string, error) { + return i.getRoleMembers(ctx, addr, [32]byte(timelock.RoleBypasser.Bytes())) +} + +// GetCancellers returns the list of addresses with the canceller role +func (i TimelockInspector) GetCancellers(ctx context.Context, addr string) ([]string, error) { + return i.getRoleMembers(ctx, addr, [32]byte(timelock.RoleCanceller.Bytes())) +} + +// GetOracles returns the list of addresses with the oracle role +func (i TimelockInspector) GetOracles(ctx context.Context, addr string) ([]string, error) { + return i.getRoleMembers(ctx, addr, [32]byte(timelock.RoleOracle.Bytes())) +} + +// getRoleMembers returns the list of addresses with the given role +func (i TimelockInspector) getRoleMembers(ctx context.Context, _address string, role [32]byte) ([]string, error) { + // Map to Ton Address type (timelock.address) + addr, err := address.ParseAddr(_address) + if err != nil { + return nil, fmt.Errorf("invalid timelock address: %w", err) + } + + _role := new(big.Int).SetBytes(role[:]) + _addresses, err := rbac.GetRoleMembersView(ctx, i.client, addr, _role) + if err != nil { + return nil, fmt.Errorf("error calling GetRoleMembersView: %w", err) + } + + n := len(_addresses) + addresses := make([]string, n) + for j := range n { + addresses[j] = _addresses[j].String() + } + + return addresses, nil +} + +func (i TimelockInspector) IsOperation(ctx context.Context, _address string, opID [32]byte) (bool, error) { + return i.isOperationFor(ctx, _address, opID, timelock.IsOperation) +} + +func (i TimelockInspector) IsOperationPending(ctx context.Context, _address string, opID [32]byte) (bool, error) { + return i.isOperationFor(ctx, _address, opID, timelock.IsOperationPending) +} + +func (i TimelockInspector) IsOperationReady(ctx context.Context, _address string, opID [32]byte) (bool, error) { + return i.isOperationFor(ctx, _address, opID, timelock.IsOperationReady) +} + +func (i TimelockInspector) IsOperationDone(ctx context.Context, _address string, opID [32]byte) (bool, error) { + return i.isOperationFor(ctx, _address, opID, timelock.IsOperationDone) +} + +func (i TimelockInspector) IsOperationError(ctx context.Context, _address string, opID [32]byte) (bool, error) { + return i.isOperationFor(ctx, _address, opID, timelock.IsOperationError) +} + +// isOperationFor is a helper function to check the status of an operation using the provided getter +func (i TimelockInspector) isOperationFor( + ctx context.Context, + _address string, + opID [32]byte, + getter tvm.Getter[*big.Int, bool], +) (bool, error) { + addr, block, err := ParseAddrGetBlock(ctx, i.client, _address) + if err != nil { + return false, err + } + + _opID := new(big.Int).SetBytes(opID[:]) + + return tvm.CallGetter(ctx, i.client, block, addr, getter, _opID) +} diff --git a/sdk/ton/timelock_inspector_test.go b/sdk/ton/timelock_inspector_test.go new file mode 100644 index 000000000..a5a0c6df1 --- /dev/null +++ b/sdk/ton/timelock_inspector_test.go @@ -0,0 +1,568 @@ +package ton_test + +import ( + "context" + "errors" + "math/big" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/ton/wallet" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" + + "github.com/smartcontractkit/mcms/internal/testutils/chaintest" + + mcmston "github.com/smartcontractkit/mcms/sdk/ton" + ton_mocks "github.com/smartcontractkit/mcms/sdk/ton/mocks" +) + +type roleFetchTest struct { + name string + address string + roleMemberCount *big.Int + roleMembers []*address.Address + proposerRole [32]byte + mockError error + want []string + wantErr error + roleFetchType string // Specify the role type (proposers, executors, etc.) +} + +// Helper to mock contract calls for each role test case +func (tt roleFetchTest) mockRoleContractCalls(t *testing.T, client *ton_mocks.APIClientWrapped) { + t.Helper() + + // Mock CurrentMasterchainInfo + client.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + // Mock response for role member count + encodedRoleMemberCount := tt.roleMemberCount + r := ton.NewExecutionResult([]any{encodedRoleMemberCount}) + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(r, nil).Once() + + // Mock response for each role member + for _, member := range tt.roleMembers { + encodedMember := cell.BeginCell().MustStoreAddr(member).ToSlice() + + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(ton.NewExecutionResult([]any{encodedMember}), nil).Once() + } +} + +func TestTimelockInspector_GetRolesTests(t *testing.T) { + t.Parallel() + + var chainID = chaintest.Chain7TONID + var client *ton.APIClient + var wallets = []*wallet.Wallet{ + must(tvm.NewRandomV5R1TestWallet(client, chainID)), + must(tvm.NewRandomV5R1TestWallet(client, chainID)), + must(tvm.NewRandomV5R1TestWallet(client, chainID)), + must(tvm.NewRandomV5R1TestWallet(client, chainID)), + must(tvm.NewRandomV5R1TestWallet(client, chainID)), + must(tvm.NewRandomV5R1TestWallet(client, chainID)), + must(tvm.NewRandomV5R1TestWallet(client, chainID)), + must(tvm.NewRandomV5R1TestWallet(client, chainID)), + } + + ctx := context.Background() + tests := []roleFetchTest{ + { + name: "GetProposers success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + roleMemberCount: big.NewInt(3), + roleMembers: []*address.Address{ + wallets[0].Address(), + wallets[1].Address(), + wallets[2].Address(), + }, + proposerRole: [32]byte{0x01}, + want: []string{ + wallets[0].Address().String(), + wallets[1].Address().String(), + wallets[2].Address().String(), + }, + roleFetchType: "proposers", + }, + { + name: "GetProposers call contract failure error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockError: errors.New("call to contract failed"), + want: nil, + wantErr: errors.New("error calling GetRoleMembersView: tvm: failed to run get method \"getRoleMemberCount\": call to contract failed"), + roleFetchType: "proposers", + }, + { + name: "GetExecutors success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + roleMemberCount: big.NewInt(3), + roleMembers: []*address.Address{ + wallets[0].Address(), + wallets[1].Address(), + wallets[2].Address(), + }, + proposerRole: [32]byte{0x01}, + want: []string{ + wallets[0].Address().String(), + wallets[1].Address().String(), + wallets[2].Address().String(), + }, + roleFetchType: "executors", + }, + { + name: "GetExecutors call contract failure error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockError: errors.New("call to contract failed"), + want: nil, + wantErr: errors.New("error calling GetRoleMembersView: tvm: failed to run get method \"getRoleMemberCount\": call to contract failed"), + roleFetchType: "executors", + }, + { + name: "GetExecutors success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + roleMemberCount: big.NewInt(3), + roleMembers: []*address.Address{ + wallets[0].Address(), + wallets[1].Address(), + wallets[2].Address(), + }, + proposerRole: [32]byte{0x01}, + want: []string{ + wallets[0].Address().String(), + wallets[1].Address().String(), + wallets[2].Address().String(), + }, + roleFetchType: "executors", + }, + { + name: "GetExecutors call contract failure error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockError: errors.New("call to contract failed"), + want: nil, + wantErr: errors.New("error calling GetRoleMembersView: tvm: failed to run get method \"getRoleMemberCount\": call to contract failed"), + roleFetchType: "executors", + }, + { + name: "GetBypassers success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + roleMemberCount: big.NewInt(3), + roleMembers: []*address.Address{ + wallets[0].Address(), + wallets[1].Address(), + wallets[2].Address(), + }, + proposerRole: [32]byte{0x01}, + want: []string{ + wallets[0].Address().String(), + wallets[1].Address().String(), + wallets[2].Address().String(), + }, + roleFetchType: "bypassers", + }, + { + name: "GetBypassers call contract failure error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockError: errors.New("call to contract failed"), + want: nil, + wantErr: errors.New("error calling GetRoleMembersView: tvm: failed to run get method \"getRoleMemberCount\": call to contract failed"), + roleFetchType: "bypassers", + }, + { + name: "GetCancellers success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + roleMemberCount: big.NewInt(3), + roleMembers: []*address.Address{ + wallets[0].Address(), + wallets[1].Address(), + wallets[2].Address(), + }, + proposerRole: [32]byte{0x01}, + want: []string{ + wallets[0].Address().String(), + wallets[1].Address().String(), + wallets[2].Address().String(), + }, + roleFetchType: "bypassers", + }, + { + name: "GetCancellers call contract failure error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockError: errors.New("call to contract failed"), + want: nil, + wantErr: errors.New("error calling GetRoleMembersView: tvm: failed to run get method \"getRoleMemberCount\": call to contract failed"), + roleFetchType: "cancellers", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + // Create a new mock client and inspector for each test case + client := ton_mocks.NewAPIClientWrapped(t) + inspector := mcmston.NewTimelockInspector(client) + + // Mock the contract calls based on the test case + if tt.mockError == nil { + tt.mockRoleContractCalls(t, client) + } else { + // Mock CurrentMasterchainInfo + client.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + // If there's an error, mock it on the first CallContract call + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(nil, tt.mockError).Once() + } + + // Select and call the appropriate role-fetching function + var got []string + var err error + switch tt.roleFetchType { + case "proposers": + got, err = inspector.GetProposers(ctx, tt.address) + case "executors": + got, err = inspector.GetExecutors(ctx, tt.address) + case "cancellers": + got, err = inspector.GetCancellers(ctx, tt.address) + case "bypassers": + got, err = inspector.GetBypassers(ctx, tt.address) + default: + t.Fatalf("unsupported roleFetchType: %s", tt.roleFetchType) + } + + // Assertions for expected error or successful result + if tt.wantErr != nil { + require.Error(t, err) + require.EqualError(t, err, tt.wantErr.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tt.want, got) + } + + // Verify expectations + client.AssertExpectations(t) + }) + } +} + +func TestTimelockInspector_IsOperation(t *testing.T) { + t.Parallel() + + ctx := context.Background() + tests := []struct { + name string + address string + opID [32]byte + mockError error + want bool + wantErr error + }{ + { + name: "IsOperation success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + opID: [32]byte{0x01}, + want: true, + }, + { + name: "IsOperation call contract failure error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + opID: [32]byte{0x02}, + mockError: errors.New("call to contract failed"), + want: false, + wantErr: errors.New("tvm: failed to run get method \"isOperation\": call to contract failed"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + // Create a new mock client and inspector for each test case + client := ton_mocks.NewAPIClientWrapped(t) + inspector := mcmston.NewTimelockInspector(client) + + // Mock the contract call based on the test case + // Mock CurrentMasterchainInfo + client.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + if tt.mockError == nil { + // Encode the expected `IsOperation` return value for a successful call + wantInt := 0 + if tt.want { + wantInt = 1 + } + r := ton.NewExecutionResult([]any{big.NewInt(int64(wantInt))}) + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(r, nil).Once() + } else { + // If there's an error, mock it on the first CallContract call + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(nil, tt.mockError).Once() + } + + // Call the `IsOperation` method + got, err := inspector.IsOperation(ctx, tt.address, tt.opID) + + // Assertions for expected error or successful result + if tt.wantErr != nil { + require.Error(t, err) + require.EqualError(t, err, tt.wantErr.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tt.want, got) + } + + // Verify expectations + client.AssertExpectations(t) + }) + } +} + +// Helper function to test the various "IsOperation" states +func testIsOperationState( + t *testing.T, + methodName string, + addr string, + opID [32]byte, + want bool, + mockError error, + wantErr error, +) { + t.Helper() + + ctx := context.Background() + + // Create a new mock client and inspector for each test case + client := ton_mocks.NewAPIClientWrapped(t) + inspector := mcmston.NewTimelockInspector(client) + + // Mock the contract call based on the test case + // Mock CurrentMasterchainInfo + client.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + if mockError == nil { + // Encode the expected `IsOperation` return value for a successful call + wantInt := 0 + if want { + wantInt = 1 + } + r := ton.NewExecutionResult([]any{big.NewInt(int64(wantInt))}) + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(r, nil).Once() + } else { + // If there's an error, mock it on the first CallContract call + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(nil, mockError).Once() + } + + // Call the respective method based on methodName + var got bool + var err error + switch methodName { + case "isOperationPending": + got, err = inspector.IsOperationPending(ctx, addr, opID) + case "isOperationReady": + got, err = inspector.IsOperationReady(ctx, addr, opID) + case "isOperationDone": + got, err = inspector.IsOperationDone(ctx, addr, opID) + default: + t.Fatalf("unsupported methodName: %s", methodName) + } + + // Assertions for expected error or successful result + if wantErr != nil { + require.Error(t, err) + require.EqualError(t, err, wantErr.Error()) + } else { + require.NoError(t, err) + require.Equal(t, want, got) + } + + // Verify expectations + client.AssertExpectations(t) +} + +// Individual test functions calling the helper function with specific method names +func TestTimelockInspector_IsOperationPending(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + address string + opID [32]byte + want bool + mockError error + wantErr error + }{ + { + name: "IsOperationPending success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + opID: [32]byte{0x01}, + want: true, + }, + { + name: "IsOperationPending call contract failure error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + opID: [32]byte{0x02}, + mockError: errors.New("call to contract failed"), + want: false, + wantErr: errors.New("tvm: failed to run get method \"isOperationPending\": call to contract failed"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + testIsOperationState(t, "isOperationPending", tt.address, tt.opID, tt.want, tt.mockError, tt.wantErr) + }) + } +} + +func TestTimelockInspector_IsOperationReady(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + address string + opID [32]byte + want bool + mockError error + wantErr error + }{ + { + name: "IsOperationReady success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + opID: [32]byte{0x01}, + want: true, + }, + { + name: "IsOperationReady call contract failure error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + opID: [32]byte{0x02}, + mockError: errors.New("call to contract failed"), + want: false, + wantErr: errors.New("tvm: failed to run get method \"isOperationReady\": call to contract failed"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + testIsOperationState(t, "isOperationReady", tt.address, tt.opID, tt.want, tt.mockError, tt.wantErr) + }) + } +} + +func TestTimelockInspector_IsOperationDone(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + address string + opID [32]byte + want bool + mockError error + wantErr error + }{ + { + name: "IsOperationDone success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + opID: [32]byte{0x01}, + want: true, + }, + { + name: "IsOperationDone call contract failure error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + opID: [32]byte{0x02}, + mockError: errors.New("call to contract failed"), + want: false, + wantErr: errors.New("tvm: failed to run get method \"isOperationDone\": call to contract failed"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + testIsOperationState(t, "isOperationDone", tt.address, tt.opID, tt.want, tt.mockError, tt.wantErr) + }) + } +} + +func TestTimelockInspector_GetMinDelay(t *testing.T) { + t.Parallel() + + ctx := context.Background() + + tests := []struct { + name string + address string + minDelay *big.Int + mockError error + want uint64 + wantErr error + }{ + { + name: "GetMinDelay success", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + minDelay: big.NewInt(300), + want: 300, + }, + { + name: "GetMinDelay call contract failure error", + address: "EQADa3W6G0nSiTV4a6euRA42fU9QxSEnb-WeDpcrtWzA2jM8", + mockError: errors.New("call to contract failed"), + want: 0, + wantErr: errors.New("tvm: failed to run get method \"getMinDelay\": call to contract failed"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + // Create a new mock client and inspector for each test case + client := ton_mocks.NewAPIClientWrapped(t) + inspector := mcmston.NewTimelockInspector(client) + + // Mock CurrentMasterchainInfo + client.EXPECT().CurrentMasterchainInfo(mock.Anything). + Return(&ton.BlockIDExt{}, nil) + + if tt.mockError == nil { + // Encode the expected `getMinDelay` return value for a successful call + r := ton.NewExecutionResult([]any{tt.minDelay}) + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(r, nil).Once() + } else { + // Simulate a low-level call failure + client.EXPECT().RunGetMethod(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(nil, tt.mockError).Once() + } + + // Act + got, err := inspector.GetMinDelay(ctx, tt.address) + + // Assert + if tt.wantErr != nil { + require.Error(t, err) + require.EqualError(t, err, tt.wantErr.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tt.want, got) + } + + client.AssertExpectations(t) + }) + } +} diff --git a/sdk/ton/transaction.go b/sdk/ton/transaction.go new file mode 100644 index 000000000..7b9838560 --- /dev/null +++ b/sdk/ton/transaction.go @@ -0,0 +1,68 @@ +package ton + +import ( + "encoding/json" + "fmt" + "math/big" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/mcms/types" +) + +func ValidateAdditionalFields(additionalFields json.RawMessage) error { + fields := AdditionalFields{ + Value: big.NewInt(0), + } + if len(additionalFields) != 0 { + if err := json.Unmarshal(additionalFields, &fields); err != nil { + return fmt.Errorf("failed to unmarshal TON additional fields: %w", err) + } + } + + return fields.Validate() +} + +type AdditionalFields struct { + Value *big.Int `json:"value"` +} + +// Validate ensures the TON-specific fields are correct +func (f AdditionalFields) Validate() error { + if f.Value == nil || f.Value.Sign() < 0 { + return fmt.Errorf("invalid TON value: %v", f.Value) + } + + return nil +} + +// TODO: should use a generic type and an interface to define this (method to create generic types.Transaction from a specific type [S]) +func NewTransaction( + to *address.Address, + body *cell.Slice, + value *big.Int, + contractType string, + tags []string, +) (types.Transaction, error) { + additionalFields, err := json.Marshal(AdditionalFields{Value: value}) + if err != nil { + return types.Transaction{}, fmt.Errorf("failed to marshal additional fields: %w", err) + } + + bodyCell, err := body.ToCell() + if err != nil { + return types.Transaction{}, fmt.Errorf("failed to convert body to cell: %w", err) + } + data := bodyCell.ToBOC() + + return types.Transaction{ + To: to.String(), + Data: data, + AdditionalFields: additionalFields, + OperationMetadata: types.OperationMetadata{ + ContractType: contractType, + Tags: tags, + }, + }, nil +} diff --git a/sdk/ton/transaction_test.go b/sdk/ton/transaction_test.go new file mode 100644 index 000000000..5ec235a11 --- /dev/null +++ b/sdk/ton/transaction_test.go @@ -0,0 +1,107 @@ +package ton_test + +import ( + "encoding/json" + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/mcms/sdk/ton" +) + +func TestValidateAdditionalFields(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + input json.RawMessage + expectedErr bool + }{ + { + name: "empty json defaults to value 0", + input: json.RawMessage(""), + expectedErr: false, + }, + { + name: "valid json with missing value field", + input: json.RawMessage(`{}`), + expectedErr: false, + }, + { + name: "json with negative value", + input: json.RawMessage(`{"value": "-10"}`), + expectedErr: true, + }, + { + name: "json with null value", + input: json.RawMessage(`{"value": null}`), + expectedErr: true, + }, + { + name: "invalid json", + input: json.RawMessage(`{bad json}`), + expectedErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + err := ton.ValidateAdditionalFields(tt.input) + if tt.expectedErr { + assert.Error(t, err, "expected an error but got none") + } else { + assert.NoError(t, err, "expected no error but got one") + } + }) + } +} +func TestOperationFieldsValidate(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + value *big.Int + expectedErr bool + }{ + { + name: "valid positive value", + value: big.NewInt(100), + expectedErr: false, + }, + { + name: "valid zero value", + value: big.NewInt(0), + expectedErr: false, + }, + { + name: "nil value", + value: nil, + expectedErr: true, + }, + { + name: "negative value", + value: big.NewInt(-10), + expectedErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + op := ton.AdditionalFields{ + Value: tt.value, + } + + err := op.Validate() + + if tt.expectedErr { + assert.Error(t, err, "expected an error but got none") + } else { + assert.NoError(t, err, "expected no error but got one") + } + }) + } +} diff --git a/shell.nix b/shell.nix new file mode 100644 index 000000000..10c81556e --- /dev/null +++ b/shell.nix @@ -0,0 +1,56 @@ +{ + stdenv, + pkgs, + lib, + # smart contract pkgs to load + pkgsContracts, +}: +pkgs.mkShell { + buildInputs = with pkgs; + [ + # nix tooling + alejandra + + # Go 1.25 + tools + go_1_25 + gopls + delve + golangci-lint + gotools + go-mockery_2 + go-task # taskfile runner + + # Rust + tools + # rustc + # cargo + # solana-cli + + # TS/Node set of tools for changesets + nodejs_24 + (pnpm.override {nodejs = nodejs_24;}) + nodePackages.typescript + nodePackages.typescript-language-server + # Required dependency for @ledgerhq/hw-transport-node-hid -> usb + nodePackages.node-gyp + + # Extra tools + git + jq + yq-go # for manipulating golangci-lint config + go-task + ] + ++ builtins.attrValues pkgsContracts + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + libiconv + + # Required to support go build inside a nix devshell (c compiler dependency on SecTrustCopyCertificateChain/macOS 12+) + # https://github.com/NixOS/nixpkgs/issues/433688#issuecomment-3231551949 + pkgs.apple-sdk_15 + ]; + + PATH_CONTRACTS_TON = "${pkgsContracts.chainlink-ton-contracts}/lib/node_modules/@chainlink/contracts-ton/build/"; + + shellHook = '' + echo "TON contracts located here: $PATH_CONTRACTS_TON" + ''; +} diff --git a/signable_test.go b/signable_test.go index 831463a99..d3b8df919 100644 --- a/signable_test.go +++ b/signable_test.go @@ -979,7 +979,7 @@ func TestSignable_Simulate(t *testing.T) { } } -func TestSignable_ValidateConfigs(t *testing.T) { +func TestSignableValidateConfigs(t *testing.T) { t.Parallel() var ( diff --git a/taskfiles/test/Taskfile.yml b/taskfiles/test/Taskfile.yml index 8a0a50490..5289ec2b5 100644 --- a/taskfiles/test/Taskfile.yml +++ b/taskfiles/test/Taskfile.yml @@ -17,6 +17,11 @@ tasks: cmds: - go test -v {{.CLI_ARGS}} ./sdk/sui/... + unit:ton: + desc: "Run TON unit tests" + cmds: + - go test -v {{.CLI_ARGS}} ./sdk/ton/... + e2e: desc: "Run e2e tests" env: @@ -45,6 +50,13 @@ tasks: cmds: - CTF_CONFIGS=$CTF_CONFIGS go test -v -tags=e2e -test.run TestSuiSuite {{.CLI_ARGS}} ./e2e/tests... + e2e:ton: + desc: "Run Ton e2e tests" + env: + CTF_CONFIGS: '{{ .CTF_CONFIGS | default "../config.ton.toml" }}' + cmds: + - CTF_CONFIGS=$CTF_CONFIGS go test -v -tags=e2e -test.run TestTONSuite {{.CLI_ARGS}} ./e2e/tests... + coverage: desc: "Run unit test suite with coverage" cmds: diff --git a/types/chain_selector.go b/types/chain_selector.go index f99ab50eb..1bf0cdf0d 100644 --- a/types/chain_selector.go +++ b/types/chain_selector.go @@ -28,6 +28,7 @@ var supportedFamilies = []string{ cselectors.FamilySolana, cselectors.FamilyAptos, cselectors.FamilySui, + cselectors.FamilyTon, } // GetChainSelectorFamily returns the family of the chain selector. diff --git a/types/config_test.go b/types/config_test.go index 9b5d97b0b..568a33afa 100644 --- a/types/config_test.go +++ b/types/config_test.go @@ -41,7 +41,7 @@ func TestNewConfig(t *testing.T) { assert.Equal(t, Config{}, got) } -func TestConfig_Validate(t *testing.T) { +func TestConfigValidate(t *testing.T) { t.Parallel() tests := []struct { diff --git a/validation.go b/validation.go index e8fe35076..f5355bcdc 100644 --- a/validation.go +++ b/validation.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/sdk/solana" "github.com/smartcontractkit/mcms/sdk/sui" + "github.com/smartcontractkit/mcms/sdk/ton" ) func validateAdditionalFields(additionalFields json.RawMessage, csel types.ChainSelector) error { @@ -32,6 +33,9 @@ func validateAdditionalFields(additionalFields json.RawMessage, csel types.Chain case cselectors.FamilySui: return sui.ValidateAdditionalFields(additionalFields) + + case cselectors.FamilyTon: + return ton.ValidateAdditionalFields(additionalFields) } return nil @@ -53,6 +57,10 @@ func validateChainMetadata(metadata types.ChainMetadata, csel types.ChainSelecto return nil case cselectors.FamilySui: return sui.ValidateChainMetadata(metadata) + case cselectors.FamilyTon: + // TODO (ton): do we need special chain metadata for TON? + // Yes! We could attach MCMS -> Timelock value here which is now hardcoded default in timelock converter + return nil default: return fmt.Errorf("unsupported chain family: %s", chainFamily) } From 9b4bf1634a419dd43ed6dc9e89af84db86ff4fa6 Mon Sep 17 00:00:00 2001 From: Pablo Date: Thu, 15 Jan 2026 18:23:29 -0600 Subject: [PATCH 17/26] fix: linting errors Signed-off-by: Pablo --- .tool-versions | 2 +- chainsmetadata/sui_helpers_test.go | 1 - inspectors/inspectors.go | 4 ++++ sdk/evm/utils.go | 3 --- signable_test.go | 2 +- timelock_proposal_test.go | 9 +++++++-- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.tool-versions b/.tool-versions index d480b4036..67912758f 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/sui_helpers_test.go b/chainsmetadata/sui_helpers_test.go index 1df4d45cd..a1ba92483 100644 --- a/chainsmetadata/sui_helpers_test.go +++ b/chainsmetadata/sui_helpers_test.go @@ -54,7 +54,6 @@ func TestSuiMetadata(t *testing.T) { } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { t.Parallel() diff --git a/inspectors/inspectors.go b/inspectors/inspectors.go index 33f0b0f87..07f906a0e 100644 --- a/inspectors/inspectors.go +++ b/inspectors/inspectors.go @@ -67,12 +67,14 @@ func BuildInspector( 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) @@ -83,6 +85,7 @@ func BuildInspector( 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.Sui(rawSelector) @@ -93,6 +96,7 @@ func BuildInspector( 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/sdk/evm/utils.go b/sdk/evm/utils.go index 2fb0928a2..e024e449b 100644 --- a/sdk/evm/utils.go +++ b/sdk/evm/utils.go @@ -6,9 +6,6 @@ import ( 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" ) diff --git a/signable_test.go b/signable_test.go index d3b8df919..4c1b8501a 100644 --- a/signable_test.go +++ b/signable_test.go @@ -460,7 +460,7 @@ func TestSignable_SingleChainMultipleSignerMultipleTX_FailureMissingQuorum(t *te // Validate the signatures quorumMet, err := signable.ValidateSignatures(ctx) require.Error(t, err) - //nolint:testifylint // Allow IsType for error type checking + require.IsType(t, &QuorumNotReachedError{}, err) require.False(t, quorumMet) } diff --git a/timelock_proposal_test.go b/timelock_proposal_test.go index 41f0739ad..25458ada9 100644 --- a/timelock_proposal_test.go +++ b/timelock_proposal_test.go @@ -20,7 +20,7 @@ import ( "github.com/smartcontractkit/mcms/internal/testutils/chaintest" "github.com/smartcontractkit/mcms/sdk" - mocks "github.com/smartcontractkit/mcms/sdk/mocks" + "github.com/smartcontractkit/mcms/sdk/mocks" "github.com/smartcontractkit/mcms/sdk/solana" evmsdk "github.com/smartcontractkit/mcms/sdk/evm" @@ -333,11 +333,14 @@ func TestTimelockProposal_GetOpCount(t *testing.T) { 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, @@ -360,6 +363,8 @@ func TestTimelockProposal_GetOpCount(t *testing.T) { Action: types.TimelockActionSchedule, }, setupMock: func(t *testing.T) (sdk.Inspector, error) { + t.Helper() + return nil, errors.New("factory boom") }, expectErr: "factory boom", @@ -367,7 +372,6 @@ func TestTimelockProposal_GetOpCount(t *testing.T) { } for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { t.Parallel() @@ -381,6 +385,7 @@ func TestTimelockProposal_GetOpCount(t *testing.T) { GetOpCount(mock.Anything, metadata.MCMAddress). Return(uint64(1), nil). Once() + return defaultInspector, nil } t.Cleanup(func() { From fed18c7bbbf37b8d00a20a50b0336b21351005f4 Mon Sep 17 00:00:00 2001 From: Pablo Date: Thu, 15 Jan 2026 21:47:44 -0600 Subject: [PATCH 18/26] fix: refactor inspector API and converter for consistency Signed-off-by: Pablo --- converters/converters.go | 4 ++-- inspectors/inspectors.go | 21 ++++----------------- inspectors/inspectors_test.go | 4 +--- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/converters/converters.go b/converters/converters.go index 968db1404..5f0af5b4d 100644 --- a/converters/converters.go +++ b/converters/converters.go @@ -13,8 +13,8 @@ import ( "github.com/smartcontractkit/mcms/types" ) -// BuildConvertersForTimelockProposal constructs a map of chain selectors to their respective timelock converters based on the provided timelock proposal. -func BuildConvertersForTimelockProposal(proposal mcms.TimelockProposal) (map[types.ChainSelector]sdk.TimelockConverter, error) { +// 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) diff --git a/inspectors/inspectors.go b/inspectors/inspectors.go index 07f906a0e..2fdcd42e4 100644 --- a/inspectors/inspectors.go +++ b/inspectors/inspectors.go @@ -14,27 +14,14 @@ import ( "github.com/smartcontractkit/mcms/types" ) -type InspectorFetcher interface { - FetchInspectors(chainMetadata map[types.ChainSelector]types.ChainMetadata, action types.TimelockAction) (map[types.ChainSelector]sdk.Inspector, error) -} - -var _ InspectorFetcher = (*MCMInspectorFetcher)(nil) - -type MCMInspectorFetcher struct { - chains sdk.ChainAccess -} - -func NewMCMInspectorFetcher(chains sdk.ChainAccess) *MCMInspectorFetcher { - return &MCMInspectorFetcher{chains: chains} -} - -// FetchInspectors gets a map of inspectors for the given chain metadata and chain clients -func (b *MCMInspectorFetcher) FetchInspectors( +// 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(b.chains, chainSelector, action, metadata) + inspector, err := BuildInspector(chains, chainSelector, action, metadata) if err != nil { return nil, err } diff --git a/inspectors/inspectors_test.go b/inspectors/inspectors_test.go index 861c89c45..465bc2e33 100644 --- a/inspectors/inspectors_test.go +++ b/inspectors/inspectors_test.go @@ -68,9 +68,7 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { if tc.chainAccess == nil { tc.chainAccess = &fakeChainAccess{} } - - builder := NewMCMInspectorFetcher(tc.chainAccess) - inspectors, err := builder.FetchInspectors(tc.chainMetadata, mcmsTypes.TimelockActionSchedule) + inspectors, err := BuildInspectors(tc.chainMetadata, mcmsTypes.TimelockActionSchedule) if tc.expectErr { require.Error(t, err) require.Contains(t, err.Error(), tc.errContains) From 44991a9a88162f065b7aab1551f372f5b050c816 Mon Sep 17 00:00:00 2001 From: Pablo Date: Thu, 15 Jan 2026 21:57:40 -0600 Subject: [PATCH 19/26] fix: refactor inspector SUI client name and fix unit tests Signed-off-by: Pablo --- inspectors/inspectors.go | 2 +- inspectors/inspectors_test.go | 99 ++++++----------------------------- sdk/chainclient.go | 2 +- sdk/evm/utils.go | 1 + sdk/mocks/chain_access.go | 22 ++++---- 5 files changed, 31 insertions(+), 95 deletions(-) diff --git a/inspectors/inspectors.go b/inspectors/inspectors.go index 2fdcd42e4..4ca068987 100644 --- a/inspectors/inspectors.go +++ b/inspectors/inspectors.go @@ -75,7 +75,7 @@ func BuildInspector( return aptos.NewInspector(client, role), nil case chainsel.FamilySui: - client, signer, ok := chains.Sui(rawSelector) + client, signer, ok := chains.SuiClient(rawSelector) if !ok { return nil, fmt.Errorf("missing Sui chain client for selector %d", rawSelector) } diff --git a/inspectors/inspectors_test.go b/inspectors/inspectors_test.go index 465bc2e33..12135db01 100644 --- a/inspectors/inspectors_test.go +++ b/inspectors/inspectors_test.go @@ -3,13 +3,11 @@ package inspectors import ( "testing" - aptoslib "github.com/aptos-labs/aptos-go-sdk" - "github.com/block-vision/sui-go-sdk/sui" - solrpc "github.com/gagliardetto/solana-go/rpc" chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/mcms/sdk" + "github.com/smartcontractkit/mcms/sdk/mocks" mcmsTypes "github.com/smartcontractkit/mcms/types" ) @@ -19,7 +17,8 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { tests := []struct { name string chainMetadata map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata - chainAccess sdk.ChainAccess + chainAccess *mocks.ChainAccess + setup func(access *mocks.ChainAccess) expectErr bool errContains string expectedInspectorsCount int @@ -27,7 +26,7 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { { name: "empty input", chainMetadata: map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata{}, - chainAccess: &fakeChainAccess{}, + chainAccess: mocks.NewChainAccess(t), expectErr: false, }, { @@ -35,7 +34,7 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { chainMetadata: map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata{ 1: {MCMAddress: "0xabc", StartingOpCount: 0}, }, - chainAccess: &fakeChainAccess{}, + chainAccess: mocks.NewChainAccess(t), expectErr: true, errContains: "error getting chain family: chain family not found for selector 1", }, @@ -45,19 +44,12 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { mcmsTypes.ChainSelector(chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector): {MCMAddress: "0xabc", StartingOpCount: 0}, mcmsTypes.ChainSelector(chainsel.SOLANA_DEVNET.Selector): {MCMAddress: "0xabc", StartingOpCount: 0}, }, - chainAccess: &fakeChainAccess{ - selectors: []uint64{ - chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector, - chainsel.SOLANA_DEVNET.Selector, - }, - evmClients: map[uint64]sdk.ContractDeployBackend{ - chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector: nil, - }, - solanaClients: map[uint64]*solrpc.Client{ - chainsel.SOLANA_DEVNET.Selector: nil, - }, + 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) }, - expectErr: false, expectedInspectorsCount: 2, }, } @@ -66,9 +58,13 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() if tc.chainAccess == nil { - tc.chainAccess = &fakeChainAccess{} + tc.chainAccess = mocks.NewChainAccess(t) } - inspectors, err := BuildInspectors(tc.chainMetadata, mcmsTypes.TimelockActionSchedule) + 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) @@ -79,64 +75,3 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { }) } } - -type fakeChainAccess struct { - selectors []uint64 - evmClients map[uint64]sdk.ContractDeployBackend - solanaClients map[uint64]*solrpc.Client - aptosClients map[uint64]aptoslib.AptosRpcClient - suiClients map[uint64]struct { - client sui.ISuiAPI - signer sdk.SuiSigner - } -} - -var _ sdk.ChainAccess = (*fakeChainAccess)(nil) - -func (f *fakeChainAccess) Selectors() []uint64 { - if f == nil { - return nil - } - - return f.selectors -} - -func (f *fakeChainAccess) EVMClient(selector uint64) (sdk.ContractDeployBackend, bool) { - if f == nil || f.evmClients == nil { - return nil, false - } - client, ok := f.evmClients[selector] - - return client, ok -} - -func (f *fakeChainAccess) SolanaClient(selector uint64) (*solrpc.Client, bool) { - if f == nil || f.solanaClients == nil { - return nil, false - } - client, ok := f.solanaClients[selector] - - return client, ok -} - -func (f *fakeChainAccess) AptosClient(selector uint64) (aptoslib.AptosRpcClient, bool) { - if f == nil || f.aptosClients == nil { - var zero aptoslib.AptosRpcClient - return zero, false - } - client, ok := f.aptosClients[selector] - - return client, ok -} - -func (f *fakeChainAccess) Sui(selector uint64) (sui.ISuiAPI, sdk.SuiSigner, bool) { - if f == nil || f.suiClients == nil { - return nil, nil, false - } - client, ok := f.suiClients[selector] - if !ok { - return nil, nil, false - } - - return client.client, client.signer, true -} diff --git a/sdk/chainclient.go b/sdk/chainclient.go index 9bce514df..2568bce47 100644 --- a/sdk/chainclient.go +++ b/sdk/chainclient.go @@ -26,5 +26,5 @@ type ChainAccess interface { EVMClient(selector uint64) (ContractDeployBackend, bool) SolanaClient(selector uint64) (*solrpc.Client, bool) AptosClient(selector uint64) (aptoslib.AptosRpcClient, bool) - Sui(selector uint64) (sui.ISuiAPI, SuiSigner, bool) + SuiClient(selector uint64) (sui.ISuiAPI, SuiSigner, bool) } diff --git a/sdk/evm/utils.go b/sdk/evm/utils.go index e024e449b..339484010 100644 --- a/sdk/evm/utils.go +++ b/sdk/evm/utils.go @@ -1,6 +1,7 @@ package evm import ( + "github.com/ethereum/go-ethereum/common" cselectors "github.com/smartcontractkit/chain-selectors" sdkerrors "github.com/smartcontractkit/mcms/sdk/errors" diff --git a/sdk/mocks/chain_access.go b/sdk/mocks/chain_access.go index c3906142d..31a49a19c 100644 --- a/sdk/mocks/chain_access.go +++ b/sdk/mocks/chain_access.go @@ -247,12 +247,12 @@ func (_c *ChainAccess_SolanaClient_Call) RunAndReturn(run func(uint64) (*rpc.Cli return _c } -// Sui provides a mock function with given fields: selector -func (_m *ChainAccess) Sui(selector uint64) (sui.ISuiAPI, sdk.SuiSigner, bool) { +// 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 Sui") + panic("no return value specified for SuiClient") } var r0 sui.ISuiAPI @@ -286,30 +286,30 @@ func (_m *ChainAccess) Sui(selector uint64) (sui.ISuiAPI, sdk.SuiSigner, bool) { return r0, r1, r2 } -// ChainAccess_Sui_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Sui' -type ChainAccess_Sui_Call struct { +// 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 } -// Sui is a helper method to define mock.On call +// SuiClient is a helper method to define mock.On call // - selector uint64 -func (_e *ChainAccess_Expecter) Sui(selector interface{}) *ChainAccess_Sui_Call { - return &ChainAccess_Sui_Call{Call: _e.mock.On("Sui", selector)} +func (_e *ChainAccess_Expecter) SuiClient(selector interface{}) *ChainAccess_SuiClient_Call { + return &ChainAccess_SuiClient_Call{Call: _e.mock.On("SuiClient", selector)} } -func (_c *ChainAccess_Sui_Call) Run(run func(selector uint64)) *ChainAccess_Sui_Call { +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_Sui_Call) Return(_a0 sui.ISuiAPI, _a1 sdk.SuiSigner, _a2 bool) *ChainAccess_Sui_Call { +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_Sui_Call) RunAndReturn(run func(uint64) (sui.ISuiAPI, sdk.SuiSigner, bool)) *ChainAccess_Sui_Call { +func (_c *ChainAccess_SuiClient_Call) RunAndReturn(run func(uint64) (sui.ISuiAPI, sdk.SuiSigner, bool)) *ChainAccess_SuiClient_Call { _c.Call.Return(run) return _c } From a5ef8221ac19b1f277c24dce4d084c03318255bd Mon Sep 17 00:00:00 2001 From: Pablo Date: Fri, 16 Jan 2026 08:53:02 -0600 Subject: [PATCH 20/26] fix: refactor to have a chainaccess pkg with inspectors, converters and interfaces in it. Signed-off-by: Pablo --- .mockery.yaml | 2 +- chainaccess/chainaccess.go | 18 ++++ {converters => chainaccess}/converters.go | 7 +- chainaccess/converters_test.go | 75 +++++++++++++ {inspectors => chainaccess}/inspectors.go | 11 +- .../inspectors_test.go | 4 +- {sdk => chainaccess}/mocks/chain_access.go | 33 +++--- chainsmetadata/aptos_helpers.go | 21 ---- chainsmetadata/sui_helpers.go | 24 ----- inspectors/mocks/inspector_fetcher.go | 96 ----------------- sdk/aptos/aptos_helpers.go | 20 ++++ .../aptos}/aptos_helpers_test.go | 11 +- sdk/aptos/configurer.go | 3 +- sdk/chainclient.go | 30 ------ sdk/confighelpers.go | 102 ++++++++++++++++++ sdk/evm/config_transformer.go | 96 +---------------- sdk/evm/configurer.go | 6 +- sdk/evm/execution_error.go | 5 +- sdk/evm/execution_error_test.go | 3 +- sdk/evm/executor.go | 3 +- sdk/evm/inspector.go | 4 +- sdk/evm/simulator.go | 3 +- sdk/evm/simulator_test.go | 3 +- sdk/evm/timelock_executor.go | 4 +- sdk/evm/timelock_inspector.go | 4 +- sdk/evm/utils.go | 6 ++ sdk/solana/config_transformer.go | 5 +- sdk/solana/configurer.go | 4 +- sdk/sui/configurer.go | 3 +- sdk/sui/sui_helpers.go | 23 ++++ .../sui}/sui_helpers_test.go | 7 +- sdk/sui/utils.go | 9 ++ sdk/ton/config_transformer.go | 2 +- sdk/ton/configurer.go | 4 +- signable_test.go | 2 +- timelock_proposal.go | 8 +- timelock_proposal_test.go | 3 +- 37 files changed, 323 insertions(+), 341 deletions(-) create mode 100644 chainaccess/chainaccess.go rename {converters => chainaccess}/converters.go (82%) create mode 100644 chainaccess/converters_test.go rename {inspectors => chainaccess}/inspectors.go (91%) rename {inspectors => chainaccess}/inspectors_test.go (96%) rename {sdk => chainaccess}/mocks/chain_access.go (90%) delete mode 100644 chainsmetadata/aptos_helpers.go delete mode 100644 chainsmetadata/sui_helpers.go delete mode 100644 inspectors/mocks/inspector_fetcher.go create mode 100644 sdk/aptos/aptos_helpers.go rename {chainsmetadata => sdk/aptos}/aptos_helpers_test.go (84%) delete mode 100644 sdk/chainclient.go create mode 100644 sdk/confighelpers.go create mode 100644 sdk/sui/sui_helpers.go rename {chainsmetadata => sdk/sui}/sui_helpers_test.go (90%) diff --git a/.mockery.yaml b/.mockery.yaml index 6614b1716..6d096eb16 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -32,7 +32,7 @@ packages: config: dir: "./sdk/ton/mocks" filename: "api.go" - github.com/smartcontractkit/mcms/inspectors: + github.com/smartcontractkit/mcms/chainaccess: github.com/smartcontractkit/mcms/sdk: github.com/smartcontractkit/mcms/sdk/evm: github.com/smartcontractkit/mcms/sdk/evm/bindings: diff --git a/chainaccess/chainaccess.go b/chainaccess/chainaccess.go new file mode 100644 index 000000000..c19f1f403 --- /dev/null +++ b/chainaccess/chainaccess.go @@ -0,0 +1,18 @@ +package chainaccess + +import ( + aptoslib "github.com/aptos-labs/aptos-go-sdk" + "github.com/block-vision/sui-go-sdk/sui" + solrpc "github.com/gagliardetto/solana-go/rpc" + + evmsdk "github.com/smartcontractkit/mcms/sdk/evm" + suisuisdk "github.com/smartcontractkit/mcms/sdk/sui" +) + +type ChainAccess interface { + Selectors() []uint64 + EVMClient(selector uint64) (evmsdk.ContractDeployBackend, bool) + SolanaClient(selector uint64) (*solrpc.Client, bool) + AptosClient(selector uint64) (aptoslib.AptosRpcClient, bool) + SuiClient(selector uint64) (sui.ISuiAPI, suisuisdk.SuiSigner, bool) +} diff --git a/converters/converters.go b/chainaccess/converters.go similarity index 82% rename from converters/converters.go rename to chainaccess/converters.go index 5f0af5b4d..567494998 100644 --- a/converters/converters.go +++ b/chainaccess/converters.go @@ -1,11 +1,10 @@ -package proposalutils +package chainaccess 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" @@ -14,9 +13,9 @@ import ( ) // 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) { +func BuildConverters(chainMetadata map[types.ChainSelector]types.ChainMetadata) (map[types.ChainSelector]sdk.TimelockConverter, error) { converters := make(map[types.ChainSelector]sdk.TimelockConverter) - for chainMeta := range proposal.ChainMetadata { + for chainMeta := range chainMetadata { fam, err := types.GetChainSelectorFamily(chainMeta) if err != nil { return nil, fmt.Errorf("error getting chain family: %w", err) diff --git a/chainaccess/converters_test.go b/chainaccess/converters_test.go new file mode 100644 index 000000000..d607aca39 --- /dev/null +++ b/chainaccess/converters_test.go @@ -0,0 +1,75 @@ +package chainaccess + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/mcms/internal/testutils/chaintest" + "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/sdk/evm" + "github.com/smartcontractkit/mcms/sdk/solana" + "github.com/smartcontractkit/mcms/types" +) + +func TestBuildConverters(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + metadata map[types.ChainSelector]types.ChainMetadata + expectTypes map[types.ChainSelector]any + expectErr string + }{ + { + name: "supported families", + metadata: map[types.ChainSelector]types.ChainMetadata{ + chaintest.Chain2Selector: {}, + chaintest.Chain4Selector: {}, + chaintest.Chain5Selector: {}, + }, + expectTypes: map[types.ChainSelector]any{ + chaintest.Chain2Selector: (*evm.TimelockConverter)(nil), + chaintest.Chain4Selector: (*solana.TimelockConverter)(nil), + chaintest.Chain5Selector: (*aptos.TimelockConverter)(nil), + }, + }, + { + name: "unsupported family", + metadata: map[types.ChainSelector]types.ChainMetadata{ + chaintest.Chain6Selector: {}, + }, + expectErr: "unsupported chain family", + }, + { + name: "invalid selector", + metadata: map[types.ChainSelector]types.ChainMetadata{ + chaintest.ChainInvalidSelector: {}, + }, + expectErr: "error getting chain family", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + converters, err := BuildConverters(tc.metadata) + + if tc.expectErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectErr) + + return + } + + require.NoError(t, err) + require.Len(t, converters, len(tc.expectTypes)) + for selector, expectedType := range tc.expectTypes { + converter, ok := converters[selector] + require.True(t, ok) + require.IsType(t, expectedType, converter) + } + }) + } +} diff --git a/inspectors/inspectors.go b/chainaccess/inspectors.go similarity index 91% rename from inspectors/inspectors.go rename to chainaccess/inspectors.go index 4ca068987..dc70b7a81 100644 --- a/inspectors/inspectors.go +++ b/chainaccess/inspectors.go @@ -1,11 +1,10 @@ -package inspectors +package chainaccess 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" @@ -16,7 +15,7 @@ import ( // BuildInspectors gets a map of inspectors for the given chain metadata and chain clients func BuildInspectors( - chains sdk.ChainAccess, + chains ChainAccess, chainMetadata map[types.ChainSelector]types.ChainMetadata, action types.TimelockAction) (map[types.ChainSelector]sdk.Inspector, error) { inspectors := map[types.ChainSelector]sdk.Inspector{} @@ -33,7 +32,7 @@ func BuildInspectors( // BuildInspector constructs a chain-family-specific Inspector from ChainAccess plus metadata. func BuildInspector( - chains sdk.ChainAccess, + chains ChainAccess, selector types.ChainSelector, action types.TimelockAction, metadata types.ChainMetadata, @@ -68,7 +67,7 @@ func BuildInspector( if !ok { return nil, fmt.Errorf("missing Aptos chain client for selector %d", rawSelector) } - role, err := chainsmetadata.AptosRoleFromAction(action) + role, err := aptos.AptosRoleFromAction(action) if err != nil { return nil, fmt.Errorf("error determining aptos role: %w", err) } @@ -79,7 +78,7 @@ func BuildInspector( if !ok { return nil, fmt.Errorf("missing Sui chain client for selector %d", rawSelector) } - suiMetadata, err := chainsmetadata.SuiMetadata(metadata) + suiMetadata, err := sdkSui.SuiMetadata(metadata) if err != nil { return nil, fmt.Errorf("error parsing sui metadata: %w", err) } diff --git a/inspectors/inspectors_test.go b/chainaccess/inspectors_test.go similarity index 96% rename from inspectors/inspectors_test.go rename to chainaccess/inspectors_test.go index 12135db01..f7abbe24c 100644 --- a/inspectors/inspectors_test.go +++ b/chainaccess/inspectors_test.go @@ -1,4 +1,4 @@ -package inspectors +package chainaccess import ( "testing" @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/mcms/sdk/mocks" + "github.com/smartcontractkit/mcms/chainaccess/mocks" mcmsTypes "github.com/smartcontractkit/mcms/types" ) diff --git a/sdk/mocks/chain_access.go b/chainaccess/mocks/chain_access.go similarity index 90% rename from sdk/mocks/chain_access.go rename to chainaccess/mocks/chain_access.go index 31a49a19c..521b827c0 100644 --- a/sdk/mocks/chain_access.go +++ b/chainaccess/mocks/chain_access.go @@ -4,11 +4,14 @@ package mocks import ( aptos "github.com/aptos-labs/aptos-go-sdk" + + evm "github.com/smartcontractkit/mcms/sdk/evm" + mock "github.com/stretchr/testify/mock" rpc "github.com/gagliardetto/solana-go/rpc" - sdk "github.com/smartcontractkit/mcms/sdk" + sdksui "github.com/smartcontractkit/mcms/sdk/sui" sui "github.com/block-vision/sui-go-sdk/sui" ) @@ -85,23 +88,23 @@ func (_c *ChainAccess_AptosClient_Call) RunAndReturn(run func(uint64) (aptos.Apt } // EVMClient provides a mock function with given fields: selector -func (_m *ChainAccess) EVMClient(selector uint64) (sdk.ContractDeployBackend, bool) { +func (_m *ChainAccess) EVMClient(selector uint64) (evm.ContractDeployBackend, bool) { ret := _m.Called(selector) if len(ret) == 0 { panic("no return value specified for EVMClient") } - var r0 sdk.ContractDeployBackend + var r0 evm.ContractDeployBackend var r1 bool - if rf, ok := ret.Get(0).(func(uint64) (sdk.ContractDeployBackend, bool)); ok { + if rf, ok := ret.Get(0).(func(uint64) (evm.ContractDeployBackend, bool)); ok { return rf(selector) } - if rf, ok := ret.Get(0).(func(uint64) sdk.ContractDeployBackend); ok { + if rf, ok := ret.Get(0).(func(uint64) evm.ContractDeployBackend); ok { r0 = rf(selector) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(sdk.ContractDeployBackend) + r0 = ret.Get(0).(evm.ContractDeployBackend) } } @@ -132,12 +135,12 @@ func (_c *ChainAccess_EVMClient_Call) Run(run func(selector uint64)) *ChainAcces return _c } -func (_c *ChainAccess_EVMClient_Call) Return(_a0 sdk.ContractDeployBackend, _a1 bool) *ChainAccess_EVMClient_Call { +func (_c *ChainAccess_EVMClient_Call) Return(_a0 evm.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 { +func (_c *ChainAccess_EVMClient_Call) RunAndReturn(run func(uint64) (evm.ContractDeployBackend, bool)) *ChainAccess_EVMClient_Call { _c.Call.Return(run) return _c } @@ -248,7 +251,7 @@ func (_c *ChainAccess_SolanaClient_Call) RunAndReturn(run func(uint64) (*rpc.Cli } // SuiClient provides a mock function with given fields: selector -func (_m *ChainAccess) SuiClient(selector uint64) (sui.ISuiAPI, sdk.SuiSigner, bool) { +func (_m *ChainAccess) SuiClient(selector uint64) (sui.ISuiAPI, sdksui.SuiSigner, bool) { ret := _m.Called(selector) if len(ret) == 0 { @@ -256,9 +259,9 @@ func (_m *ChainAccess) SuiClient(selector uint64) (sui.ISuiAPI, sdk.SuiSigner, b } var r0 sui.ISuiAPI - var r1 sdk.SuiSigner + var r1 sdksui.SuiSigner var r2 bool - if rf, ok := ret.Get(0).(func(uint64) (sui.ISuiAPI, sdk.SuiSigner, bool)); ok { + if rf, ok := ret.Get(0).(func(uint64) (sui.ISuiAPI, sdksui.SuiSigner, bool)); ok { return rf(selector) } if rf, ok := ret.Get(0).(func(uint64) sui.ISuiAPI); ok { @@ -269,11 +272,11 @@ func (_m *ChainAccess) SuiClient(selector uint64) (sui.ISuiAPI, sdk.SuiSigner, b } } - if rf, ok := ret.Get(1).(func(uint64) sdk.SuiSigner); ok { + if rf, ok := ret.Get(1).(func(uint64) sdksui.SuiSigner); ok { r1 = rf(selector) } else { if ret.Get(1) != nil { - r1 = ret.Get(1).(sdk.SuiSigner) + r1 = ret.Get(1).(sdksui.SuiSigner) } } @@ -304,12 +307,12 @@ func (_c *ChainAccess_SuiClient_Call) Run(run func(selector uint64)) *ChainAcces return _c } -func (_c *ChainAccess_SuiClient_Call) Return(_a0 sui.ISuiAPI, _a1 sdk.SuiSigner, _a2 bool) *ChainAccess_SuiClient_Call { +func (_c *ChainAccess_SuiClient_Call) Return(_a0 sui.ISuiAPI, _a1 sdksui.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 { +func (_c *ChainAccess_SuiClient_Call) RunAndReturn(run func(uint64) (sui.ISuiAPI, sdksui.SuiSigner, bool)) *ChainAccess_SuiClient_Call { _c.Call.Return(run) return _c } diff --git a/chainsmetadata/aptos_helpers.go b/chainsmetadata/aptos_helpers.go deleted file mode 100644 index 8b337e48e..000000000 --- a/chainsmetadata/aptos_helpers.go +++ /dev/null @@ -1,21 +0,0 @@ -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/sui_helpers.go b/chainsmetadata/sui_helpers.go deleted file mode 100644 index b4d214675..000000000 --- a/chainsmetadata/sui_helpers.go +++ /dev/null @@ -1,24 +0,0 @@ -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/inspectors/mocks/inspector_fetcher.go b/inspectors/mocks/inspector_fetcher.go deleted file mode 100644 index 59ceff298..000000000 --- a/inspectors/mocks/inspector_fetcher.go +++ /dev/null @@ -1,96 +0,0 @@ -// 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/aptos/aptos_helpers.go b/sdk/aptos/aptos_helpers.go new file mode 100644 index 000000000..5757a6d21 --- /dev/null +++ b/sdk/aptos/aptos_helpers.go @@ -0,0 +1,20 @@ +package aptos + +import ( + "errors" + + "github.com/smartcontractkit/mcms/types" +) + +func AptosRoleFromAction(action types.TimelockAction) (TimelockRole, error) { + switch action { + case types.TimelockActionBypass: + return TimelockRoleBypasser, nil + case types.TimelockActionSchedule: + return TimelockRoleProposer, nil + case types.TimelockActionCancel: + return TimelockRoleCanceller, nil + default: + return 0, errors.New("unknown timelock action") + } +} diff --git a/chainsmetadata/aptos_helpers_test.go b/sdk/aptos/aptos_helpers_test.go similarity index 84% rename from chainsmetadata/aptos_helpers_test.go rename to sdk/aptos/aptos_helpers_test.go index eb20466a3..8542d7706 100644 --- a/chainsmetadata/aptos_helpers_test.go +++ b/sdk/aptos/aptos_helpers_test.go @@ -1,4 +1,4 @@ -package chainsmetadata +package aptos import ( "testing" @@ -6,7 +6,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/mcms/sdk/aptos" mcmsTypes "github.com/smartcontractkit/mcms/types" ) @@ -16,25 +15,25 @@ func TestAptosRoleFromAction(t *testing.T) { tests := []struct { name string action mcmsTypes.TimelockAction - expectedRole aptos.TimelockRole + expectedRole TimelockRole expectError bool }{ { name: "bypass action returns bypasser role", action: mcmsTypes.TimelockActionBypass, - expectedRole: aptos.TimelockRoleBypasser, + expectedRole: TimelockRoleBypasser, expectError: false, }, { name: "schedule action returns proposer role", action: mcmsTypes.TimelockActionSchedule, - expectedRole: aptos.TimelockRoleProposer, + expectedRole: TimelockRoleProposer, expectError: false, }, { name: "cancel action returns canceller role", action: mcmsTypes.TimelockActionCancel, - expectedRole: aptos.TimelockRoleCanceller, + expectedRole: TimelockRoleCanceller, expectError: false, }, { diff --git a/sdk/aptos/configurer.go b/sdk/aptos/configurer.go index b54c5a39c..46d6e3e48 100644 --- a/sdk/aptos/configurer.go +++ b/sdk/aptos/configurer.go @@ -12,7 +12,6 @@ import ( "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/types" ) @@ -68,7 +67,7 @@ func (c Configurer) SetConfig(ctx context.Context, mcmsAddr string, cfg *types.C mcmsBinding := c.bindingFn(mcmsAddress, c.client) opts := &bind.TransactOpts{Signer: c.auth} - groupQuorum, groupParents, signerAddresses, signerGroups, err := evm.ExtractSetConfigInputs(cfg) + groupQuorum, groupParents, signerAddresses, signerGroups, err := sdk.ExtractSetConfigInputs(cfg) if err != nil { return types.TransactionResult{}, fmt.Errorf("unable to extract set config inputs: %w", err) } diff --git a/sdk/chainclient.go b/sdk/chainclient.go deleted file mode 100644 index 2568bce47..000000000 --- a/sdk/chainclient.go +++ /dev/null @@ -1,30 +0,0 @@ -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/confighelpers.go b/sdk/confighelpers.go new file mode 100644 index 000000000..750768351 --- /dev/null +++ b/sdk/confighelpers.go @@ -0,0 +1,102 @@ +package sdk + +import ( + "fmt" + "math/big" + "slices" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/mcms/internal/utils/safecast" + "github.com/smartcontractkit/mcms/sdk/evm/bindings" + "github.com/smartcontractkit/mcms/types" +) + +// ExtractSetConfigInputs flattens a nested `*types.Config` into: +// 1. groupQuorums: [32]uint8 where each index i holds the quorum for group i (zero-padded). +// 2. groupParents: [32]uint8 where each index i holds the parent group’s index (or a sentinel). +// 3. orderedSignerAddresses: a sorted slice of all signer addresses. +// 4. orderedSignerGroups: a parallel slice of group indices for each signer. +// +// Returns an error if the structure cannot be flattened (e.g., too many groups). +func ExtractSetConfigInputs( + group *types.Config, +) ([32]uint8, [32]uint8, []common.Address, []uint8, error) { + var groupQuorums, groupParents, signerGroups = []uint8{}, []uint8{}, []uint8{} + var signerAddrs = []common.Address{} + + err := extractGroupsAndSigners(group, 0, &groupQuorums, &groupParents, &signerAddrs, &signerGroups) + if err != nil { + return [32]uint8{}, [32]uint8{}, []common.Address{}, []uint8{}, err + } + + // fill the rest of the arrays with 0s + for i := len(groupQuorums); i < 32; i++ { + groupQuorums = append(groupQuorums, 0) + groupParents = append(groupParents, 0) + } + + // Combine SignerAddresses and SignerGroups into a slice of Signer structs + bindSigners := make([]bindings.ManyChainMultiSigSigner, len(signerAddrs)) + for i := range signerAddrs { + bindSigners[i] = bindings.ManyChainMultiSigSigner{ + Addr: signerAddrs[i], + Group: signerGroups[i], + } + } + + // Sort signers by their addresses in ascending order + slices.SortFunc(bindSigners, func(i, j bindings.ManyChainMultiSigSigner) int { + addressA := new(big.Int).SetBytes(i.Addr.Bytes()) + addressB := new(big.Int).SetBytes(j.Addr.Bytes()) + + return addressA.Cmp(addressB) + }) + + // Extract the ordered addresses and groups after sorting + orderedSignerAddresses := make([]common.Address, len(signerAddrs)) + orderedSignerGroups := make([]uint8, len(signerAddrs)) + for i, signer := range bindSigners { + orderedSignerAddresses[i] = signer.Addr + orderedSignerGroups[i] = signer.Group + } + + return [32]uint8(groupQuorums), [32]uint8(groupParents), orderedSignerAddresses, orderedSignerGroups, nil +} + +func extractGroupsAndSigners( + group *types.Config, + parentIdx uint8, + groupQuorums *[]uint8, + groupParents *[]uint8, + signerAddrs *[]common.Address, + signerGroups *[]uint8, +) error { + // Append the group's quorum and parent index to the respective slices + *groupQuorums = append(*groupQuorums, group.Quorum) + *groupParents = append(*groupParents, parentIdx) + + // Assign the current group index + currentGroupIdx := len(*groupQuorums) - 1 + + // Safe to cast currentGroupIdx to uint8 + currentGroupIdxUint8, err := safecast.IntToUint8(currentGroupIdx) + if err != nil { + return fmt.Errorf("group index %d exceeds uint8 range", currentGroupIdx) + } + + // For each string signer, append the signer and its group index + for _, signerAddr := range group.Signers { + *signerAddrs = append(*signerAddrs, signerAddr) + *signerGroups = append(*signerGroups, currentGroupIdxUint8) + } + + // Recursively handle the nested multisig groups + for _, groupSigner := range group.GroupSigners { + if err := extractGroupsAndSigners(&groupSigner, currentGroupIdxUint8, groupQuorums, groupParents, signerAddrs, signerGroups); err != nil { + return err + } + } + + return nil +} diff --git a/sdk/evm/config_transformer.go b/sdk/evm/config_transformer.go index bffec74fb..ecd1138ab 100644 --- a/sdk/evm/config_transformer.go +++ b/sdk/evm/config_transformer.go @@ -1,13 +1,8 @@ package evm import ( - "fmt" - "math/big" - "slices" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/mcms/internal/utils/safecast" "github.com/smartcontractkit/mcms/sdk" sdkerrors "github.com/smartcontractkit/mcms/sdk/errors" "github.com/smartcontractkit/mcms/sdk/evm/bindings" @@ -69,7 +64,7 @@ func (e *ConfigTransformer) ToChainConfig( ) (bindings.ManyChainMultiSigConfig, error) { var bindConfig bindings.ManyChainMultiSigConfig - groupQuorums, groupParents, signerAddrs, signerGroups, err := ExtractSetConfigInputs(&cfg) + groupQuorums, groupParents, signerAddrs, signerGroups, err := sdk.ExtractSetConfigInputs(&cfg) if err != nil { return bindConfig, err } @@ -97,92 +92,3 @@ func (e *ConfigTransformer) ToChainConfig( Signers: bindSigners, }, nil } - -// ExtractSetConfigInputs flattens a nested `*types.Config` into: -// 1. groupQuorums: [32]uint8 where each index i holds the quorum for group i (zero-padded). -// 2. groupParents: [32]uint8 where each index i holds the parent group’s index (or a sentinel). -// 3. orderedSignerAddresses: a sorted slice of all signer addresses. -// 4. orderedSignerGroups: a parallel slice of group indices for each signer. -// -// Returns an error if the structure cannot be flattened (e.g., too many groups). -func ExtractSetConfigInputs( - group *types.Config, -) ([32]uint8, [32]uint8, []common.Address, []uint8, error) { - var groupQuorums, groupParents, signerGroups = []uint8{}, []uint8{}, []uint8{} - var signerAddrs = []common.Address{} - - err := extractGroupsAndSigners(group, 0, &groupQuorums, &groupParents, &signerAddrs, &signerGroups) - if err != nil { - return [32]uint8{}, [32]uint8{}, []common.Address{}, []uint8{}, err - } - - // fill the rest of the arrays with 0s - for i := len(groupQuorums); i < 32; i++ { - groupQuorums = append(groupQuorums, 0) - groupParents = append(groupParents, 0) - } - - // Combine SignerAddresses and SignerGroups into a slice of Signer structs - bindSigners := make([]bindings.ManyChainMultiSigSigner, len(signerAddrs)) - for i := range signerAddrs { - bindSigners[i] = bindings.ManyChainMultiSigSigner{ - Addr: signerAddrs[i], - Group: signerGroups[i], - } - } - - // Sort signers by their addresses in ascending order - slices.SortFunc(bindSigners, func(i, j bindings.ManyChainMultiSigSigner) int { - addressA := new(big.Int).SetBytes(i.Addr.Bytes()) - addressB := new(big.Int).SetBytes(j.Addr.Bytes()) - - return addressA.Cmp(addressB) - }) - - // Extract the ordered addresses and groups after sorting - orderedSignerAddresses := make([]common.Address, len(signerAddrs)) - orderedSignerGroups := make([]uint8, len(signerAddrs)) - for i, signer := range bindSigners { - orderedSignerAddresses[i] = signer.Addr - orderedSignerGroups[i] = signer.Group - } - - return [32]uint8(groupQuorums), [32]uint8(groupParents), orderedSignerAddresses, orderedSignerGroups, nil -} - -func extractGroupsAndSigners( - group *types.Config, - parentIdx uint8, - groupQuorums *[]uint8, - groupParents *[]uint8, - signerAddrs *[]common.Address, - signerGroups *[]uint8, -) error { - // Append the group's quorum and parent index to the respective slices - *groupQuorums = append(*groupQuorums, group.Quorum) - *groupParents = append(*groupParents, parentIdx) - - // Assign the current group index - currentGroupIdx := len(*groupQuorums) - 1 - - // Safe to cast currentGroupIdx to uint8 - currentGroupIdxUint8, err := safecast.IntToUint8(currentGroupIdx) - if err != nil { - return fmt.Errorf("group index %d exceeds uint8 range", currentGroupIdx) - } - - // For each string signer, append the signer and its group index - for _, signerAddr := range group.Signers { - *signerAddrs = append(*signerAddrs, signerAddr) - *signerGroups = append(*signerGroups, currentGroupIdxUint8) - } - - // Recursively handle the nested multisig groups - for _, groupSigner := range group.GroupSigners { - if err := extractGroupsAndSigners(&groupSigner, currentGroupIdxUint8, groupQuorums, groupParents, signerAddrs, signerGroups); err != nil { - return err - } - } - - return nil -} diff --git a/sdk/evm/configurer.go b/sdk/evm/configurer.go index c24e17dfe..9cbbc39f0 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 sdk.ContractDeployBackend + client ContractDeployBackend auth *bind.TransactOpts } // NewConfigurer creates a new Configurer for EVM chains. -func NewConfigurer(client sdk.ContractDeployBackend, auth *bind.TransactOpts, +func NewConfigurer(client ContractDeployBackend, auth *bind.TransactOpts, ) *Configurer { return &Configurer{ client: client, @@ -37,7 +37,7 @@ func (c *Configurer) SetConfig(ctx context.Context, mcmAddr string, cfg *types.C return types.TransactionResult{}, err } - groupQuorums, groupParents, signerAddrs, signerGroups, err := ExtractSetConfigInputs(cfg) + groupQuorums, groupParents, signerAddrs, signerGroups, err := sdk.ExtractSetConfigInputs(cfg) if err != nil { return types.TransactionResult{}, err } diff --git a/sdk/evm/execution_error.go b/sdk/evm/execution_error.go index 291b724ac..b7c15891b 100644 --- a/sdk/evm/execution_error.go +++ b/sdk/evm/execution_error.go @@ -18,7 +18,6 @@ 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" ) @@ -240,7 +239,7 @@ func BuildExecutionError( txPreview *gethtypes.Transaction, opts *bind.TransactOpts, contractAddr common.Address, - client sdk.ContractDeployBackend, + client ContractDeployBackend, timelockAddr common.Address, timelockCallData []byte, ) *ExecutionError { @@ -615,7 +614,7 @@ func getUnderlyingRevertReason( timelockAddr common.Address, timelockCallData []byte, opts *bind.TransactOpts, - client sdk.ContractDeployBackend, + client 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 9484800b6..f1418a33c 100644 --- a/sdk/evm/execution_error_test.go +++ b/sdk/evm/execution_error_test.go @@ -15,7 +15,6 @@ 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" ) @@ -1400,7 +1399,7 @@ func TestGetUnderlyingRevertReason(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - var client sdk.ContractDeployBackend + var client 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 c9318cf6b..2cc3e5564 100644 --- a/sdk/evm/executor.go +++ b/sdk/evm/executor.go @@ -12,7 +12,6 @@ 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" ) @@ -25,7 +24,7 @@ type Executor struct { } // NewExecutor creates a new Executor for EVM chains -func NewExecutor(encoder *Encoder, client sdk.ContractDeployBackend, auth *bind.TransactOpts) *Executor { +func NewExecutor(encoder *Encoder, client 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 e253b90fd..db215a47d 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 sdk.ContractDeployBackend + client ContractDeployBackend } // NewInspector creates a new Inspector for EVM chains -func NewInspector(client sdk.ContractDeployBackend) *Inspector { +func NewInspector(client ContractDeployBackend) *Inspector { return &Inspector{ ConfigTransformer: ConfigTransformer{}, client: client, diff --git a/sdk/evm/simulator.go b/sdk/evm/simulator.go index c7ad29bcd..2dbd203a0 100644 --- a/sdk/evm/simulator.go +++ b/sdk/evm/simulator.go @@ -9,7 +9,6 @@ import ( "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 +18,7 @@ type Simulator struct { *Inspector } -func NewSimulator(encoder *Encoder, client sdk.ContractDeployBackend) (*Simulator, error) { +func NewSimulator(encoder *Encoder, client 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 150b69995..da8b58944 100644 --- a/sdk/evm/simulator_test.go +++ b/sdk/evm/simulator_test.go @@ -15,7 +15,6 @@ 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" @@ -31,7 +30,7 @@ func TestNewSimulator(t *testing.T) { tests := []struct { name string encoder *evm.Encoder - client sdk.ContractDeployBackend + client evm.ContractDeployBackend wantErr error wantErrMsg string }{ diff --git a/sdk/evm/timelock_executor.go b/sdk/evm/timelock_executor.go index 9deb69deb..7bade02e7 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 sdk.ContractDeployBackend + client ContractDeployBackend auth *bind.TransactOpts } // NewTimelockExecutor creates a new TimelockExecutor -func NewTimelockExecutor(client sdk.ContractDeployBackend, auth *bind.TransactOpts) *TimelockExecutor { +func NewTimelockExecutor(client 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 e38257242..bff045470 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 sdk.ContractDeployBackend + client ContractDeployBackend } // NewTimelockInspector creates a new TimelockInspector -func NewTimelockInspector(client sdk.ContractDeployBackend) *TimelockInspector { +func NewTimelockInspector(client ContractDeployBackend) *TimelockInspector { return &TimelockInspector{ client: client, } diff --git a/sdk/evm/utils.go b/sdk/evm/utils.go index 339484010..05bab6f6c 100644 --- a/sdk/evm/utils.go +++ b/sdk/evm/utils.go @@ -1,6 +1,7 @@ package evm import ( + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" cselectors "github.com/smartcontractkit/chain-selectors" @@ -18,6 +19,11 @@ 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/solana/config_transformer.go b/sdk/solana/config_transformer.go index ceee25cac..858a29905 100644 --- a/sdk/solana/config_transformer.go +++ b/sdk/solana/config_transformer.go @@ -3,8 +3,9 @@ package solana import ( "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/mcms/sdk" sdkerrors "github.com/smartcontractkit/mcms/sdk/errors" - "github.com/smartcontractkit/mcms/sdk/evm" + "github.com/smartcontractkit/mcms/types" "github.com/gagliardetto/solana-go" @@ -77,7 +78,7 @@ func (e *ConfigTransformer) ToChainConfig(cfg types.Config, solanaConfig Additio ProposedOwner: solanaConfig.ProposedOwner, } // Populate the signers: we can reuse the evm implementation here as the signers structure is the same - groupQuorums, groupParents, signerAddrs, signerGroups, err := evm.ExtractSetConfigInputs(&cfg) + groupQuorums, groupParents, signerAddrs, signerGroups, err := sdk.ExtractSetConfigInputs(&cfg) if err != nil { return bindings.MultisigConfig{}, err } diff --git a/sdk/solana/configurer.go b/sdk/solana/configurer.go index 0a94feef6..29bfb1283 100644 --- a/sdk/solana/configurer.go +++ b/sdk/solana/configurer.go @@ -9,7 +9,7 @@ import ( evmCommon "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/mcms/sdk" - evmsdk "github.com/smartcontractkit/mcms/sdk/evm" + "github.com/smartcontractkit/mcms/types" "github.com/gagliardetto/solana-go" @@ -89,7 +89,7 @@ func (c *Configurer) SetConfig( return types.TransactionResult{}, err } - groupQuorums, groupParents, signerAddresses, signerGroups, err := evmsdk.ExtractSetConfigInputs(cfg) + groupQuorums, groupParents, signerAddresses, signerGroups, err := sdk.ExtractSetConfigInputs(cfg) if err != nil { return types.TransactionResult{}, fmt.Errorf("unable to extract set config inputs: %w", err) } diff --git a/sdk/sui/configurer.go b/sdk/sui/configurer.go index df95fb8f2..1ddaf8d85 100644 --- a/sdk/sui/configurer.go +++ b/sdk/sui/configurer.go @@ -14,7 +14,6 @@ import ( bindutils "github.com/smartcontractkit/chainlink-sui/bindings/utils" "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/types" ) @@ -51,7 +50,7 @@ func (c Configurer) SetConfig(ctx context.Context, mcmsAddr string, cfg *types.C return types.TransactionResult{}, err } chainIDBig := new(big.Int).SetUint64(chainID) - groupQuorum, groupParents, signerAddresses, signerGroups, err := evm.ExtractSetConfigInputs(cfg) + groupQuorum, groupParents, signerAddresses, signerGroups, err := sdk.ExtractSetConfigInputs(cfg) if err != nil { return types.TransactionResult{}, fmt.Errorf("unable to extract set config inputs: %w", err) diff --git a/sdk/sui/sui_helpers.go b/sdk/sui/sui_helpers.go new file mode 100644 index 000000000..1c167c146 --- /dev/null +++ b/sdk/sui/sui_helpers.go @@ -0,0 +1,23 @@ +package sui + +import ( + "encoding/json" + "fmt" + + "github.com/smartcontractkit/mcms/types" +) + +func SuiMetadata(chainMetadata types.ChainMetadata) (AdditionalFieldsMetadata, error) { + var metadata AdditionalFieldsMetadata + err := json.Unmarshal([]byte(chainMetadata.AdditionalFields), &metadata) + if err != nil { + return AdditionalFieldsMetadata{}, fmt.Errorf("error unmarshaling sui chain metadata: %w", err) + } + + err = metadata.Validate() + if err != nil { + return AdditionalFieldsMetadata{}, fmt.Errorf("error validating sui chain metadata: %w", err) + } + + return metadata, nil +} diff --git a/chainsmetadata/sui_helpers_test.go b/sdk/sui/sui_helpers_test.go similarity index 90% rename from chainsmetadata/sui_helpers_test.go rename to sdk/sui/sui_helpers_test.go index a1ba92483..468dcdf01 100644 --- a/chainsmetadata/sui_helpers_test.go +++ b/sdk/sui/sui_helpers_test.go @@ -1,4 +1,4 @@ -package chainsmetadata +package sui import ( "testing" @@ -6,7 +6,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/mcms/sdk/sui" "github.com/smartcontractkit/mcms/types" ) @@ -61,14 +60,14 @@ func TestSuiMetadata(t *testing.T) { if tt.expectError { require.Error(t, err) assert.Contains(t, err.Error(), tt.errorMsg) - assert.Equal(t, sui.AdditionalFieldsMetadata{}, metadata) + assert.Equal(t, AdditionalFieldsMetadata{}, metadata) return } require.NoError(t, err) assert.Equal(t, "0x1", metadata.McmsPackageID) - assert.Equal(t, sui.TimelockRole(1), metadata.Role) + assert.Equal(t, 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/sdk/sui/utils.go b/sdk/sui/utils.go index 0782cd745..477f346cb 100644 --- a/sdk/sui/utils.go +++ b/sdk/sui/utils.go @@ -8,6 +8,15 @@ import ( const AddressLen = 32 +// 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 Address [AddressLen]uint8 func AddressFromHex(str string) (*Address, error) { diff --git a/sdk/ton/config_transformer.go b/sdk/ton/config_transformer.go index 69349c2c6..0b274a96d 100644 --- a/sdk/ton/config_transformer.go +++ b/sdk/ton/config_transformer.go @@ -33,7 +33,7 @@ func NewConfigTransformer() ConfigTransformer { return &configTransformer{} } // ToChainConfig converts the chain agnostic config to the chain-specific config func (e *configTransformer) ToChainConfig(cfg types.Config, _ any) (mcms.Config, error) { - groupQuorum, groupParents, signerAddrs, signerGroups, err := evm.ExtractSetConfigInputs(&cfg) + groupQuorum, groupParents, signerAddrs, signerGroups, err := sdk.ExtractSetConfigInputs(&cfg) if err != nil { return mcms.Config{}, fmt.Errorf("unable to extract set config inputs: %w", err) } diff --git a/sdk/ton/configurer.go b/sdk/ton/configurer.go index d49ccc5a9..89c6b880d 100644 --- a/sdk/ton/configurer.go +++ b/sdk/ton/configurer.go @@ -9,7 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" "github.com/smartcontractkit/mcms/sdk" - "github.com/smartcontractkit/mcms/sdk/evm" + "github.com/smartcontractkit/mcms/types" "github.com/xssnick/tonutils-go/address" @@ -62,7 +62,7 @@ func (c configurer) SetConfig(ctx context.Context, mcmsAddr string, cfg *types.C return types.TransactionResult{}, fmt.Errorf("invalid mcms address: %w", err) } - groupQuorum, groupParents, signerAddresses, _signerGroups, err := evm.ExtractSetConfigInputs(cfg) + groupQuorum, groupParents, signerAddresses, _signerGroups, err := sdk.ExtractSetConfigInputs(cfg) if err != nil { return types.TransactionResult{}, fmt.Errorf("unable to extract set config inputs: %w", err) } diff --git a/signable_test.go b/signable_test.go index d3b8df919..4c1b8501a 100644 --- a/signable_test.go +++ b/signable_test.go @@ -460,7 +460,7 @@ func TestSignable_SingleChainMultipleSignerMultipleTX_FailureMissingQuorum(t *te // Validate the signatures quorumMet, err := signable.ValidateSignatures(ctx) require.Error(t, err) - //nolint:testifylint // Allow IsType for error type checking + require.IsType(t, &QuorumNotReachedError{}, err) require.False(t, quorumMet) } diff --git a/timelock_proposal.go b/timelock_proposal.go index 09562e1a0..caec11edd 100644 --- a/timelock_proposal.go +++ b/timelock_proposal.go @@ -15,7 +15,7 @@ import ( chain_selectors "github.com/smartcontractkit/chain-selectors" - inspectorsbuilder "github.com/smartcontractkit/mcms/inspectors" + inspectorsbuilder "github.com/smartcontractkit/mcms/chainaccess" "github.com/smartcontractkit/mcms/internal/utils/safecast" "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/sdk/aptos" @@ -343,7 +343,7 @@ func (m *TimelockProposal) OperationCounts(ctx context.Context) (map[types.Chain // 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, + chains inspectorsbuilder.ChainAccess, chainSelector types.ChainSelector, ) (uint64, error) { if m == nil { @@ -367,7 +367,7 @@ type chainInspectorFactoryFunc func( action types.TimelockAction, metadata types.ChainMetadata, chainSelector types.ChainSelector, - chains sdk.ChainAccess, + chains inspectorsbuilder.ChainAccess, ) (sdk.Inspector, error) // inspectorFactory is overridden in tests so we can inject lightweight inspectors @@ -381,7 +381,7 @@ func defaultInspectorFactory( action types.TimelockAction, metadata types.ChainMetadata, chainSelector types.ChainSelector, - chains sdk.ChainAccess, + chains inspectorsbuilder.ChainAccess, ) (sdk.Inspector, error) { return inspectorsbuilder.BuildInspector(chains, chainSelector, action, metadata) } diff --git a/timelock_proposal_test.go b/timelock_proposal_test.go index 25458ada9..d939511ea 100644 --- a/timelock_proposal_test.go +++ b/timelock_proposal_test.go @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/mcms/chainaccess" "github.com/smartcontractkit/mcms/internal/testutils/chaintest" "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/sdk/mocks" @@ -376,7 +377,7 @@ func TestTimelockProposal_GetOpCount(t *testing.T) { t.Parallel() prevFactory := inspectorFactory - inspectorFactory = func(action types.TimelockAction, metadata types.ChainMetadata, cs types.ChainSelector, chains sdk.ChainAccess) (sdk.Inspector, error) { + inspectorFactory = func(action types.TimelockAction, metadata types.ChainMetadata, cs types.ChainSelector, chains chainaccess.ChainAccess) (sdk.Inspector, error) { if tc.setupMock != nil { return tc.setupMock(t) } From 9616e3af015c23d4c46ab7f5760e6c06feda4cca Mon Sep 17 00:00:00 2001 From: Pablo Date: Fri, 16 Jan 2026 08:56:05 -0600 Subject: [PATCH 21/26] fix: remove timelock proposal helper Signed-off-by: Pablo --- timelock_proposal.go | 47 ----------------- timelock_proposal_test.go | 105 +------------------------------------- 2 files changed, 2 insertions(+), 150 deletions(-) diff --git a/timelock_proposal.go b/timelock_proposal.go index caec11edd..8cf463674 100644 --- a/timelock_proposal.go +++ b/timelock_proposal.go @@ -15,7 +15,6 @@ import ( chain_selectors "github.com/smartcontractkit/chain-selectors" - inspectorsbuilder "github.com/smartcontractkit/mcms/chainaccess" "github.com/smartcontractkit/mcms/internal/utils/safecast" "github.com/smartcontractkit/mcms/sdk" "github.com/smartcontractkit/mcms/sdk/aptos" @@ -340,52 +339,6 @@ 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 inspectorsbuilder.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 inspectorsbuilder.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 inspectorsbuilder.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 d939511ea..2585f20dc 100644 --- a/timelock_proposal_test.go +++ b/timelock_proposal_test.go @@ -18,14 +18,13 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/mcms/chainaccess" "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" ) @@ -307,107 +306,7 @@ func TestNewTimelockProposal(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 chainaccess.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) { +func TestWriteTimelockProposal(t *testing.T) { t.Parallel() tests := []struct { From 677cf02b0e4cda597dbb332bcde97e6b938afd21 Mon Sep 17 00:00:00 2001 From: Pablo Date: Fri, 16 Jan 2026 09:21:49 -0600 Subject: [PATCH 22/26] fix: linting Signed-off-by: Pablo --- signable_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/signable_test.go b/signable_test.go index 4c1b8501a..672b7e7af 100644 --- a/signable_test.go +++ b/signable_test.go @@ -461,7 +461,7 @@ func TestSignable_SingleChainMultipleSignerMultipleTX_FailureMissingQuorum(t *te quorumMet, err := signable.ValidateSignatures(ctx) require.Error(t, err) - require.IsType(t, &QuorumNotReachedError{}, err) + require.EqualError(t, QuorumNotReachedError{ChainSelector: chaintest.Chain1Selector}, err.Error()) require.False(t, quorumMet) } From 56dd5bba9e0b7b170a088b7beee734ca64f17ab7 Mon Sep 17 00:00:00 2001 From: Pablo Date: Fri, 16 Jan 2026 11:01:37 -0600 Subject: [PATCH 23/26] fix: rename chain accessor and pkg name Signed-off-by: Pablo --- .../chainaccess.go => chainwrappers/chainaccessor.go | 4 ++-- {chainaccess => chainwrappers}/converters.go | 2 +- {chainaccess => chainwrappers}/converters_test.go | 2 +- {chainaccess => chainwrappers}/inspectors.go | 8 ++++---- {chainaccess => chainwrappers}/inspectors_test.go | 3 ++- {chainaccess => chainwrappers}/mocks/chain_access.go | 0 errors.go | 2 +- 7 files changed, 11 insertions(+), 10 deletions(-) rename chainaccess/chainaccess.go => chainwrappers/chainaccessor.go (90%) rename {chainaccess => chainwrappers}/converters.go (98%) rename {chainaccess => chainwrappers}/converters_test.go (98%) rename {chainaccess => chainwrappers}/inspectors.go (96%) rename {chainaccess => chainwrappers}/inspectors_test.go (99%) rename {chainaccess => chainwrappers}/mocks/chain_access.go (100%) diff --git a/chainaccess/chainaccess.go b/chainwrappers/chainaccessor.go similarity index 90% rename from chainaccess/chainaccess.go rename to chainwrappers/chainaccessor.go index c19f1f403..112e549f3 100644 --- a/chainaccess/chainaccess.go +++ b/chainwrappers/chainaccessor.go @@ -1,4 +1,4 @@ -package chainaccess +package chainwrappers import ( aptoslib "github.com/aptos-labs/aptos-go-sdk" @@ -9,7 +9,7 @@ import ( suisuisdk "github.com/smartcontractkit/mcms/sdk/sui" ) -type ChainAccess interface { +type ChainAccessor interface { Selectors() []uint64 EVMClient(selector uint64) (evmsdk.ContractDeployBackend, bool) SolanaClient(selector uint64) (*solrpc.Client, bool) diff --git a/chainaccess/converters.go b/chainwrappers/converters.go similarity index 98% rename from chainaccess/converters.go rename to chainwrappers/converters.go index 567494998..6cabb7c44 100644 --- a/chainaccess/converters.go +++ b/chainwrappers/converters.go @@ -1,4 +1,4 @@ -package chainaccess +package chainwrappers import ( "fmt" diff --git a/chainaccess/converters_test.go b/chainwrappers/converters_test.go similarity index 98% rename from chainaccess/converters_test.go rename to chainwrappers/converters_test.go index d607aca39..01dd72997 100644 --- a/chainaccess/converters_test.go +++ b/chainwrappers/converters_test.go @@ -1,4 +1,4 @@ -package chainaccess +package chainwrappers import ( "testing" diff --git a/chainaccess/inspectors.go b/chainwrappers/inspectors.go similarity index 96% rename from chainaccess/inspectors.go rename to chainwrappers/inspectors.go index dc70b7a81..c15ef8033 100644 --- a/chainaccess/inspectors.go +++ b/chainwrappers/inspectors.go @@ -1,4 +1,4 @@ -package chainaccess +package chainwrappers import ( "fmt" @@ -15,7 +15,7 @@ import ( // BuildInspectors gets a map of inspectors for the given chain metadata and chain clients func BuildInspectors( - chains ChainAccess, + chains ChainAccessor, chainMetadata map[types.ChainSelector]types.ChainMetadata, action types.TimelockAction) (map[types.ChainSelector]sdk.Inspector, error) { inspectors := map[types.ChainSelector]sdk.Inspector{} @@ -30,9 +30,9 @@ func BuildInspectors( return inspectors, nil } -// BuildInspector constructs a chain-family-specific Inspector from ChainAccess plus metadata. +// BuildInspector constructs a chain-family-specific Inspector from ChainAccessor plus metadata. func BuildInspector( - chains ChainAccess, + chains ChainAccessor, selector types.ChainSelector, action types.TimelockAction, metadata types.ChainMetadata, diff --git a/chainaccess/inspectors_test.go b/chainwrappers/inspectors_test.go similarity index 99% rename from chainaccess/inspectors_test.go rename to chainwrappers/inspectors_test.go index f7abbe24c..90c2226e7 100644 --- a/chainaccess/inspectors_test.go +++ b/chainwrappers/inspectors_test.go @@ -1,4 +1,4 @@ -package chainaccess +package chainwrappers import ( "testing" @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/mcms/chainaccess/mocks" + mcmsTypes "github.com/smartcontractkit/mcms/types" ) diff --git a/chainaccess/mocks/chain_access.go b/chainwrappers/mocks/chain_access.go similarity index 100% rename from chainaccess/mocks/chain_access.go rename to chainwrappers/mocks/chain_access.go diff --git a/errors.go b/errors.go index 2ce62bd39..a827b8c5e 100644 --- a/errors.go +++ b/errors.go @@ -109,7 +109,7 @@ func NewQuorumNotReachedError(sel types.ChainSelector) *QuorumNotReachedError { return &QuorumNotReachedError{ChainSelector: sel} } -func (e *QuorumNotReachedError) Error() string { +func (e QuorumNotReachedError) Error() string { return fmt.Sprintf("quorum not reached for chain %d", e.ChainSelector) } From 0ed8e3ea35db88b72b9e0db733286a5e42c93d29 Mon Sep 17 00:00:00 2001 From: Pablo Date: Fri, 16 Jan 2026 11:20:33 -0600 Subject: [PATCH 24/26] fix: lint errors Signed-off-by: Pablo --- chainwrappers/inspectors_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainwrappers/inspectors_test.go b/chainwrappers/inspectors_test.go index 90c2226e7..7f2ec7159 100644 --- a/chainwrappers/inspectors_test.go +++ b/chainwrappers/inspectors_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/mcms/chainaccess/mocks" + "github.com/smartcontractkit/mcms/chainwrappers/mocks" mcmsTypes "github.com/smartcontractkit/mcms/types" ) From e76ab00c6d2286cb2c878b6cb70ee2df6b080aeb Mon Sep 17 00:00:00 2001 From: Pablo Date: Fri, 16 Jan 2026 11:22:47 -0600 Subject: [PATCH 25/26] fix: mocks generation Signed-off-by: Pablo --- .mockery.yaml | 2 +- .../{chain_access.go => chain_accessor.go} | 98 +++++++++---------- 2 files changed, 50 insertions(+), 50 deletions(-) rename chainwrappers/mocks/{chain_access.go => chain_accessor.go} (52%) diff --git a/.mockery.yaml b/.mockery.yaml index 6d096eb16..d4ad3d309 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -32,7 +32,7 @@ packages: config: dir: "./sdk/ton/mocks" filename: "api.go" - github.com/smartcontractkit/mcms/chainaccess: + github.com/smartcontractkit/mcms/chainwrappers: github.com/smartcontractkit/mcms/sdk: github.com/smartcontractkit/mcms/sdk/evm: github.com/smartcontractkit/mcms/sdk/evm/bindings: diff --git a/chainwrappers/mocks/chain_access.go b/chainwrappers/mocks/chain_accessor.go similarity index 52% rename from chainwrappers/mocks/chain_access.go rename to chainwrappers/mocks/chain_accessor.go index 521b827c0..58f1d7be6 100644 --- a/chainwrappers/mocks/chain_access.go +++ b/chainwrappers/mocks/chain_accessor.go @@ -16,21 +16,21 @@ import ( sui "github.com/block-vision/sui-go-sdk/sui" ) -// ChainAccess is an autogenerated mock type for the ChainAccess type -type ChainAccess struct { +// ChainAccessor is an autogenerated mock type for the ChainAccessor type +type ChainAccessor struct { mock.Mock } -type ChainAccess_Expecter struct { +type ChainAccessor_Expecter struct { mock *mock.Mock } -func (_m *ChainAccess) EXPECT() *ChainAccess_Expecter { - return &ChainAccess_Expecter{mock: &_m.Mock} +func (_m *ChainAccessor) EXPECT() *ChainAccessor_Expecter { + return &ChainAccessor_Expecter{mock: &_m.Mock} } // AptosClient provides a mock function with given fields: selector -func (_m *ChainAccess) AptosClient(selector uint64) (aptos.AptosRpcClient, bool) { +func (_m *ChainAccessor) AptosClient(selector uint64) (aptos.AptosRpcClient, bool) { ret := _m.Called(selector) if len(ret) == 0 { @@ -59,36 +59,36 @@ func (_m *ChainAccess) AptosClient(selector uint64) (aptos.AptosRpcClient, 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 { +// ChainAccessor_AptosClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AptosClient' +type ChainAccessor_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 (_e *ChainAccessor_Expecter) AptosClient(selector interface{}) *ChainAccessor_AptosClient_Call { + return &ChainAccessor_AptosClient_Call{Call: _e.mock.On("AptosClient", selector)} } -func (_c *ChainAccess_AptosClient_Call) Run(run func(selector uint64)) *ChainAccess_AptosClient_Call { +func (_c *ChainAccessor_AptosClient_Call) Run(run func(selector uint64)) *ChainAccessor_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 { +func (_c *ChainAccessor_AptosClient_Call) Return(_a0 aptos.AptosRpcClient, _a1 bool) *ChainAccessor_AptosClient_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *ChainAccess_AptosClient_Call) RunAndReturn(run func(uint64) (aptos.AptosRpcClient, bool)) *ChainAccess_AptosClient_Call { +func (_c *ChainAccessor_AptosClient_Call) RunAndReturn(run func(uint64) (aptos.AptosRpcClient, bool)) *ChainAccessor_AptosClient_Call { _c.Call.Return(run) return _c } // EVMClient provides a mock function with given fields: selector -func (_m *ChainAccess) EVMClient(selector uint64) (evm.ContractDeployBackend, bool) { +func (_m *ChainAccessor) EVMClient(selector uint64) (evm.ContractDeployBackend, bool) { ret := _m.Called(selector) if len(ret) == 0 { @@ -117,36 +117,36 @@ func (_m *ChainAccess) EVMClient(selector uint64) (evm.ContractDeployBackend, bo 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 { +// ChainAccessor_EVMClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EVMClient' +type ChainAccessor_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 (_e *ChainAccessor_Expecter) EVMClient(selector interface{}) *ChainAccessor_EVMClient_Call { + return &ChainAccessor_EVMClient_Call{Call: _e.mock.On("EVMClient", selector)} } -func (_c *ChainAccess_EVMClient_Call) Run(run func(selector uint64)) *ChainAccess_EVMClient_Call { +func (_c *ChainAccessor_EVMClient_Call) Run(run func(selector uint64)) *ChainAccessor_EVMClient_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(uint64)) }) return _c } -func (_c *ChainAccess_EVMClient_Call) Return(_a0 evm.ContractDeployBackend, _a1 bool) *ChainAccess_EVMClient_Call { +func (_c *ChainAccessor_EVMClient_Call) Return(_a0 evm.ContractDeployBackend, _a1 bool) *ChainAccessor_EVMClient_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *ChainAccess_EVMClient_Call) RunAndReturn(run func(uint64) (evm.ContractDeployBackend, bool)) *ChainAccess_EVMClient_Call { +func (_c *ChainAccessor_EVMClient_Call) RunAndReturn(run func(uint64) (evm.ContractDeployBackend, bool)) *ChainAccessor_EVMClient_Call { _c.Call.Return(run) return _c } // Selectors provides a mock function with no fields -func (_m *ChainAccess) Selectors() []uint64 { +func (_m *ChainAccessor) Selectors() []uint64 { ret := _m.Called() if len(ret) == 0 { @@ -165,35 +165,35 @@ func (_m *ChainAccess) Selectors() []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 { +// ChainAccessor_Selectors_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Selectors' +type ChainAccessor_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 (_e *ChainAccessor_Expecter) Selectors() *ChainAccessor_Selectors_Call { + return &ChainAccessor_Selectors_Call{Call: _e.mock.On("Selectors")} } -func (_c *ChainAccess_Selectors_Call) Run(run func()) *ChainAccess_Selectors_Call { +func (_c *ChainAccessor_Selectors_Call) Run(run func()) *ChainAccessor_Selectors_Call { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *ChainAccess_Selectors_Call) Return(_a0 []uint64) *ChainAccess_Selectors_Call { +func (_c *ChainAccessor_Selectors_Call) Return(_a0 []uint64) *ChainAccessor_Selectors_Call { _c.Call.Return(_a0) return _c } -func (_c *ChainAccess_Selectors_Call) RunAndReturn(run func() []uint64) *ChainAccess_Selectors_Call { +func (_c *ChainAccessor_Selectors_Call) RunAndReturn(run func() []uint64) *ChainAccessor_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) { +func (_m *ChainAccessor) SolanaClient(selector uint64) (*rpc.Client, bool) { ret := _m.Called(selector) if len(ret) == 0 { @@ -222,36 +222,36 @@ func (_m *ChainAccess) SolanaClient(selector uint64) (*rpc.Client, 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 { +// ChainAccessor_SolanaClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SolanaClient' +type ChainAccessor_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 (_e *ChainAccessor_Expecter) SolanaClient(selector interface{}) *ChainAccessor_SolanaClient_Call { + return &ChainAccessor_SolanaClient_Call{Call: _e.mock.On("SolanaClient", selector)} } -func (_c *ChainAccess_SolanaClient_Call) Run(run func(selector uint64)) *ChainAccess_SolanaClient_Call { +func (_c *ChainAccessor_SolanaClient_Call) Run(run func(selector uint64)) *ChainAccessor_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 { +func (_c *ChainAccessor_SolanaClient_Call) Return(_a0 *rpc.Client, _a1 bool) *ChainAccessor_SolanaClient_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *ChainAccess_SolanaClient_Call) RunAndReturn(run func(uint64) (*rpc.Client, bool)) *ChainAccess_SolanaClient_Call { +func (_c *ChainAccessor_SolanaClient_Call) RunAndReturn(run func(uint64) (*rpc.Client, bool)) *ChainAccessor_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, sdksui.SuiSigner, bool) { +func (_m *ChainAccessor) SuiClient(selector uint64) (sui.ISuiAPI, sdksui.SuiSigner, bool) { ret := _m.Called(selector) if len(ret) == 0 { @@ -289,41 +289,41 @@ func (_m *ChainAccess) SuiClient(selector uint64) (sui.ISuiAPI, sdksui.SuiSigner 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 { +// ChainAccessor_SuiClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SuiClient' +type ChainAccessor_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 (_e *ChainAccessor_Expecter) SuiClient(selector interface{}) *ChainAccessor_SuiClient_Call { + return &ChainAccessor_SuiClient_Call{Call: _e.mock.On("SuiClient", selector)} } -func (_c *ChainAccess_SuiClient_Call) Run(run func(selector uint64)) *ChainAccess_SuiClient_Call { +func (_c *ChainAccessor_SuiClient_Call) Run(run func(selector uint64)) *ChainAccessor_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 sdksui.SuiSigner, _a2 bool) *ChainAccess_SuiClient_Call { +func (_c *ChainAccessor_SuiClient_Call) Return(_a0 sui.ISuiAPI, _a1 sdksui.SuiSigner, _a2 bool) *ChainAccessor_SuiClient_Call { _c.Call.Return(_a0, _a1, _a2) return _c } -func (_c *ChainAccess_SuiClient_Call) RunAndReturn(run func(uint64) (sui.ISuiAPI, sdksui.SuiSigner, bool)) *ChainAccess_SuiClient_Call { +func (_c *ChainAccessor_SuiClient_Call) RunAndReturn(run func(uint64) (sui.ISuiAPI, sdksui.SuiSigner, bool)) *ChainAccessor_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. +// NewChainAccessor creates a new instance of ChainAccessor. 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 { +func NewChainAccessor(t interface { mock.TestingT Cleanup(func()) -}) *ChainAccess { - mock := &ChainAccess{} +}) *ChainAccessor { + mock := &ChainAccessor{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) From 991ee66dfaeb472ba8c04b8179509e36627507c9 Mon Sep 17 00:00:00 2001 From: Pablo Date: Fri, 16 Jan 2026 11:25:44 -0600 Subject: [PATCH 26/26] fix: unit tests Signed-off-by: Pablo --- chainwrappers/inspectors_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/chainwrappers/inspectors_test.go b/chainwrappers/inspectors_test.go index 7f2ec7159..72af7b5bd 100644 --- a/chainwrappers/inspectors_test.go +++ b/chainwrappers/inspectors_test.go @@ -18,8 +18,8 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { tests := []struct { name string chainMetadata map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata - chainAccess *mocks.ChainAccess - setup func(access *mocks.ChainAccess) + chainAccess *mocks.ChainAccessor + setup func(access *mocks.ChainAccessor) expectErr bool errContains string expectedInspectorsCount int @@ -27,7 +27,7 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { { name: "empty input", chainMetadata: map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata{}, - chainAccess: mocks.NewChainAccess(t), + chainAccess: mocks.NewChainAccessor(t), expectErr: false, }, { @@ -35,7 +35,7 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { chainMetadata: map[mcmsTypes.ChainSelector]mcmsTypes.ChainMetadata{ 1: {MCMAddress: "0xabc", StartingOpCount: 0}, }, - chainAccess: mocks.NewChainAccess(t), + chainAccess: mocks.NewChainAccessor(t), expectErr: true, errContains: "error getting chain family: chain family not found for selector 1", }, @@ -45,9 +45,9 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { 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), + chainAccess: mocks.NewChainAccessor(t), expectErr: false, - setup: func(access *mocks.ChainAccess) { + setup: func(access *mocks.ChainAccessor) { access.EXPECT().EVMClient(mock.Anything).Return(nil, true) access.EXPECT().SolanaClient(mock.Anything).Return(nil, true) }, @@ -59,7 +59,7 @@ func TestMCMInspectorBuilder_BuildInspectors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() if tc.chainAccess == nil { - tc.chainAccess = mocks.NewChainAccess(t) + tc.chainAccess = mocks.NewChainAccessor(t) } if tc.expectedInspectorsCount > 0 { tc.setup(tc.chainAccess)

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