diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 92aa5fbc157..bc7792dd970 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -24,7 +24,7 @@ require ( github.com/prometheus/client_golang v1.20.5 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 9b0336635bb..4b2db7a7db5 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1092,8 +1092,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80 h1:BdqTkM2KObIaD2vevGM5MVJz+3pZl3wNF8h68Gh5iys= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595 h1:H6i0LEvXB0se/63E3jE9N0/7TugOYLpK4e6TT6a0omc= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f h1:xzEYM1e6Jvu2IHLkVgJeKNmxvz0R+CHQwrRM/lqmMRM= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= diff --git a/core/services/relay/evm/bindings/chain_config_factory.go b/core/services/relay/evm/bindings/chain_config_factory.go new file mode 100644 index 00000000000..8bd30cf9d5b --- /dev/null +++ b/core/services/relay/evm/bindings/chain_config_factory.go @@ -0,0 +1,107 @@ +package bindings + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" +) + +func NewChainReaderConfig() types.ChainReaderConfig { + chainReaderConfig := types.ChainReaderConfig{ + Contracts: map[string]types.ChainContractReader{ + "ChainReaderTester": types.ChainContractReader{ + Configs: map[string]*types.ChainReaderDefinition{ + "GetAlterablePrimitiveValue": &types.ChainReaderDefinition{ + CacheEnabled: false, + ChainSpecificName: "getAlterablePrimitiveValue", + ReadType: 0, + }, "GetDifferentPrimitiveValue": &types.ChainReaderDefinition{ + CacheEnabled: false, + ChainSpecificName: "getDifferentPrimitiveValue", + ReadType: 0, + }, "GetElementAtIndex": &types.ChainReaderDefinition{ + CacheEnabled: false, + ChainSpecificName: "getElementAtIndex", + ReadType: 0, + }, "GetPrimitiveValue": &types.ChainReaderDefinition{ + CacheEnabled: false, + ChainSpecificName: "getPrimitiveValue", + ReadType: 0, + }, "GetSliceValue": &types.ChainReaderDefinition{ + CacheEnabled: false, + ChainSpecificName: "getSliceValue", + ReadType: 0, + }, "ReturnSeen": &types.ChainReaderDefinition{ + CacheEnabled: false, + ChainSpecificName: "returnSeen", + ReadType: 0, + }, + }, + ContractABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"StaticBytes\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct AccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"}],\"name\":\"Triggered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"fieldHash\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"TriggeredEventWithDynamicTopic\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field1\",\"type\":\"int32\"},{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field2\",\"type\":\"int32\"},{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field3\",\"type\":\"int32\"}],\"name\":\"TriggeredWithFourTopics\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"field1\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint8[32]\",\"name\":\"field2\",\"type\":\"uint8[32]\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"field3\",\"type\":\"bytes32\"}],\"name\":\"TriggeredWithFourTopicsWithHashed\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"struct AccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"}],\"name\":\"addTestStruct\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAlterablePrimitiveValue\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDifferentPrimitiveValue\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"getElementAtIndex\",\"outputs\":[{\"components\":[{\"internalType\":\"int32\",\"name\":\"Field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"DifferentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"OracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"OracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"struct AccountStruct\",\"name\":\"AccountStruct\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"BigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"NestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"NestedStaticStruct\",\"type\":\"tuple\"}],\"internalType\":\"struct TestStruct\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPrimitiveValue\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSliceValue\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"struct AccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"}],\"name\":\"returnSeen\",\"outputs\":[{\"components\":[{\"internalType\":\"int32\",\"name\":\"Field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"DifferentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"OracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"OracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"struct AccountStruct\",\"name\":\"AccountStruct\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"BigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"NestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"NestedStaticStruct\",\"type\":\"tuple\"}],\"internalType\":\"struct TestStruct\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"value\",\"type\":\"uint64\"}],\"name\":\"setAlterablePrimitiveValue\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"struct AccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"}],\"name\":\"triggerEvent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"triggerEventWithDynamicTopic\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"val1\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"val2\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"val3\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"val4\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"val5\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"val6\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"val7\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"raw\",\"type\":\"bytes\"}],\"name\":\"triggerStaticBytes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field1\",\"type\":\"int32\"},{\"internalType\":\"int32\",\"name\":\"field2\",\"type\":\"int32\"},{\"internalType\":\"int32\",\"name\":\"field3\",\"type\":\"int32\"}],\"name\":\"triggerWithFourTopics\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"field1\",\"type\":\"string\"},{\"internalType\":\"uint8[32]\",\"name\":\"field2\",\"type\":\"uint8[32]\"},{\"internalType\":\"bytes32\",\"name\":\"field3\",\"type\":\"bytes32\"}],\"name\":\"triggerWithFourTopicsWithHashed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractPollingFilter: types.ContractPollingFilter{ + PollingFilter: types.PollingFilter{ + LogsPerBlock: 0, + MaxLogsKept: 0, + Retention: 0, + }, + }, + }, + }, + } + return chainReaderConfig +} + +func NewChainWriterConfig(maxGasPrice assets.Wei, defaultGasPrice uint64, fromAddress common.Address) types.ChainWriterConfig { + chainWriterConfig := types.ChainWriterConfig{ + Contracts: map[string]*types.ContractConfig{ + "ChainReaderTester": &types.ContractConfig{ + Configs: map[string]*types.ChainWriterDefinition{ + "AddTestStruct": &types.ChainWriterDefinition{ + ChainSpecificName: "addTestStruct", + Checker: "simulate", + FromAddress: fromAddress, + GasLimit: 0, + }, "SetAlterablePrimitiveValue": &types.ChainWriterDefinition{ + ChainSpecificName: "setAlterablePrimitiveValue", + Checker: "simulate", + FromAddress: fromAddress, + GasLimit: 0, + }, "TriggerEvent": &types.ChainWriterDefinition{ + ChainSpecificName: "triggerEvent", + Checker: "simulate", + FromAddress: fromAddress, + GasLimit: 0, + }, "TriggerEventWithDynamicTopic": &types.ChainWriterDefinition{ + ChainSpecificName: "triggerEventWithDynamicTopic", + Checker: "simulate", + FromAddress: fromAddress, + GasLimit: 0, + }, "TriggerStaticBytes": &types.ChainWriterDefinition{ + ChainSpecificName: "triggerStaticBytes", + Checker: "simulate", + FromAddress: fromAddress, + GasLimit: 0, + }, "TriggerWithFourTopics": &types.ChainWriterDefinition{ + ChainSpecificName: "triggerWithFourTopics", + Checker: "simulate", + FromAddress: fromAddress, + GasLimit: 0, + }, "TriggerWithFourTopicsWithHashed": &types.ChainWriterDefinition{ + ChainSpecificName: "triggerWithFourTopicsWithHashed", + Checker: "simulate", + FromAddress: fromAddress, + GasLimit: 0, + }, + }, + ContractABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"StaticBytes\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct AccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"}],\"name\":\"Triggered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"fieldHash\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"TriggeredEventWithDynamicTopic\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field1\",\"type\":\"int32\"},{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field2\",\"type\":\"int32\"},{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field3\",\"type\":\"int32\"}],\"name\":\"TriggeredWithFourTopics\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"field1\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint8[32]\",\"name\":\"field2\",\"type\":\"uint8[32]\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"field3\",\"type\":\"bytes32\"}],\"name\":\"TriggeredWithFourTopicsWithHashed\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"struct AccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"}],\"name\":\"addTestStruct\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAlterablePrimitiveValue\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDifferentPrimitiveValue\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"getElementAtIndex\",\"outputs\":[{\"components\":[{\"internalType\":\"int32\",\"name\":\"Field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"DifferentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"OracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"OracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"struct AccountStruct\",\"name\":\"AccountStruct\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"BigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"NestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"NestedStaticStruct\",\"type\":\"tuple\"}],\"internalType\":\"struct TestStruct\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPrimitiveValue\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSliceValue\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"struct AccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"}],\"name\":\"returnSeen\",\"outputs\":[{\"components\":[{\"internalType\":\"int32\",\"name\":\"Field\",\"type\":\"int32\"},{\"internalType\":\"string\",\"name\":\"DifferentField\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"OracleId\",\"type\":\"uint8\"},{\"internalType\":\"uint8[32]\",\"name\":\"OracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"struct AccountStruct\",\"name\":\"AccountStruct\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"internalType\":\"int192\",\"name\":\"BigField\",\"type\":\"int192\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"NestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"NestedStaticStruct\",\"type\":\"tuple\"}],\"internalType\":\"struct TestStruct\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"value\",\"type\":\"uint64\"}],\"name\":\"setAlterablePrimitiveValue\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"S\",\"type\":\"string\"}],\"internalType\":\"struct InnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelDynamicTestStruct\",\"name\":\"nestedDynamicStruct\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"FixedBytes\",\"type\":\"bytes2\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"IntVal\",\"type\":\"int64\"},{\"internalType\":\"address\",\"name\":\"A\",\"type\":\"address\"}],\"internalType\":\"struct InnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"struct MidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"AccountStr\",\"type\":\"address\"}],\"internalType\":\"struct AccountStruct\",\"name\":\"accountStruct\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"internalType\":\"int192\",\"name\":\"bigField\",\"type\":\"int192\"}],\"name\":\"triggerEvent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"triggerEventWithDynamicTopic\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"val1\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"val2\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"val3\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"val4\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"val5\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"val6\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"val7\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"raw\",\"type\":\"bytes\"}],\"name\":\"triggerStaticBytes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"field1\",\"type\":\"int32\"},{\"internalType\":\"int32\",\"name\":\"field2\",\"type\":\"int32\"},{\"internalType\":\"int32\",\"name\":\"field3\",\"type\":\"int32\"}],\"name\":\"triggerWithFourTopics\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"field1\",\"type\":\"string\"},{\"internalType\":\"uint8[32]\",\"name\":\"field2\",\"type\":\"uint8[32]\"},{\"internalType\":\"bytes32\",\"name\":\"field3\",\"type\":\"bytes32\"}],\"name\":\"triggerWithFourTopicsWithHashed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + }, + }, + } + chainWriterConfig.MaxGasPrice = &maxGasPrice + for _, contract := range chainWriterConfig.Contracts { + for _, chainWriterDefinition := range contract.Configs { + chainWriterDefinition.GasLimit = defaultGasPrice + } + } + return chainWriterConfig +} diff --git a/core/services/relay/evm/bindings/chain_reader_tester.go b/core/services/relay/evm/bindings/chain_reader_tester.go new file mode 100644 index 00000000000..f15f1431679 --- /dev/null +++ b/core/services/relay/evm/bindings/chain_reader_tester.go @@ -0,0 +1,201 @@ +// Code generated evm-bindings; DO NOT EDIT. + +package bindings + +import ( + "context" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + "math/big" +) + +// CodeDetails methods inputs and outputs structs +type ChainReaderTester struct { + BoundContract types.BoundContract + ContractReader types.ContractReader + ChainWriter types.ChainWriter +} + +type AccountStruct struct { + Account []byte + AccountStr []byte +} + +type AddTestStructInput struct { + Field int32 + DifferentField string + OracleId uint8 + OracleIds [32]uint8 + AccountStruct AccountStruct + Accounts [][]byte + BigField *big.Int + NestedDynamicStruct MidLevelDynamicTestStruct + NestedStaticStruct MidLevelStaticTestStruct +} + +type GetAlterablePrimitiveValueOutput struct { + Value uint64 +} + +type GetDifferentPrimitiveValueOutput struct { + Value uint64 +} + +type GetElementAtIndexInput struct { + I *big.Int +} + +type GetPrimitiveValueOutput struct { + Value uint64 +} + +type GetSliceValueOutput struct { + Value []uint64 +} + +type InnerDynamicTestStruct struct { + IntVal int64 + S string +} + +type InnerStaticTestStruct struct { + IntVal int64 + A []byte +} + +type MidLevelDynamicTestStruct struct { + FixedBytes [2]uint8 + Inner InnerDynamicTestStruct +} + +type MidLevelStaticTestStruct struct { + FixedBytes [2]uint8 + Inner InnerStaticTestStruct +} + +type ReturnSeenInput struct { + Field int32 + DifferentField string + OracleId uint8 + OracleIds [32]uint8 + AccountStruct AccountStruct + Accounts [][]byte + BigField *big.Int + NestedDynamicStruct MidLevelDynamicTestStruct + NestedStaticStruct MidLevelStaticTestStruct +} + +type SetAlterablePrimitiveValueInput struct { + Value uint64 +} + +type TestStruct struct { + Field int32 + DifferentField string + OracleId uint8 + OracleIds [32]uint8 + AccountStruct AccountStruct + Accounts [][]byte + BigField *big.Int + NestedDynamicStruct MidLevelDynamicTestStruct + NestedStaticStruct MidLevelStaticTestStruct +} + +type TriggerEventInput struct { + Field int32 + OracleId uint8 + NestedDynamicStruct MidLevelDynamicTestStruct + NestedStaticStruct MidLevelStaticTestStruct + OracleIds [32]uint8 + AccountStruct AccountStruct + Accounts [][]byte + DifferentField string + BigField *big.Int +} + +type TriggerEventWithDynamicTopicInput struct { + Field string +} + +type TriggerStaticBytesInput struct { + Val1 uint32 + Val2 uint32 + Val3 uint32 + Val4 uint64 + Val5 [32]uint8 + Val6 [32]uint8 + Val7 [32]uint8 + Raw []uint8 +} + +type TriggerWithFourTopicsInput struct { + Field1 int32 + Field2 int32 + Field3 int32 +} + +type TriggerWithFourTopicsWithHashedInput struct { + Field1 string + Field2 [32]uint8 + Field3 [32]uint8 +} + +func (b ChainReaderTester) GetPrimitiveValue(ctx context.Context, confidence primitives.ConfidenceLevel) (uint64, error) { + var output uint64 + err := b.ContractReader.GetLatestValue(ctx, b.BoundContract.ReadIdentifier("GetPrimitiveValue"), confidence, nil, &output) + return output, err +} + +func (b ChainReaderTester) GetSliceValue(ctx context.Context, confidence primitives.ConfidenceLevel) ([]uint64, error) { + var output []uint64 + err := b.ContractReader.GetLatestValue(ctx, b.BoundContract.ReadIdentifier("GetSliceValue"), confidence, nil, &output) + return output, err +} + +func (b ChainReaderTester) ReturnSeen(ctx context.Context, input ReturnSeenInput, confidence primitives.ConfidenceLevel) (TestStruct, error) { + output := TestStruct{} + err := b.ContractReader.GetLatestValue(ctx, b.BoundContract.ReadIdentifier("ReturnSeen"), confidence, input, &output) + return output, err +} + +func (b ChainReaderTester) TriggerEvent(ctx context.Context, input TriggerEventInput, txId string, toAddress string, meta *types.TxMeta) error { + return b.ChainWriter.SubmitTransaction(ctx, "ChainReaderTester", "TriggerEvent", input, txId, toAddress, meta, big.NewInt(0)) +} + +func (b ChainReaderTester) GetDifferentPrimitiveValue(ctx context.Context, confidence primitives.ConfidenceLevel) (uint64, error) { + var output uint64 + err := b.ContractReader.GetLatestValue(ctx, b.BoundContract.ReadIdentifier("GetDifferentPrimitiveValue"), confidence, nil, &output) + return output, err +} + +func (b ChainReaderTester) GetElementAtIndex(ctx context.Context, input GetElementAtIndexInput, confidence primitives.ConfidenceLevel) (TestStruct, error) { + output := TestStruct{} + err := b.ContractReader.GetLatestValue(ctx, b.BoundContract.ReadIdentifier("GetElementAtIndex"), confidence, input, &output) + return output, err +} + +func (b ChainReaderTester) SetAlterablePrimitiveValue(ctx context.Context, input SetAlterablePrimitiveValueInput, txId string, toAddress string, meta *types.TxMeta) error { + return b.ChainWriter.SubmitTransaction(ctx, "ChainReaderTester", "SetAlterablePrimitiveValue", input, txId, toAddress, meta, big.NewInt(0)) +} + +func (b ChainReaderTester) TriggerEventWithDynamicTopic(ctx context.Context, input TriggerEventWithDynamicTopicInput, txId string, toAddress string, meta *types.TxMeta) error { + return b.ChainWriter.SubmitTransaction(ctx, "ChainReaderTester", "TriggerEventWithDynamicTopic", input, txId, toAddress, meta, big.NewInt(0)) +} + +func (b ChainReaderTester) TriggerWithFourTopics(ctx context.Context, input TriggerWithFourTopicsInput, txId string, toAddress string, meta *types.TxMeta) error { + return b.ChainWriter.SubmitTransaction(ctx, "ChainReaderTester", "TriggerWithFourTopics", input, txId, toAddress, meta, big.NewInt(0)) +} + +func (b ChainReaderTester) TriggerWithFourTopicsWithHashed(ctx context.Context, input TriggerWithFourTopicsWithHashedInput, txId string, toAddress string, meta *types.TxMeta) error { + return b.ChainWriter.SubmitTransaction(ctx, "ChainReaderTester", "TriggerWithFourTopicsWithHashed", input, txId, toAddress, meta, big.NewInt(0)) +} + +func (b ChainReaderTester) AddTestStruct(ctx context.Context, input AddTestStructInput, txId string, toAddress string, meta *types.TxMeta) error { + return b.ChainWriter.SubmitTransaction(ctx, "ChainReaderTester", "AddTestStruct", input, txId, toAddress, meta, big.NewInt(0)) +} + +func (b ChainReaderTester) GetAlterablePrimitiveValue(ctx context.Context, confidence primitives.ConfidenceLevel) (uint64, error) { + var output uint64 + err := b.ContractReader.GetLatestValue(ctx, b.BoundContract.ReadIdentifier("GetAlterablePrimitiveValue"), confidence, nil, &output) + return output, err +} diff --git a/core/services/relay/evm/chain_components_test.go b/core/services/relay/evm/chain_components_test.go index 33a862c6ce9..3b7f529a867 100644 --- a/core/services/relay/evm/chain_components_test.go +++ b/core/services/relay/evm/chain_components_test.go @@ -206,15 +206,16 @@ func TestContractReaderEventsInitValidation(t *testing.T) { } } +//go:generate evm-chain-bindings -contracts contracts/src/v0.8/shared/test/helpers -output core/services/relay/evm/bindings func TestChainComponents(t *testing.T) { t.Parallel() it := &EVMChainComponentsInterfaceTester[*testing.T]{Helper: &helper{}} - - it.Helper.Init(t) + it.Init(t) // add new subtests here so that it can be run on real chains too RunChainComponentsEvmTests(t, it) RunChainComponentsInLoopEvmTests[*testing.T](t, commontestutils.WrapContractReaderTesterForLoop(it)) + RunChainComponentsInLoopEvmTests(t, WrapContractReaderTesterWithBindings(t, it)) } type helper struct { diff --git a/core/services/relay/evm/chain_writer_historical_wrapper_test.go b/core/services/relay/evm/chain_writer_historical_wrapper_test.go index c849d1f3d57..669ec9e7953 100644 --- a/core/services/relay/evm/chain_writer_historical_wrapper_test.go +++ b/core/services/relay/evm/chain_writer_historical_wrapper_test.go @@ -2,6 +2,7 @@ package evm import ( "context" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/bindings" "math/big" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -22,7 +23,8 @@ func NewChainWriterHistoricalWrapper(cw commontypes.ChainWriter, cwh *ClientWith } func (cwhw *ChainWriterHistoricalWrapper) SubmitTransaction(ctx context.Context, contractName, method string, args any, transactionID string, toAddress string, meta *commontypes.TxMeta, value *big.Int) error { - if primArgs, ok := args.(interfacetesttypes.PrimitiveArgs); ok { + alterablePrimitiveCall, newValue := cwhw.getPrimitiveValueIfPossible(args) + if alterablePrimitiveCall { callArgs := interfacetesttypes.ExpectedGetLatestValueArgs{ ContractName: contractName, ReadName: "GetAlterablePrimitiveValue", @@ -30,10 +32,25 @@ func (cwhw *ChainWriterHistoricalWrapper) SubmitTransaction(ctx context.Context, Params: nil, ReturnVal: nil, } - err := cwhw.cwh.SetUintLatestValue(ctx, primArgs.Value, callArgs) + err := cwhw.cwh.SetUintLatestValue(ctx, newValue, callArgs) if err != nil { return err } } return cwhw.ChainWriter.SubmitTransaction(ctx, contractName, method, args, transactionID, toAddress, meta, value) } + +func (cwhw *ChainWriterHistoricalWrapper) getPrimitiveValueIfPossible(args any) (bool, uint64) { + primitiveArgs, alterablePrimitiveCall := args.(interfacetesttypes.PrimitiveArgs) + var newValue uint64 + var alterablePrimitiveValue bindings.SetAlterablePrimitiveValueInput + if alterablePrimitiveCall { + newValue = primitiveArgs.Value + } else { + alterablePrimitiveValue, alterablePrimitiveCall = args.(bindings.SetAlterablePrimitiveValueInput) + if alterablePrimitiveCall { + newValue = alterablePrimitiveValue.Value + } + } + return alterablePrimitiveCall, newValue +} diff --git a/core/services/relay/evm/evmtesting/bindings_test_adapter.go b/core/services/relay/evm/evmtesting/bindings_test_adapter.go new file mode 100644 index 00000000000..c3c7d3ccab1 --- /dev/null +++ b/core/services/relay/evm/evmtesting/bindings_test_adapter.go @@ -0,0 +1,518 @@ +package evmtesting + +import ( + "context" + "errors" + "fmt" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/go-viper/mapstructure/v2" + "github.com/smartcontractkit/chainlink-common/pkg/codec" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/bindings" + evmcodec "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + "math/big" + "reflect" + "strings" + "testing" +) + +const contractName = "ChainReaderTester" + +// Wraps EVMChainComponentsInterfaceTester to rely on the EVM bindings generated for CR/CW instead of going directly to CR/CW. This way we can reuse all existing tests. Transformation between expected +// contract names and read keys will be done here as well as invocation delegation to generated code. +func WrapContractReaderTesterWithBindings(t *testing.T, wrapped *EVMChainComponentsInterfaceTester[*testing.T]) interfacetests.ChainComponentsInterfaceTester[*testing.T] { + //Tests not yet supported by EVM bindings. + wrapped.DisableTests([]string{ + interfacetests.GetLatestValueAsValuesDotValue, interfacetests.GetLatestValueNoArgumentsAndPrimitiveReturnAsValuesDotValue, interfacetests.GetLatestValueNoArgumentsAndSliceReturnAsValueDotValue, + interfacetests.GetLatestValueGetsLatestForEvent, interfacetests.GetLatestValueBasedOnConfidenceLevelForEvent, + interfacetests.GetLatestValueReturnsNotFoundWhenNotTriggeredForEvent, interfacetests.GetLatestValueWithFilteringForEvent, interfacetests.BatchGetLatestValue, interfacetests.BatchGetLatestValueMultipleContractNamesSameFunction, + interfacetests.BatchGetLatestValueDifferentParamsResultsRetainOrder, interfacetests.BatchGetLatestValueDifferentParamsResultsRetainOrderMultipleContracts, interfacetests.BatchGetLatestValueNoArgumentsPrimitiveReturn, + interfacetests.BatchGetLatestValueSetsErrorsProperly, interfacetests.BatchGetLatestValueNoArgumentsWithSliceReturn, interfacetests.BatchGetLatestValueWithModifiersOwnMapstructureOverride, + interfacetests.QueryKeyNotFound, interfacetests.QueryKeyReturnsData, interfacetests.QueryKeyReturnsDataAsValuesDotValue, interfacetests.QueryKeyReturnsDataAsValuesDotValue, + interfacetests.QueryKeyCanFilterWithValueComparator, interfacetests.QueryKeyCanLimitResultsWithCursor, + QueryKeyFilterOnDataWordsWithValueComparator, QueryKeyOnDataWordsWithValueComparatorOnNestedField, + QueryKeyFilterOnDataWordsWithValueComparatorOnDynamicField, QueryKeyFilteringOnDataWordsUsingValueComparatorsOnFieldsWithManualIndex, + }) + wrapped.SetChainReaderConfigSupplier(func(t *testing.T) types.ChainReaderConfig { + return getChainReaderConfig(wrapped) + }) + wrapped.SetChainWriterConfigSupplier(func(t *testing.T) types.ChainWriterConfig { + return getChainWriterConfig(t, wrapped) + }) + return newBindingClientTester(wrapped) +} + +func newBindingClientTester(wrapped *EVMChainComponentsInterfaceTester[*testing.T]) bindingClientTester { + bindingsMapping := newBindingsMapping() + return bindingClientTester{ + ChainComponentsInterfaceTester: wrapped, + bindingsMapping: &bindingsMapping, + } +} + +func newBindingsMapping() bindingsMapping { + contractReaderProxy := bindingContractReaderProxy{} + chainWriterProxy := bindingChainWriterProxy{} + methodNameMappingByContract := make(map[string]map[string]string) + methodNameMappingByContract[interfacetests.AnyContractName] = map[string]string{ + interfacetests.MethodTakingLatestParamsReturningTestStruct: "GetElementAtIndex", + interfacetests.MethodReturningSeenStruct: "ReturnSeen", + interfacetests.MethodReturningAlterableUint64: "GetAlterablePrimitiveValue", + interfacetests.MethodReturningUint64: "GetPrimitiveValue", + interfacetests.MethodReturningUint64Slice: "getSliceValue", + interfacetests.MethodSettingStruct: "AddTestStruct", + interfacetests.MethodSettingUint64: "SetAlterablePrimitiveValue", + interfacetests.MethodTriggeringEvent: "TriggerEvent", + } + methodNameMappingByContract[interfacetests.AnySecondContractName] = map[string]string{ + interfacetests.MethodReturningUint64: "GetDifferentPrimitiveValue", + } + + bindingsMapping := bindingsMapping{ + contractNameMapping: map[string]string{ + interfacetests.AnyContractName: contractName, + interfacetests.AnySecondContractName: contractName, + }, + methodNameMappingByContract: methodNameMappingByContract, + contractReaderProxy: &contractReaderProxy, + chainWriterProxy: &chainWriterProxy, + chainReaderTesters: map[string]*bindings.ChainReaderTester{}, + } + contractReaderProxy.bm = &bindingsMapping + chainWriterProxy.bm = &bindingsMapping + bindingsMapping.createDelegates() + return bindingsMapping +} + +func getChainReaderConfig(wrapped *EVMChainComponentsInterfaceTester[*testing.T]) types.ChainReaderConfig { + testStruct := interfacetests.CreateTestStruct[*testing.T](0, wrapped) + chainReaderConfig := bindings.NewChainReaderConfig() + chainReaderConfig.Contracts["ChainReaderTester"].Configs["ReturnSeen"] = &types.ChainReaderDefinition{ + CacheEnabled: false, + ChainSpecificName: "returnSeen", + ReadType: 0, + InputModifications: codec.ModifiersConfig{ + &codec.HardCodeModifierConfig{ + OnChainValues: map[string]any{ + "BigField": testStruct.BigField.String(), + "AccountStruct.Account": hexutil.Encode(testStruct.AccountStruct.Account), + }, + }, + }, + OutputModifications: codec.ModifiersConfig{ + &codec.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": interfacetests.AnyExtraValue}}, + }, + } + return chainReaderConfig +} + +func getChainWriterConfig(t *testing.T, wrapped *EVMChainComponentsInterfaceTester[*testing.T]) types.ChainWriterConfig { + return bindings.NewChainWriterConfig(*assets.NewWei(big.NewInt(1000000000000000000)), 2_000_000, wrapped.Helper.Accounts(t)[1].From) +} + +func (b bindingClientTester) Name() string { + return "generated bindings" +} + +type bindingClientTester struct { + interfacetests.ChainComponentsInterfaceTester[*testing.T] + bindingsMapping *bindingsMapping +} + +func (b bindingClientTester) GetContractReader(t *testing.T) commontypes.ContractReader { + contractReader := b.ChainComponentsInterfaceTester.GetContractReader(t) + if b.bindingsMapping.contractReaderProxy.ContractReader == nil { + b.bindingsMapping.contractReaderProxy.ContractReader = contractReader + b.addDefaultBindings(t) + for _, tester := range b.bindingsMapping.chainReaderTesters { + tester.ContractReader = contractReader + } + } + return b.bindingsMapping.contractReaderProxy +} + +func (b bindingClientTester) addDefaultBindings(t *testing.T) { + defaultBindings := b.ChainComponentsInterfaceTester.GetBindings(t) + for _, binding := range defaultBindings { + chainReaderTester := b.bindingsMapping.chainReaderTesters[binding.Address] + if chainReaderTester == nil { + chainReaderTester = &bindings.ChainReaderTester{ + BoundContract: binding, + ChainWriter: b.bindingsMapping.chainWriterProxy.ChainWriter, + } + b.bindingsMapping.chainReaderTesters[binding.Address] = chainReaderTester + } else { + chainReaderTester.ChainWriter = b.bindingsMapping.chainWriterProxy.ChainWriter + } + } +} + +func (b bindingClientTester) GetChainWriter(t *testing.T) commontypes.ChainWriter { + chainWriter := b.ChainComponentsInterfaceTester.GetChainWriter(t) + if b.bindingsMapping.chainWriterProxy.ChainWriter == nil { + b.addDefaultBindings(t) + for _, tester := range b.bindingsMapping.chainReaderTesters { + tester.ChainWriter = chainWriter + } + b.bindingsMapping.chainWriterProxy.ChainWriter = chainWriter + } + return b.bindingsMapping.chainWriterProxy +} + +type bindingsMapping struct { + contractNameMapping map[string]string + methodNameMappingByContract map[string]map[string]string + delegates map[string]*Delegate + chainReaderTesters map[string]*bindings.ChainReaderTester + contractReaderProxy *bindingContractReaderProxy + chainWriterProxy *bindingChainWriterProxy +} + +type bindingContractReaderProxy struct { + commontypes.ContractReader + bm *bindingsMapping +} + +type bindingChainWriterProxy struct { + commontypes.ChainWriter + bm *bindingsMapping +} + +func (b bindingContractReaderProxy) Bind(ctx context.Context, boundContracts []commontypes.BoundContract) error { + updatedBindings := b.bm.translateContractNames(boundContracts) + for _, updatedBinding := range updatedBindings { + b.bm.chainReaderTesters[updatedBinding.Address] = &bindings.ChainReaderTester{ + BoundContract: updatedBinding, + ContractReader: b.ContractReader, + ChainWriter: b.bm.chainWriterProxy.ChainWriter, + } + } + return b.ContractReader.Bind(ctx, updatedBindings) +} + +func (b bindingsMapping) translateContractNames(boundContracts []commontypes.BoundContract) []commontypes.BoundContract { + updatedBindings := []commontypes.BoundContract{} + for _, boundContract := range boundContracts { + updatedBindings = append(updatedBindings, commontypes.BoundContract{ + boundContract.Address, + b.translateContractName(boundContract.Name), + }) + } + return updatedBindings +} + +func (b bindingContractReaderProxy) Close() error { + return b.ContractReader.Close() +} + +func (b bindingContractReaderProxy) GetLatestValue(ctx context.Context, readKey string, confidenceLevel primitives.ConfidenceLevel, params, returnVal any) error { + delegate, err := b.bm.getBindingDelegate(readKey) + if err != nil { + return err + } + output, err := delegate.apply(ctx, readKey, params, confidenceLevel) + if err != nil { + return err + } + if output == nil { + return nil + } + err = convertStruct(output, returnVal) + if err != nil { + return err + } + return nil +} + +func (b bindingChainWriterProxy) SubmitTransaction(ctx context.Context, contract, method string, args any, transactionID string, toAddress string, meta *commontypes.TxMeta, value *big.Int) error { + chainReaderTesters := b.bm.chainReaderTesters[toAddress] + switch contract { + case interfacetests.AnyContractName, interfacetests.AnySecondContractName: + switch method { + case interfacetests.MethodSettingStruct: + bindingsInput := bindings.AddTestStructInput{} + convertStruct(args, &bindingsInput) + return chainReaderTesters.AddTestStruct(ctx, bindingsInput, transactionID, toAddress, meta) + case interfacetests.MethodSettingUint64: + bindingsInput := bindings.SetAlterablePrimitiveValueInput{} + convertStruct(args, &bindingsInput) + return chainReaderTesters.SetAlterablePrimitiveValue(ctx, bindingsInput, transactionID, toAddress, meta) + case interfacetests.MethodTriggeringEvent: + bindingsInput := bindings.TriggerEventInput{} + convertStruct(args, &bindingsInput) + return chainReaderTesters.TriggerEvent(ctx, bindingsInput, transactionID, toAddress, meta) + default: + return errors.New("No logic implemented for method: " + method) + } + default: + return errors.New("contract with id not supported " + contract) + } +} + +func (b *bindingChainWriterProxy) GetTransactionStatus(ctx context.Context, transactionID string) (commontypes.TransactionStatus, error) { + return b.ChainWriter.GetTransactionStatus(ctx, transactionID) +} + +func removeAddressFromReadIdentifier(s string) string { + index := strings.Index(s, "-") + if index == -1 { + return s + } + return s[index+1:] +} + +func (b *bindingsMapping) createDelegates() { + delegates := make(map[string]*Delegate) + boundContract := commontypes.BoundContract{Address: "", Name: contractName} + methodTakingLatestParamsKey := removeAddressFromReadIdentifier(boundContract.ReadIdentifier(b.methodNameMappingByContract[interfacetests.AnyContractName][interfacetests.MethodTakingLatestParamsReturningTestStruct])) + delegates[methodTakingLatestParamsKey] = b.createDelegateForMethodTakingLatestParams() + methodReturningAlterableUint64Key := removeAddressFromReadIdentifier(boundContract.ReadIdentifier(b.methodNameMappingByContract[interfacetests.AnyContractName][interfacetests.MethodReturningAlterableUint64])) + delegates[methodReturningAlterableUint64Key] = b.createDelegateForMethodReturningAlterableUint64() + methodReturningSeenStructKey := removeAddressFromReadIdentifier(boundContract.ReadIdentifier(b.methodNameMappingByContract[interfacetests.AnyContractName][interfacetests.MethodReturningSeenStruct])) + delegates[methodReturningSeenStructKey] = b.createDelegateForMethodReturningSeenStruct() + methodReturningUint64Key := removeAddressFromReadIdentifier(boundContract.ReadIdentifier(b.methodNameMappingByContract[interfacetests.AnyContractName][interfacetests.MethodReturningUint64])) + delegates[methodReturningUint64Key] = b.createDelegateForMethodReturningUint64() + methodReturningUint64SliceKey := removeAddressFromReadIdentifier(boundContract.ReadIdentifier(b.methodNameMappingByContract[interfacetests.AnyContractName][interfacetests.MethodReturningUint64Slice])) + delegates[methodReturningUint64SliceKey] = b.createDelegateForMethodReturningUint64Slice() + methodReturningDifferentUint64Key := removeAddressFromReadIdentifier(boundContract.ReadIdentifier(b.methodNameMappingByContract[interfacetests.AnySecondContractName][interfacetests.MethodReturningUint64])) + delegates[methodReturningDifferentUint64Key] = b.createDelegateForSecondContractMethodReturningUint64() + b.delegates = delegates +} + +func (b *bindingsMapping) createDelegateForMethodTakingLatestParams() *Delegate { + delegate := Delegate{inputType: reflect.TypeOf(bindings.GetElementAtIndexInput{})} + delegate.delegateFunc = func(ctx context.Context, readyKey string, input *any, level primitives.ConfidenceLevel) (any, error) { + methodInvocation := func(ctx context.Context, readKey string, input *bindings.GetElementAtIndexInput, level primitives.ConfidenceLevel) (any, error) { + chainReaderTester := b.GetChainReaderTester(readKey) + return chainReaderTester.GetElementAtIndex(ctx, *input, level) + } + return invokeSpecificMethod(ctx, b.translateReadKey(readyKey), (*input).(*bindings.GetElementAtIndexInput), level, methodInvocation) + } + return &delegate +} + +func (b *bindingsMapping) createDelegateForMethodReturningAlterableUint64() *Delegate { + delegate := Delegate{} + delegate.delegateFunc = func(ctx context.Context, readyKey string, input *any, level primitives.ConfidenceLevel) (any, error) { + methodInvocation := func(ctx context.Context, readKey string, input any, level primitives.ConfidenceLevel) (any, error) { + chainReaderTester := b.GetChainReaderTester(readKey) + return chainReaderTester.GetAlterablePrimitiveValue(ctx, level) + } + return invokeSpecificMethod(ctx, b.translateReadKey(readyKey), nil, level, methodInvocation) + } + return &delegate +} + +func (b *bindingsMapping) createDelegateForMethodReturningSeenStruct() *Delegate { + delegate := Delegate{inputType: reflect.TypeOf(bindings.ReturnSeenInput{})} + delegate.delegateFunc = func(ctx context.Context, readyKey string, input *any, level primitives.ConfidenceLevel) (any, error) { + methodInvocation := func(ctx context.Context, readKey string, input *bindings.ReturnSeenInput, level primitives.ConfidenceLevel) (any, error) { + chainReaderTester := b.GetChainReaderTester(readKey) + return chainReaderTester.ReturnSeen(ctx, *input, level) + } + return invokeSpecificMethod(ctx, b.translateReadKey(readyKey), (*input).(*bindings.ReturnSeenInput), level, methodInvocation) + } + return &delegate +} + +func (b *bindingsMapping) createDelegateForMethodReturningUint64() *Delegate { + delegate := Delegate{} + delegate.delegateFunc = func(ctx context.Context, readyKey string, input *any, level primitives.ConfidenceLevel) (any, error) { + methodInvocation := func(ctx context.Context, readKey string, input any, level primitives.ConfidenceLevel) (any, error) { + chainReaderTester := b.GetChainReaderTester(readKey) + return chainReaderTester.GetPrimitiveValue(ctx, level) + } + return invokeSpecificMethod(ctx, b.translateReadKey(readyKey), nil, level, methodInvocation) + } + return &delegate +} + +func (b *bindingsMapping) createDelegateForMethodReturningUint64Slice() *Delegate { + delegate := Delegate{} + delegate.delegateFunc = func(ctx context.Context, readyKey string, input *any, level primitives.ConfidenceLevel) (any, error) { + methodInvocation := func(ctx context.Context, readKey string, input any, level primitives.ConfidenceLevel) (any, error) { + chainReaderTester := b.GetChainReaderTester(readKey) + return chainReaderTester.GetSliceValue(ctx, level) + } + return invokeSpecificMethod(ctx, b.translateReadKey(readyKey), nil, level, methodInvocation) + } + return &delegate +} + +func (b *bindingsMapping) createDelegateForSecondContractMethodReturningUint64() *Delegate { + delegate := Delegate{} + delegate.delegateFunc = func(ctx context.Context, readyKey string, input *any, level primitives.ConfidenceLevel) (any, error) { + methodInvocation := func(ctx context.Context, readKey string, input any, level primitives.ConfidenceLevel) (any, error) { + chainReaderTester := b.GetChainReaderTester(readKey) + return chainReaderTester.GetDifferentPrimitiveValue(ctx, level) + } + return invokeSpecificMethod(ctx, b.translateReadKey(readyKey), nil, level, methodInvocation) + } + return &delegate +} + +// Transforms a readKey from ChainReader using the generic testing config to the actual config being used with go bindings which is the auto-generated from the solidity contract. +func (b bindingsMapping) translateReadKey(key string) string { + var updatedKey = key + parts := strings.Split(key, "-") + contractName := parts[1] + methodName := parts[2] + for testConfigName, bindingsName := range b.contractNameMapping { + if contractName == testConfigName { + updatedKey = strings.Replace(updatedKey, testConfigName, bindingsName, 1) + } + } + for testConfigName, bindingsName := range b.methodNameMappingByContract[contractName] { + if methodName == testConfigName { + updatedKey = strings.Replace(updatedKey, testConfigName, bindingsName, 1) + } + } + return updatedKey +} + +// Transforms a readKey from ChainReader using the generic testing config to the actual config being used with go bindings which is the auto-generated from the solidity contract. +func (b bindingsMapping) translateContractName(contractName string) string { + for testContractName, bindingsName := range b.contractNameMapping { + if contractName == testContractName { + return bindingsName + } + } + return contractName +} + +func invokeSpecificMethod[T any](ctx context.Context, readKey string, input T, level primitives.ConfidenceLevel, methodInvocation func(ctx context.Context, readKey string, input T, level primitives.ConfidenceLevel) (any, error)) (any, error) { + return methodInvocation(ctx, readKey, input, level) +} + +func (b bindingsMapping) getBindingDelegate(readKey string) (*Delegate, error) { + translatedKey := removeAddressFromReadIdentifier(b.translateReadKey(readKey)) + delegate := b.delegates[translatedKey] + + if delegate == nil { + return nil, fmt.Errorf("delegate not found for readerKey %s", translatedKey) + } + return delegate, nil +} + +func (b bindingsMapping) GetChainReaderTester(key string) *bindings.ChainReaderTester { + address := key[0:strings.Index(key, "-")] + return b.chainReaderTesters[address] +} + +type Delegate struct { + inputType reflect.Type + delegateFunc func(context.Context, string, *any, primitives.ConfidenceLevel) (any, error) +} + +func (d Delegate) getInput(input any) (*any, error) { + if input == nil { + return nil, nil + } + adaptedInput := reflect.New(d.inputType).Interface() + err := convertStruct(input, adaptedInput) + if err != nil { + return nil, err + } + return &adaptedInput, nil +} + +func (d Delegate) apply(ctx context.Context, readKey string, input any, confidenceLevel primitives.ConfidenceLevel) (any, error) { + adaptedInput, err := d.getInput(input) + if err != nil { + return nil, err + } + output, err := d.delegateFunc(ctx, readKey, adaptedInput, confidenceLevel) + if err != nil { + return nil, err + } + return output, nil +} + +// Utility function to converted original types from and to bindings expected types. +func convertStruct(src any, dst any) error { + if reflect.TypeOf(src).Kind() == reflect.Ptr && reflect.TypeOf(dst).Kind() == reflect.Ptr && reflect.TypeOf(src).Elem() == reflect.TypeOf(interfacetests.LatestParams{}) && reflect.TypeOf(dst).Elem() == reflect.TypeOf(bindings.GetElementAtIndexInput{}) { + value := (*src.(*interfacetests.LatestParams)).I + dst.(*bindings.GetElementAtIndexInput).I = big.NewInt(int64(value)) + return nil + } + decoder, err := createDecoder(dst) + if err != nil { + return err + } + err = decoder.Decode(src) + if err != nil { + return err + } + if reflect.TypeOf(dst).Elem() == reflect.TypeOf(interfacetests.TestStructWithExtraField{}) { + destTestStruct := dst.(*interfacetests.TestStructWithExtraField) + if destTestStruct != nil { + auxTestStruct := &interfacetests.TestStruct{} + decoder, _ := createDecoder(auxTestStruct) + decoder.Decode(src) + destTestStruct.TestStruct = *auxTestStruct + sourceTestStruct := src.(bindings.TestStruct) + destTestStruct.BigField = sourceTestStruct.BigField + destTestStruct.NestedStaticStruct.Inner.I = int(sourceTestStruct.NestedStaticStruct.Inner.IntVal) + destTestStruct.NestedStaticStruct.FixedBytes = sourceTestStruct.NestedStaticStruct.FixedBytes + destTestStruct.NestedDynamicStruct.Inner.I = int(sourceTestStruct.NestedDynamicStruct.Inner.IntVal) + destTestStruct.NestedDynamicStruct.FixedBytes = sourceTestStruct.NestedDynamicStruct.FixedBytes + destTestStruct.ExtraField = interfacetests.AnyExtraValue + } + } else if reflect.TypeOf(dst).Elem() == reflect.TypeOf(interfacetests.TestStruct{}) { + destTestStruct := dst.(*interfacetests.TestStruct) + if destTestStruct != nil { + sourceTestStruct := src.(bindings.TestStruct) + destTestStruct.BigField = sourceTestStruct.BigField + destTestStruct.NestedStaticStruct.Inner.I = int(sourceTestStruct.NestedStaticStruct.Inner.IntVal) + destTestStruct.NestedStaticStruct.FixedBytes = sourceTestStruct.NestedStaticStruct.FixedBytes + destTestStruct.NestedDynamicStruct.Inner.I = int(sourceTestStruct.NestedDynamicStruct.Inner.IntVal) + destTestStruct.NestedDynamicStruct.FixedBytes = sourceTestStruct.NestedDynamicStruct.FixedBytes + } + } else if reflect.TypeOf(src) == reflect.TypeOf(interfacetests.TestStruct{}) && reflect.TypeOf(dst) == reflect.TypeOf(&bindings.AddTestStructInput{}) { + destTestStruct := dst.(*bindings.AddTestStructInput) + if destTestStruct != nil { + sourceTestStruct := src.(interfacetests.TestStruct) + destTestStruct.BigField = sourceTestStruct.BigField + destTestStruct.NestedStaticStruct.Inner.IntVal = int64(sourceTestStruct.NestedStaticStruct.Inner.I) + destTestStruct.NestedStaticStruct.FixedBytes = sourceTestStruct.NestedStaticStruct.FixedBytes + destTestStruct.NestedDynamicStruct.Inner.IntVal = int64(sourceTestStruct.NestedDynamicStruct.Inner.I) + destTestStruct.NestedDynamicStruct.FixedBytes = sourceTestStruct.NestedDynamicStruct.FixedBytes + } + } else if reflect.TypeOf(src) == reflect.TypeOf(interfacetests.TestStruct{}) && reflect.TypeOf(dst) == reflect.TypeOf(&bindings.ReturnSeenInput{}) { + destTestStruct := dst.(*bindings.ReturnSeenInput) + if destTestStruct != nil { + sourceTestStruct := src.(interfacetests.TestStruct) + destTestStruct.BigField = sourceTestStruct.BigField + destTestStruct.NestedStaticStruct.Inner.IntVal = int64(sourceTestStruct.NestedStaticStruct.Inner.I) + destTestStruct.NestedStaticStruct.FixedBytes = sourceTestStruct.NestedStaticStruct.FixedBytes + destTestStruct.NestedDynamicStruct.Inner.IntVal = int64(sourceTestStruct.NestedDynamicStruct.Inner.I) + destTestStruct.NestedDynamicStruct.FixedBytes = sourceTestStruct.NestedDynamicStruct.FixedBytes + } + } + return err +} + +func createDecoder(dst any) (*mapstructure.Decoder, error) { + decoderConfig := &mapstructure.DecoderConfig{ + DecodeHook: mapstructure.ComposeDecodeHookFunc( + stringToByteArrayHook, + ), + Result: dst, + } + decoder, err := mapstructure.NewDecoder(decoderConfig) + return decoder, err +} + +func stringToByteArrayHook(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) { + if from.Kind() == reflect.String && to == reflect.TypeOf([]byte{}) { + return evmcodec.EVMAddressModifier{}.DecodeAddress(data.(string)) + } + if from == reflect.TypeOf([]byte{}) && to.Kind() == reflect.String { + return evmcodec.EVMAddressModifier{}.EncodeAddress(data.([]byte)) + } + return data, nil +} diff --git a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go index 968c7667882..0803b8cbeab 100644 --- a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go +++ b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go @@ -14,7 +14,7 @@ import ( "github.com/smartcontractkit/libocr/commontypes" "github.com/stretchr/testify/require" - commoncodec "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/codec" clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" @@ -60,20 +60,24 @@ type EVMChainComponentsInterfaceTesterHelper[T TestingT[T]] interface { } type EVMChainComponentsInterfaceTester[T TestingT[T]] struct { - Helper EVMChainComponentsInterfaceTesterHelper[T] - client client.Client - address string - address2 string - contractTesters map[string]*chain_reader_tester.ChainReaderTester - chainReaderConfig types.ChainReaderConfig - chainWriterConfig types.ChainWriterConfig - deployerAuth *bind.TransactOpts - senderAuth *bind.TransactOpts - cr evm.ChainReaderService - cw evm.ChainWriterService - dirtyContracts bool - txm evmtxmgr.TxManager - gasEstimator gas.EvmFeeEstimator + TestSelectionSupport + Helper EVMChainComponentsInterfaceTesterHelper[T] + client client.Client + address string + address2 string + contractTesters map[string]*chain_reader_tester.ChainReaderTester + chainReaderConfig types.ChainReaderConfig + chainWriterConfig types.ChainWriterConfig + deployerAuth *bind.TransactOpts + senderAuth *bind.TransactOpts + cr evm.ChainReaderService + cw evm.ChainWriterService + dirtyContracts bool + txm evmtxmgr.TxManager + gasEstimator gas.EvmFeeEstimator + chainReaderConfigSupplier func(t T) types.ChainReaderConfig + chainWriterConfigSupplier func(t T) types.ChainWriterConfig + dirtyConfig bool } func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { @@ -95,7 +99,7 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { }) // can re-use the same chain for tests, just make new contract for each test - if it.client != nil { + if it.client != nil && !it.dirtyConfig { it.deployNewContracts(t) return } @@ -106,20 +110,31 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { it.deployerAuth = accounts[0] it.senderAuth = accounts[1] + it.chainReaderConfig = it.chainReaderConfigSupplier(t) + it.GetContractReader(t) + + it.txm = it.Helper.TXM(t, it.client) + it.chainWriterConfig = it.chainWriterConfigSupplier(t) + + it.deployNewContracts(t) + it.dirtyConfig = false +} + +func (it *EVMChainComponentsInterfaceTester[T]) getChainReaderConfig(t T) types.ChainReaderConfig { testStruct := CreateTestStruct[T](0, it) methodTakingLatestParamsReturningTestStructConfig := types.ChainReaderDefinition{ ChainSpecificName: "getElementAtIndex", - OutputModifications: commoncodec.ModifiersConfig{ - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, - &commoncodec.AddressBytesToStringModifierConfig{ + OutputModifications: codec.ModifiersConfig{ + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + &codec.AddressBytesToStringModifierConfig{ Fields: []string{"AccountStruct.AccountStr"}, }, }, } - it.chainReaderConfig = types.ChainReaderConfig{ + return types.ChainReaderConfig{ Contracts: map[string]types.ChainContractReader{ AnyContractName: { ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, @@ -149,10 +164,10 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { "BigField": {Name: "bigField"}, }, }, - OutputModifications: commoncodec.ModifiersConfig{ - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, - &commoncodec.AddressBytesToStringModifierConfig{ + OutputModifications: codec.ModifiersConfig{ + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + &codec.AddressBytesToStringModifierConfig{ Fields: []string{"AccountStruct.AccountStr"}, }, }, @@ -173,8 +188,8 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { EventWithFilterName: { ChainSpecificName: "Triggered", ReadType: types.Event, - OutputModifications: commoncodec.ModifiersConfig{ - &commoncodec.AddressBytesToStringModifierConfig{ + OutputModifications: codec.ModifiersConfig{ + &codec.AddressBytesToStringModifierConfig{ Fields: []string{"AccountStruct.AccountStr"}, }, }, @@ -186,8 +201,8 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { // No specific reason for filter being defined here instead of on contract level, this is just for test case variety. PollingFilter: &types.PollingFilter{}, }, - InputModifications: commoncodec.ModifiersConfig{ - &commoncodec.RenameModifierConfig{Fields: map[string]string{"FieldHash": "Field"}}, + InputModifications: codec.ModifiersConfig{ + &codec.RenameModifierConfig{Fields: map[string]string{"FieldHash": "Field"}}, }, }, triggerWithAllTopics: { @@ -208,24 +223,24 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { }, MethodReturningSeenStruct: { ChainSpecificName: "returnSeen", - InputModifications: commoncodec.ModifiersConfig{ - &commoncodec.HardCodeModifierConfig{ + InputModifications: codec.ModifiersConfig{ + &codec.HardCodeModifierConfig{ OnChainValues: map[string]any{ "BigField": testStruct.BigField.String(), "AccountStruct.Account": hexutil.Encode(testStruct.AccountStruct.Account), }, }, - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, - &commoncodec.AddressBytesToStringModifierConfig{ + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + &codec.AddressBytesToStringModifierConfig{ Fields: []string{"AccountStruct.AccountStr"}, }, }, - OutputModifications: commoncodec.ModifiersConfig{ - &commoncodec.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": AnyExtraValue}}, - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, - &commoncodec.AddressBytesToStringModifierConfig{ + OutputModifications: codec.ModifiersConfig{ + &codec.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": AnyExtraValue}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + &codec.AddressBytesToStringModifierConfig{ Fields: []string{"AccountStruct.AccountStr"}, }, }, @@ -243,10 +258,10 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { }, }, } - it.GetContractReader(t) - it.txm = it.Helper.TXM(t, it.client) +} - it.chainWriterConfig = types.ChainWriterConfig{ +func (it *EVMChainComponentsInterfaceTester[T]) getChainWriterConfig(t T) types.ChainWriterConfig { + return types.ChainWriterConfig{ Contracts: map[string]*types.ContractConfig{ AnyContractName: { ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, @@ -256,9 +271,9 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { FromAddress: it.Helper.Accounts(t)[1].From, GasLimit: 2_000_000, Checker: "simulate", - InputModifications: commoncodec.ModifiersConfig{ - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + InputModifications: codec.ModifiersConfig{ + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, }, }, "setAlterablePrimitiveValue": { @@ -272,9 +287,9 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { FromAddress: it.Helper.Accounts(t)[1].From, GasLimit: 2_000_000, Checker: "simulate", - InputModifications: commoncodec.ModifiersConfig{ - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + InputModifications: codec.ModifiersConfig{ + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, }, }, "triggerEventWithDynamicTopic": { @@ -311,9 +326,9 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { FromAddress: it.Helper.Accounts(t)[1].From, GasLimit: 2_000_000, Checker: "simulate", - InputModifications: commoncodec.ModifiersConfig{ - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, + InputModifications: codec.ModifiersConfig{ + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, }, }, }, @@ -321,7 +336,6 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { }, MaxGasPrice: assets.NewWei(big.NewInt(1000000000000000000)), } - it.deployNewContracts(t) } func (it *EVMChainComponentsInterfaceTester[T]) Name() string { @@ -460,6 +474,22 @@ func (it *EVMChainComponentsInterfaceTester[T]) MaxWaitTimeForEvents() time.Dura return it.Helper.MaxWaitTimeForEvents() } +func (it *EVMChainComponentsInterfaceTester[T]) Init(t T) { + it.Helper.Init(t) + it.chainWriterConfigSupplier = func(t T) types.ChainWriterConfig { return it.getChainWriterConfig(t) } + it.chainReaderConfigSupplier = func(t T) types.ChainReaderConfig { return it.getChainReaderConfig(t) } +} + +func (it *EVMChainComponentsInterfaceTester[T]) SetChainReaderConfigSupplier(chainReaderConfigSupplier func(t T) types.ChainReaderConfig) { + it.dirtyConfig = true + it.chainReaderConfigSupplier = chainReaderConfigSupplier +} + +func (it *EVMChainComponentsInterfaceTester[T]) SetChainWriterConfigSupplier(chainWriterConfigSupplier func(t T) types.ChainWriterConfig) { + it.dirtyConfig = true + it.chainWriterConfigSupplier = chainWriterConfigSupplier +} + func OracleIDsToBytes(oracleIDs [32]commontypes.OracleID) [32]byte { convertedIDs := [32]byte{} for i, id := range oracleIDs { diff --git a/core/services/relay/evm/evmtesting/run_tests.go b/core/services/relay/evm/evmtesting/run_tests.go index 908c4e1a81a..8c66574a5e3 100644 --- a/core/services/relay/evm/evmtesting/run_tests.go +++ b/core/services/relay/evm/evmtesting/run_tests.go @@ -21,6 +21,17 @@ import ( . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . ) +const ( + QueryKeyFilterOnDataWordsWithValueComparator = "Filtering can be done on data words using value comparator" + QueryKeyOnDataWordsWithValueComparatorOnNestedField = "Filtering can be done on data words using value comparator on a nested field" + QueryKeyFilterOnDataWordsWithValueComparatorOnDynamicField = "Filtering can be done on data words using value comparator on field that follows a dynamic field" + QueryKeyFilteringOnDataWordsUsingValueComparatorsOnFieldsWithManualIndex = "Filtering can be done on data words using value comparators on fields that require manual index input" + DynamicTypedTopicsFilterAndCorrectReturn = "Dynamically typed topics can be used to filter and have type correct in return" + MultipleTopicCanFilterTogether = "Multiple topics can filter together" + FilteringCanBeDoneOnHashedIndexedTopics = "Filtering can be done on indexed topics that get hashed" + BindReturnsErrorOnMissingContractAtAddress = "Bind returns error on missing contract at address" +) + func RunChainComponentsEvmTests[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T]) { RunContractReaderEvmTests[T](t, it) // Add ChainWriter tests here @@ -34,237 +45,291 @@ func RunChainComponentsInLoopEvmTests[T TestingT[T]](t T, it ChainComponentsInte func RunContractReaderEvmTests[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T]) { RunContractReaderInterfaceTests[T](t, it, false) - t.Run("Dynamically typed topics can be used to filter and have type correct in return", func(t T) { - it.Setup(t) - - anyString := "foo" - ctx := it.Helper.Context(t) - - cr := it.GetContractReader(t) - bindings := it.GetBindings(t) - require.NoError(t, cr.Bind(ctx, bindings)) - - type DynamicEvent struct { - Field string - } - SubmitTransactionToCW(t, it, "triggerEventWithDynamicTopic", DynamicEvent{Field: anyString}, bindings[0], types.Unconfirmed) - - input := struct{ Field string }{Field: anyString} - tp := cr.(clcommontypes.ContractTypeProvider) - - readName := types.BoundContract{ - Address: bindings[0].Address, - Name: AnyContractName, - }.ReadIdentifier(triggerWithDynamicTopic) - - output, err := tp.CreateContractType(readName, false) - require.NoError(t, err) - rOutput := reflect.Indirect(reflect.ValueOf(output)) - - require.Eventually(t, func() bool { - return cr.GetLatestValue(ctx, readName, primitives.Unconfirmed, input, output) == nil - }, it.MaxWaitTimeForEvents(), 100*time.Millisecond) - - assert.Equal(t, &anyString, rOutput.FieldByName("Field").Interface()) - topic, err := abi.MakeTopics([]any{anyString}) - require.NoError(t, err) - assert.Equal(t, &topic[0][0], rOutput.FieldByName("FieldHash").Interface()) - }) - - t.Run("Multiple topics can filter together", func(t T) { - it.Setup(t) - ctx := it.Helper.Context(t) - cr := it.GetContractReader(t) - bindings := it.GetBindings(t) - - require.NoError(t, cr.Bind(ctx, bindings)) - - triggerFourTopics(t, it, int32(1), int32(2), int32(3)) - triggerFourTopics(t, it, int32(2), int32(2), int32(3)) - triggerFourTopics(t, it, int32(1), int32(3), int32(3)) - triggerFourTopics(t, it, int32(1), int32(2), int32(4)) - - var bound types.BoundContract - for idx := range bindings { - if bindings[idx].Name == AnyContractName { - bound = bindings[idx] - } - } - - var latest struct{ Field1, Field2, Field3 int32 } - params := struct{ Field1, Field2, Field3 int32 }{Field1: 1, Field2: 2, Field3: 3} - - time.Sleep(it.MaxWaitTimeForEvents()) - - require.NoError(t, cr.GetLatestValue(ctx, bound.ReadIdentifier(triggerWithAllTopics), primitives.Unconfirmed, params, &latest)) - assert.Equal(t, int32(1), latest.Field1) - assert.Equal(t, int32(2), latest.Field2) - assert.Equal(t, int32(3), latest.Field3) - }) - - t.Run("Filtering can be done on indexed topics that get hashed", func(t T) { - it.Setup(t) - - cr := it.GetContractReader(t) - ctx := it.Helper.Context(t) - bindings := it.GetBindings(t) - - require.NoError(t, cr.Bind(ctx, bindings)) - - triggerFourTopicsWithHashed(t, it, "1", [32]uint8{2}, [32]byte{5}) - triggerFourTopicsWithHashed(t, it, "2", [32]uint8{2}, [32]byte{3}) - triggerFourTopicsWithHashed(t, it, "1", [32]uint8{3}, [32]byte{3}) - - var bound types.BoundContract - for idx := range bindings { - if bindings[idx].Name == AnyContractName { - bound = bindings[idx] - } - } - - var latest struct { - Field3 [32]byte - } - params := struct { - Field1 string - Field2 [32]uint8 - Field3 [32]byte - }{Field1: "1", Field2: [32]uint8{2}, Field3: [32]byte{5}} - - time.Sleep(it.MaxWaitTimeForEvents()) - require.NoError(t, cr.GetLatestValue(ctx, bound.ReadIdentifier(triggerWithAllTopicsWithHashed), primitives.Unconfirmed, params, &latest)) - // only checking Field3 topic makes sense since it isn't hashed, to check other fields we'd have to replicate solidity encoding and hashing - assert.Equal(t, [32]uint8{5}, latest.Field3) - }) - - t.Run("Bind returns error on missing contract at address", func(t T) { - it.Setup(t) - - addr := common.BigToAddress(big.NewInt(42)) - reader := it.GetContractReader(t) - - ctx := it.Helper.Context(t) - err := reader.Bind(ctx, []clcommontypes.BoundContract{{Name: AnyContractName, Address: addr.Hex()}}) - - require.ErrorIs(t, err, read.NoContractExistsError{Err: clcommontypes.ErrInternal, Address: addr}) - }) + testCases := []Testcase[T]{ + { + Name: DynamicTypedTopicsFilterAndCorrectReturn, + Test: func(t T) { + it.Setup(t) + + anyString := "foo" + ctx := it.Helper.Context(t) + + cr := it.GetContractReader(t) + bindings := it.GetBindings(t) + require.NoError(t, cr.Bind(ctx, bindings)) + + type DynamicEvent struct { + Field string + } + SubmitTransactionToCW(t, it, "triggerEventWithDynamicTopic", DynamicEvent{Field: anyString}, bindings[0], types.Unconfirmed) + + input := struct{ Field string }{Field: anyString} + tp := cr.(clcommontypes.ContractTypeProvider) + + readName := types.BoundContract{ + Address: bindings[0].Address, + Name: AnyContractName, + }.ReadIdentifier(triggerWithDynamicTopic) + + output, err := tp.CreateContractType(readName, false) + require.NoError(t, err) + rOutput := reflect.Indirect(reflect.ValueOf(output)) + + require.Eventually(t, func() bool { + return cr.GetLatestValue(ctx, readName, primitives.Unconfirmed, input, output) == nil + }, it.MaxWaitTimeForEvents(), 100*time.Millisecond) + + assert.Equal(t, &anyString, rOutput.FieldByName("Field").Interface()) + topic, err := abi.MakeTopics([]any{anyString}) + require.NoError(t, err) + assert.Equal(t, &topic[0][0], rOutput.FieldByName("FieldHash").Interface()) + }, + }, + { + Name: MultipleTopicCanFilterTogether, + Test: func(t T) { + it.Setup(t) + ctx := it.Helper.Context(t) + cr := it.GetContractReader(t) + bindings := it.GetBindings(t) + + require.NoError(t, cr.Bind(ctx, bindings)) + + triggerFourTopics(t, it, int32(1), int32(2), int32(3)) + triggerFourTopics(t, it, int32(2), int32(2), int32(3)) + triggerFourTopics(t, it, int32(1), int32(3), int32(3)) + triggerFourTopics(t, it, int32(1), int32(2), int32(4)) + + var bound types.BoundContract + for idx := range bindings { + if bindings[idx].Name == AnyContractName { + bound = bindings[idx] + } + } + + var latest struct{ Field1, Field2, Field3 int32 } + params := struct{ Field1, Field2, Field3 int32 }{Field1: 1, Field2: 2, Field3: 3} + + time.Sleep(it.MaxWaitTimeForEvents()) + + require.NoError(t, cr.GetLatestValue(ctx, bound.ReadIdentifier(triggerWithAllTopics), primitives.Unconfirmed, params, &latest)) + assert.Equal(t, int32(1), latest.Field1) + assert.Equal(t, int32(2), latest.Field2) + assert.Equal(t, int32(3), latest.Field3) + }, + }, + { + Name: FilteringCanBeDoneOnHashedIndexedTopics, + Test: func(t T) { + it.Setup(t) + + cr := it.GetContractReader(t) + ctx := it.Helper.Context(t) + bindings := it.GetBindings(t) + + require.NoError(t, cr.Bind(ctx, bindings)) + + triggerFourTopicsWithHashed(t, it, "1", [32]uint8{2}, [32]byte{5}) + triggerFourTopicsWithHashed(t, it, "2", [32]uint8{2}, [32]byte{3}) + triggerFourTopicsWithHashed(t, it, "1", [32]uint8{3}, [32]byte{3}) + + var bound types.BoundContract + for idx := range bindings { + if bindings[idx].Name == AnyContractName { + bound = bindings[idx] + } + } + + var latest struct { + Field3 [32]byte + } + params := struct { + Field1 string + Field2 [32]uint8 + Field3 [32]byte + }{Field1: "1", Field2: [32]uint8{2}, Field3: [32]byte{5}} + + time.Sleep(it.MaxWaitTimeForEvents()) + require.NoError(t, cr.GetLatestValue(ctx, bound.ReadIdentifier(triggerWithAllTopicsWithHashed), primitives.Unconfirmed, params, &latest)) + // only checking Field3 topic makes sense since it isn't hashed, to check other fields we'd have to replicate solidity encoding and hashing + assert.Equal(t, [32]uint8{5}, latest.Field3) + }, + }, + { + Name: BindReturnsErrorOnMissingContractAtAddress, + Test: func(t T) { + it.Setup(t) + + addr := common.BigToAddress(big.NewInt(42)) + reader := it.GetContractReader(t) + + ctx := it.Helper.Context(t) + err := reader.Bind(ctx, []clcommontypes.BoundContract{{Name: AnyContractName, Address: addr.Hex()}}) + + require.ErrorIs(t, err, read.NoContractExistsError{Err: clcommontypes.ErrInternal, Address: addr}) + }, + }, + } + RunTests(t, it, testCases) } func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T]) { RunContractReaderInterfaceTests[T](t, it, false) - it.Setup(t) - ctx := tests.Context(t) - cr := it.GetContractReader(t) - require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) - bindings := it.GetBindings(t) - boundContract := BindingsByName(bindings, AnyContractName)[0] - require.NoError(t, cr.Bind(ctx, bindings)) - - ts1 := CreateTestStruct[T](0, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) - ts2 := CreateTestStruct[T](15, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) - ts3 := CreateTestStruct[T](35, it) - _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) - - t.Run("Filtering can be done on data words using value comparator", func(t T) { - ts := &TestStruct{} - assert.Eventually(t, func() bool { - sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: EventName, Expressions: []query.Expression{ - query.Comparator("OracleID", - primitives.ValueComparator{ - Value: uint8(ts2.OracleID), - Operator: primitives.Eq, - }), + testCases := []Testcase[T]{ + { + Name: QueryKeyFilterOnDataWordsWithValueComparator, + Test: func(t T) { + ctx := tests.Context(t) + cr := it.GetContractReader(t) + require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + bindings := it.GetBindings(t) + boundContract := BindingsByName(bindings, AnyContractName)[0] + require.NoError(t, cr.Bind(ctx, bindings)) + + ts1 := CreateTestStruct[T](0, it) + _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) + ts2 := CreateTestStruct[T](15, it) + _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) + ts3 := CreateTestStruct[T](35, it) + _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) + ts := &TestStruct{} + assert.Eventually(t, func() bool { + sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: EventName, Expressions: []query.Expression{ + query.Comparator("OracleID", + primitives.ValueComparator{ + Value: uint8(ts2.OracleID), + Operator: primitives.Eq, + }), + }, + }, query.LimitAndSort{}, ts) + return err == nil && len(sequences) == 1 && reflect.DeepEqual(&ts2, sequences[0].Data) + }, it.MaxWaitTimeForEvents(), time.Millisecond*10) }, - }, query.LimitAndSort{}, ts) - return err == nil && len(sequences) == 1 && reflect.DeepEqual(&ts2, sequences[0].Data) - }, it.MaxWaitTimeForEvents(), time.Millisecond*10) - }) - - t.Run("Filtering can be done on data words using value comparator on a nested field", func(t T) { - ts := &TestStruct{} - assert.Eventually(t, func() bool { - sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: EventName, Expressions: []query.Expression{ - query.Comparator("OracleID", - primitives.ValueComparator{ - Value: uint8(ts2.OracleID), - Operator: primitives.Eq, - }), - query.Comparator("NestedStaticStruct.Inner.IntVal", - primitives.ValueComparator{ - Value: ts2.NestedStaticStruct.Inner.I, - Operator: primitives.Eq, - }), + }, + { + Name: QueryKeyOnDataWordsWithValueComparatorOnNestedField, + Test: func(t T) { + ctx := tests.Context(t) + cr := it.GetContractReader(t) + require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + bindings := it.GetBindings(t) + boundContract := BindingsByName(bindings, AnyContractName)[0] + require.NoError(t, cr.Bind(ctx, bindings)) + + ts1 := CreateTestStruct[T](0, it) + _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) + ts2 := CreateTestStruct[T](15, it) + _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) + ts3 := CreateTestStruct[T](35, it) + _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) + ts := &TestStruct{} + assert.Eventually(t, func() bool { + sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: EventName, Expressions: []query.Expression{ + query.Comparator("OracleID", + primitives.ValueComparator{ + Value: uint8(ts2.OracleID), + Operator: primitives.Eq, + }), + query.Comparator("NestedStaticStruct.Inner.IntVal", + primitives.ValueComparator{ + Value: ts2.NestedStaticStruct.Inner.I, + Operator: primitives.Eq, + }), + }, + }, query.LimitAndSort{}, ts) + return err == nil && len(sequences) == 1 && reflect.DeepEqual(&ts2, sequences[0].Data) + }, it.MaxWaitTimeForEvents(), time.Millisecond*10) }, - }, query.LimitAndSort{}, ts) - return err == nil && len(sequences) == 1 && reflect.DeepEqual(&ts2, sequences[0].Data) - }, it.MaxWaitTimeForEvents(), time.Millisecond*10) - }) - - t.Run("Filtering can be done on data words using value comparator on field that follows a dynamic field", func(t T) { - ts := &TestStruct{} - assert.Eventually(t, func() bool { - sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: EventName, Expressions: []query.Expression{ - query.Comparator("OracleID", - primitives.ValueComparator{ - Value: uint8(ts2.OracleID), - Operator: primitives.Eq, - }), - query.Comparator("BigField", - primitives.ValueComparator{ - Value: ts2.BigField, - Operator: primitives.Eq, - }), + }, + { + Name: QueryKeyFilterOnDataWordsWithValueComparatorOnDynamicField, + Test: func(t T) { + ctx := tests.Context(t) + cr := it.GetContractReader(t) + require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + bindings := it.GetBindings(t) + boundContract := BindingsByName(bindings, AnyContractName)[0] + require.NoError(t, cr.Bind(ctx, bindings)) + + ts1 := CreateTestStruct[T](0, it) + _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts1, boundContract, types.Unconfirmed) + ts2 := CreateTestStruct[T](15, it) + _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts2, boundContract, types.Unconfirmed) + ts3 := CreateTestStruct[T](35, it) + _ = SubmitTransactionToCW(t, it, MethodTriggeringEvent, ts3, boundContract, types.Unconfirmed) + ts := &TestStruct{} + assert.Eventually(t, func() bool { + sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: EventName, Expressions: []query.Expression{ + query.Comparator("OracleID", + primitives.ValueComparator{ + Value: uint8(ts2.OracleID), + Operator: primitives.Eq, + }), + query.Comparator("BigField", + primitives.ValueComparator{ + Value: ts2.BigField, + Operator: primitives.Eq, + }), + }, + }, query.LimitAndSort{}, ts) + return err == nil && len(sequences) == 1 && reflect.DeepEqual(&ts2, sequences[0].Data) + }, it.MaxWaitTimeForEvents(), time.Millisecond*10) }, - }, query.LimitAndSort{}, ts) - return err == nil && len(sequences) == 1 && reflect.DeepEqual(&ts2, sequences[0].Data) - }, it.MaxWaitTimeForEvents(), time.Millisecond*10) - }) - - t.Run("Filtering can be done on data words using value comparators on fields that require manual index input", func(t T) { - empty12Bytes := [12]byte{} - val1, val2, val3, val4 := uint32(1), uint32(2), uint32(3), uint64(4) - val5, val6, val7 := [32]byte{}, [32]byte{6}, [32]byte{7} - copy(val5[:], append(empty12Bytes[:], 5)) - raw := []byte{9, 8} - - var buf []byte - buf = binary.BigEndian.AppendUint32(buf, val1) - buf = binary.BigEndian.AppendUint32(buf, val2) - buf = binary.BigEndian.AppendUint32(buf, val3) - buf = binary.BigEndian.AppendUint64(buf, val4) - dataWordOnChainValueToQuery := buf[:] - - resExpected := append(buf, common.LeftPadBytes(val5[:], 32)...) - resExpected = append(resExpected, common.LeftPadBytes(val6[:], 32)...) - resExpected = append(resExpected, common.LeftPadBytes(val7[:], 32)...) - resExpected = append(resExpected, raw...) - - type eventResAsStruct struct { - Message *[]uint8 - } - wrapExpectedRes := eventResAsStruct{Message: &resExpected} - - // emit the one we want to search for and a couple of random ones to confirm that filtering works - triggerStaticBytes(t, it, val1, val2, val3, val4, val5, val6, val7, raw) - triggerStaticBytes(t, it, 1337, 7331, 4747, val4, val5, val6, val7, raw) - triggerStaticBytes(t, it, 7331, 4747, 1337, val4, val5, val6, val7, raw) - triggerStaticBytes(t, it, 4747, 1337, 7331, val4, val5, val6, val7, raw) - - assert.Eventually(t, func() bool { - sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: staticBytesEventName, Expressions: []query.Expression{ - query.Comparator("msgTransmitterEvent", - primitives.ValueComparator{ - Value: dataWordOnChainValueToQuery, - Operator: primitives.Eq, - }), + }, + { + Name: QueryKeyFilteringOnDataWordsUsingValueComparatorsOnFieldsWithManualIndex, + Test: func(t T) { + ctx := tests.Context(t) + cr := it.GetContractReader(t) + require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + bindings := it.GetBindings(t) + boundContract := BindingsByName(bindings, AnyContractName)[0] + require.NoError(t, cr.Bind(ctx, bindings)) + empty12Bytes := [12]byte{} + val1, val2, val3, val4 := uint32(1), uint32(2), uint32(3), uint64(4) + val5, val6, val7 := [32]byte{}, [32]byte{6}, [32]byte{7} + copy(val5[:], append(empty12Bytes[:], 5)) + raw := []byte{9, 8} + + var buf []byte + buf = binary.BigEndian.AppendUint32(buf, val1) + buf = binary.BigEndian.AppendUint32(buf, val2) + buf = binary.BigEndian.AppendUint32(buf, val3) + buf = binary.BigEndian.AppendUint64(buf, val4) + dataWordOnChainValueToQuery := buf[:] + + resExpected := append(buf, common.LeftPadBytes(val5[:], 32)...) + resExpected = append(resExpected, common.LeftPadBytes(val6[:], 32)...) + resExpected = append(resExpected, common.LeftPadBytes(val7[:], 32)...) + resExpected = append(resExpected, raw...) + + type eventResAsStruct struct { + Message *[]uint8 + } + wrapExpectedRes := eventResAsStruct{Message: &resExpected} + + // emit the one we want to search for and a couple of random ones to confirm that filtering works + triggerStaticBytes(t, it, val1, val2, val3, val4, val5, val6, val7, raw) + triggerStaticBytes(t, it, 1337, 7331, 4747, val4, val5, val6, val7, raw) + triggerStaticBytes(t, it, 7331, 4747, 1337, val4, val5, val6, val7, raw) + triggerStaticBytes(t, it, 4747, 1337, 7331, val4, val5, val6, val7, raw) + + assert.Eventually(t, func() bool { + sequences, err := cr.QueryKey(ctx, boundContract, query.KeyFilter{Key: staticBytesEventName, Expressions: []query.Expression{ + query.Comparator("msgTransmitterEvent", + primitives.ValueComparator{ + Value: dataWordOnChainValueToQuery, + Operator: primitives.Eq, + }), + }, + }, query.LimitAndSort{}, eventResAsStruct{}) + return err == nil && len(sequences) == 1 && reflect.DeepEqual(wrapExpectedRes, sequences[0].Data) + }, it.MaxWaitTimeForEvents(), time.Millisecond*10) }, - }, query.LimitAndSort{}, eventResAsStruct{}) - return err == nil && len(sequences) == 1 && reflect.DeepEqual(wrapExpectedRes, sequences[0].Data) - }, it.MaxWaitTimeForEvents(), time.Millisecond*10) - }) + }, + } + RunTests(t, it, testCases) } func triggerFourTopics[T TestingT[T]](t T, it *EVMChainComponentsInterfaceTester[T], i1, i2, i3 int32) { diff --git a/deployment/go.mod b/deployment/go.mod index f73b5cc6b4d..5697579f7ba 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -24,7 +24,7 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 github.com/smartcontractkit/chain-selectors v1.0.27 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.12 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/deployment/go.sum b/deployment/go.sum index e854710fb5a..99e53978aee 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1387,8 +1387,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80 h1:BdqTkM2KObIaD2vevGM5MVJz+3pZl3wNF8h68Gh5iys= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595 h1:H6i0LEvXB0se/63E3jE9N0/7TugOYLpK4e6TT6a0omc= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f h1:xzEYM1e6Jvu2IHLkVgJeKNmxvz0R+CHQwrRM/lqmMRM= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= diff --git a/go.mod b/go.mod index 7b41a80c823..b35b5a59eab 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.27 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e github.com/smartcontractkit/chainlink-feeds v0.1.1 diff --git a/go.sum b/go.sum index ce3338b4b6c..7c7ccc59a18 100644 --- a/go.sum +++ b/go.sum @@ -1077,8 +1077,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80 h1:BdqTkM2KObIaD2vevGM5MVJz+3pZl3wNF8h68Gh5iys= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595 h1:H6i0LEvXB0se/63E3jE9N0/7TugOYLpK4e6TT6a0omc= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f h1:xzEYM1e6Jvu2IHLkVgJeKNmxvz0R+CHQwrRM/lqmMRM= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index eec51bbca41..65c01a93bbc 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -36,7 +36,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.27 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index e96918be689..3a72b7e6386 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1405,8 +1405,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80 h1:BdqTkM2KObIaD2vevGM5MVJz+3pZl3wNF8h68Gh5iys= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595 h1:H6i0LEvXB0se/63E3jE9N0/7TugOYLpK4e6TT6a0omc= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f h1:xzEYM1e6Jvu2IHLkVgJeKNmxvz0R+CHQwrRM/lqmMRM= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index b85078806cf..3f6e4d89133 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -17,7 +17,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index a075600dcbc..f8122f0250a 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1394,8 +1394,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80 h1:BdqTkM2KObIaD2vevGM5MVJz+3pZl3wNF8h68Gh5iys= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241029124258-09d605658a80/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595 h1:H6i0LEvXB0se/63E3jE9N0/7TugOYLpK4e6TT6a0omc= -github.com/smartcontractkit/chainlink-common v0.3.1-0.20241025132045-cfad02139595/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f h1:xzEYM1e6Jvu2IHLkVgJeKNmxvz0R+CHQwrRM/lqmMRM= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241030174834-c2c9a94ab04f/go.mod h1:TQ9/KKXZ9vr8QAlUquqGpSvDCpR+DtABKPXZY4CiRns= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg=