diff --git a/.changeset/few-pillows-yawn.md b/.changeset/few-pillows-yawn.md new file mode 100644 index 00000000000..ada48200d53 --- /dev/null +++ b/.changeset/few-pillows-yawn.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added Add RMNRemote in the chain reader definition diff --git a/.changeset/fifty-pillows-peel.md b/.changeset/fifty-pillows-peel.md new file mode 100644 index 00000000000..711a8869aa4 --- /dev/null +++ b/.changeset/fifty-pillows-peel.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Added `EVM.HeadTracker.PersistenceEnabled` config option to disable persistence for HeadTracker. #added diff --git a/.changeset/fresh-falcons-cheer.md b/.changeset/fresh-falcons-cheer.md new file mode 100644 index 00000000000..505582cc4fd --- /dev/null +++ b/.changeset/fresh-falcons-cheer.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added solana: compute unit limit configuration and transaction instruction diff --git a/.changeset/honest-cameras-cross.md b/.changeset/honest-cameras-cross.md new file mode 100644 index 00000000000..1da50c97bd5 --- /dev/null +++ b/.changeset/honest-cameras-cross.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Implementing evm specific token data encoder for CCIP #internal diff --git a/.changeset/moody-rules-agree.md b/.changeset/moody-rules-agree.md new file mode 100644 index 00000000000..ef1f3bcaf62 --- /dev/null +++ b/.changeset/moody-rules-agree.md @@ -0,0 +1,8 @@ +--- +"chainlink": patch +--- + +- register polling subscription to avoid subscription leaking when rpc client gets closed. +- add a temporary special treatment for SubscribeNewHead before we replace it with SubscribeToHeads. Add a goroutine that forwards new head from poller to caller channel. +- fix a deadlock in poller, by using a new lock for subs slice in rpc client. +#bugfix diff --git a/.changeset/nervous-books-push.md b/.changeset/nervous-books-push.md new file mode 100644 index 00000000000..b0f797344e3 --- /dev/null +++ b/.changeset/nervous-books-push.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Updated QueryKey to be able to do advanced queries on contract event data words diff --git a/.changeset/ninety-feet-change.md b/.changeset/ninety-feet-change.md new file mode 100644 index 00000000000..2c4cea72106 --- /dev/null +++ b/.changeset/ninety-feet-change.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#updated default config values for FinalityTagEnabled to match CCIP configs diff --git a/.changeset/tidy-apricots-care.md b/.changeset/tidy-apricots-care.md new file mode 100644 index 00000000000..60429107f11 --- /dev/null +++ b/.changeset/tidy-apricots-care.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added Pass the home chain selector to the commit plugin factory diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 9a1a707c194..d415c58f7b6 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -63,7 +63,7 @@ jobs: contents: read # For golangci-lint-action's `only-new-issues` option. pull-requests: read - runs-on: ubuntu22.04-8cores-32GB + runs-on: ubuntu-24.04-8cores-32GB-ARM needs: [filter] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 diff --git a/.github/workflows/crib-integration-test.yml b/.github/workflows/crib-integration-test.yml index 56e025eefff..8fd23a783f0 100644 --- a/.github/workflows/crib-integration-test.yml +++ b/.github/workflows/crib-integration-test.yml @@ -1,5 +1,8 @@ name: CRIB Integration Tests on: + pull_request: + paths: + - ".github/workflows/crib-integration-test.yml" schedule: - cron: "0 1 * * *" workflow_call: @@ -73,7 +76,7 @@ jobs: echo $GITHUB_WORKSPACE - name: Deploy and validate CRIB Environment for Core - uses: smartcontractkit/.github/actions/crib-deploy-environment@4dd21a9d6e3f1383ffe8b9650b55f6e6031d3d0a # crib-deploy-environment@1.0.0 + uses: smartcontractkit/.github/actions/crib-deploy-environment@fa63a0fb95039c4d89fec6a9a78b53c0cacf5457 # crib-deploy-environment@2.0.0 id: deploy-crib with: github-token: ${{ steps.token.outputs.access-token }} @@ -83,7 +86,7 @@ jobs: ecr-private-registry: ${{ secrets.AWS_ACCOUNT_ID_PROD }} ingress-base-domain: ${{ secrets.INGRESS_BASE_DOMAIN_STAGE }} k8s-cluster-name: ${{ secrets.AWS_K8S_CLUSTER_NAME_STAGE }} - devspace-profiles: "local-dev-simulated-core-ocr1" + command: "core-dev-simulated-core-ocr1" crib-alert-slack-webhook: ${{ secrets.CRIB_ALERT_SLACK_WEBHOOK }} product-image: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }}/chainlink product-image-tag: develop @@ -103,6 +106,8 @@ jobs: SETH_LOG_LEVEL: info # RESTY_DEBUG: true TEST_PERSISTENCE: true + E2E_TEST_CHAINLINK_IMAGE: public.ecr.aws/chainlink/chainlink + E2E_TEST_CHAINLINK_VERSION: latest run: |- go test -v -run TestCRIBChaos - name: Destroy CRIB Environment diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 9c07a8e8bfe..1933ec520fb 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -129,7 +129,7 @@ jobs: lint-integration-tests: name: Lint ${{ matrix.project.name }} - runs-on: ubuntu22.04-8cores-32GB + runs-on: ubuntu-24.04-8cores-32GB-ARM # We don't directly merge dependabot PRs, so let's not waste the resources if: github.actor != 'dependabot[bot]' strategy: @@ -665,11 +665,19 @@ jobs: with: repository: smartcontractkit/chainlink-solana ref: ${{ needs.get_solana_sha.outputs.sha }} + - name: Download Artifacts + if: (needs.changes.outputs.core_changes == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + with: + name: artifacts + path: ${{ env.CONTRACT_ARTIFACTS_PATH }} - name: Build Test Image if: (needs.changes.outputs.core_changes == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' uses: smartcontractkit/.github/actions/ctf-build-test-image@a5e4f4c8fbb8e15ab2ad131552eca6ac83c4f4b3 # ctf-build-test-image@0.1.0 with: + repository: chainlink-solana-tests tag: ${{ needs.get_solana_sha.outputs.sha }} + suites: smoke QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} diff --git a/ccip/config/evm/Avalanche_ANZ_testnet.toml b/ccip/config/evm/Avalanche_ANZ_testnet.toml index 4833881bf48..1242e1ec06e 100644 --- a/ccip/config/evm/Avalanche_ANZ_testnet.toml +++ b/ccip/config/evm/Avalanche_ANZ_testnet.toml @@ -17,3 +17,6 @@ PriceMin = '25 gwei' [GasEstimator.BlockHistory] BlockHistorySize = 24 + +[HeadTracker] +PersistenceEnabled = false diff --git a/ccip/config/evm/Avalanche_Fuji.toml b/ccip/config/evm/Avalanche_Fuji.toml index 5ba2e3cdc70..91b8bf6bab8 100644 --- a/ccip/config/evm/Avalanche_Fuji.toml +++ b/ccip/config/evm/Avalanche_Fuji.toml @@ -19,3 +19,4 @@ BlockHistorySize = 24 [HeadTracker] FinalityTagBypass = false +PersistenceEnabled = false diff --git a/ccip/config/evm/Avalanche_Mainnet.toml b/ccip/config/evm/Avalanche_Mainnet.toml index e7813842b4b..f51af60098d 100644 --- a/ccip/config/evm/Avalanche_Mainnet.toml +++ b/ccip/config/evm/Avalanche_Mainnet.toml @@ -17,3 +17,6 @@ PriceMin = '25 gwei' [GasEstimator.BlockHistory] # Average block time of 2s BlockHistorySize = 24 + +[HeadTracker] +PersistenceEnabled = false diff --git a/ccip/config/evm/BSC_Testnet.toml b/ccip/config/evm/BSC_Testnet.toml index b27a877812b..bb13501f1a2 100644 --- a/ccip/config/evm/BSC_Testnet.toml +++ b/ccip/config/evm/BSC_Testnet.toml @@ -23,6 +23,7 @@ BlockHistorySize = 24 HistoryDepth = 100 SamplingInterval = '1s' FinalityTagBypass = false +PersistenceEnabled = false [OCR] DatabaseTimeout = '2s' diff --git a/ccip/config/evm/Celo_Mainnet.toml b/ccip/config/evm/Celo_Mainnet.toml index a4948620370..0ed08986d32 100644 --- a/ccip/config/evm/Celo_Mainnet.toml +++ b/ccip/config/evm/Celo_Mainnet.toml @@ -18,3 +18,4 @@ BlockHistorySize = 12 [HeadTracker] HistoryDepth = 50 +PersistenceEnabled = false diff --git a/ccip/config/evm/Celo_Testnet.toml b/ccip/config/evm/Celo_Testnet.toml index eb43f080b7d..4f457b103e0 100644 --- a/ccip/config/evm/Celo_Testnet.toml +++ b/ccip/config/evm/Celo_Testnet.toml @@ -18,3 +18,4 @@ BlockHistorySize = 24 [HeadTracker] HistoryDepth = 50 +PersistenceEnabled = false diff --git a/ccip/config/evm/Simulated.toml b/ccip/config/evm/Simulated.toml index 52e78c94edf..b3392a93363 100644 --- a/ccip/config/evm/Simulated.toml +++ b/ccip/config/evm/Simulated.toml @@ -19,6 +19,7 @@ PriceMax = '100 micro' HistoryDepth = 10 MaxBufferSize = 100 SamplingInterval = '0s' +PersistenceEnabled = false [OCR] ContractConfirmations = 1 diff --git a/ccip/config/evm/WeMix_Mainnet.toml b/ccip/config/evm/WeMix_Mainnet.toml index 7d3fcc6bc2b..be7c278f692 100644 --- a/ccip/config/evm/WeMix_Mainnet.toml +++ b/ccip/config/evm/WeMix_Mainnet.toml @@ -14,3 +14,6 @@ ContractConfirmations = 1 [GasEstimator] EIP1559DynamicFees = true TipCapDefault = '100 gwei' + +[HeadTracker] +PersistenceEnabled = false diff --git a/ccip/config/evm/WeMix_Testnet.toml b/ccip/config/evm/WeMix_Testnet.toml index 5775097967a..4591fc4c572 100644 --- a/ccip/config/evm/WeMix_Testnet.toml +++ b/ccip/config/evm/WeMix_Testnet.toml @@ -17,3 +17,4 @@ TipCapDefault = '100 gwei' [HeadTracker] FinalityTagBypass = false +PersistenceEnabled = false diff --git a/common/headtracker/types/config.go b/common/headtracker/types/config.go index 06ad93d39d2..19ec519aa35 100644 --- a/common/headtracker/types/config.go +++ b/common/headtracker/types/config.go @@ -15,4 +15,5 @@ type HeadTrackerConfig interface { SamplingInterval() time.Duration FinalityTagBypass() bool MaxAllowedFinalityDepth() uint32 + PersistenceEnabled() bool } diff --git a/contracts/.changeset/tall-donkeys-flow.md b/contracts/.changeset/tall-donkeys-flow.md new file mode 100644 index 00000000000..3753880baeb --- /dev/null +++ b/contracts/.changeset/tall-donkeys-flow.md @@ -0,0 +1,10 @@ +--- +'@chainlink/contracts': minor +--- + +#internal Updated ChainReaderTester to include dynamic and static nested structs in TestStruct + + +PR issue: BCFR-44 + +Solidity Review issue: BCFR-957 \ No newline at end of file diff --git a/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol b/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol index e3b277119ae..2ca192e9fed 100644 --- a/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol +++ b/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol @@ -10,29 +10,41 @@ struct TestStruct { address Account; address[] Accounts; int192 BigField; - MidLevelTestStruct NestedStruct; + MidLevelDynamicTestStruct NestedDynamicStruct; + MidLevelStaticTestStruct NestedStaticStruct; } -struct MidLevelTestStruct { +struct MidLevelDynamicTestStruct { bytes2 FixedBytes; - InnerTestStruct Inner; + InnerDynamicTestStruct Inner; } -struct InnerTestStruct { +struct InnerDynamicTestStruct { int64 IntVal; string S; } +struct MidLevelStaticTestStruct { + bytes2 FixedBytes; + InnerStaticTestStruct Inner; +} + +struct InnerStaticTestStruct { + int64 IntVal; + address A; +} + contract ChainReaderTester { event Triggered( int32 indexed field, uint8 oracleId, + MidLevelDynamicTestStruct nestedDynamicStruct, + MidLevelStaticTestStruct nestedStaticStruct, uint8[32] oracleIds, address Account, address[] Accounts, string differentField, - int192 bigField, - MidLevelTestStruct nestedStruct + int192 bigField ); event TriggeredEventWithDynamicTopic(string indexed fieldHash, string field); @@ -61,9 +73,22 @@ contract ChainReaderTester { address account, address[] calldata accounts, int192 bigField, - MidLevelTestStruct calldata nestedStruct + MidLevelDynamicTestStruct calldata nestedDynamicStruct, + MidLevelStaticTestStruct calldata nestedStaticStruct ) public { - s_seen.push(TestStruct(field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct)); + s_seen.push( + TestStruct( + field, + differentField, + oracleId, + oracleIds, + account, + accounts, + bigField, + nestedDynamicStruct, + nestedStaticStruct + ) + ); } function setAlterablePrimitiveValue(uint64 value) public { @@ -78,9 +103,21 @@ contract ChainReaderTester { address account, address[] calldata accounts, int192 bigField, - MidLevelTestStruct calldata nestedStruct + MidLevelDynamicTestStruct calldata nestedDynamicStruct, + MidLevelStaticTestStruct calldata nestedStaticStruct ) public pure returns (TestStruct memory) { - return TestStruct(field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct); + return + TestStruct( + field, + differentField, + oracleId, + oracleIds, + account, + accounts, + bigField, + nestedDynamicStruct, + nestedStaticStruct + ); } function getElementAtIndex(uint256 i) public view returns (TestStruct memory) { @@ -110,14 +147,25 @@ contract ChainReaderTester { function triggerEvent( int32 field, uint8 oracleId, + MidLevelDynamicTestStruct calldata nestedDynamicStruct, + MidLevelStaticTestStruct calldata nestedStaticStruct, uint8[32] calldata oracleIds, address account, address[] calldata accounts, string calldata differentField, - int192 bigField, - MidLevelTestStruct calldata nestedStruct + int192 bigField ) public { - emit Triggered(field, oracleId, oracleIds, account, accounts, differentField, bigField, nestedStruct); + emit Triggered( + field, + oracleId, + nestedDynamicStruct, + nestedStaticStruct, + oracleIds, + account, + accounts, + differentField, + bigField + ); } function triggerEventWithDynamicTopic(string calldata field) public { diff --git a/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go b/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go index 1699820da8b..8d26d2b395a 100644 --- a/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go +++ b/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go @@ -85,6 +85,10 @@ func Test_USDCReader_MessageHashes(t *testing.T) { emitMessageSent(t, ts, ethereumDomainCCTP, polygonDomainCCTP, 31) emitMessageSent(t, ts, ethereumDomainCCTP, polygonDomainCCTP, 41) + // Need to replay as sometimes the logs are not picked up by the log poller (?) + // Maybe another situation where chain reader doesn't register filters as expected. + require.NoError(t, ts.lp.Replay(ctx, 1)) + tt := []struct { name string tokens map[exectypes.MessageTokenID]cciptypes.RampTokenAmount @@ -198,7 +202,7 @@ func Test_USDCReader_MessageHashes(t *testing.T) { } } return true - }, tests.WaitTimeout(t), 100*time.Millisecond) + }, tests.WaitTimeout(t), 50*time.Millisecond) }) } } @@ -286,6 +290,7 @@ func testSetup(ctx context.Context, t *testing.T, readerChain cciptypes.ChainSel auth: auth, cl: cl, reader: cr, + lp: lp, } } @@ -296,4 +301,5 @@ type testSetupData struct { auth *bind.TransactOpts cl client.Client reader types.ContractReader + lp logpoller.LogPoller } diff --git a/core/capabilities/ccip/ccipevm/tokendata.go b/core/capabilities/ccip/ccipevm/tokendata.go new file mode 100644 index 00000000000..5c205a8739c --- /dev/null +++ b/core/capabilities/ccip/ccipevm/tokendata.go @@ -0,0 +1,38 @@ +package ccipevm + +import ( + "context" + + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" +) + +type usdcAttestationPayload struct { + Message []byte + Attestation []byte +} + +func (m usdcAttestationPayload) AbiString() string { + return ` + [{ + "components": [ + {"name": "message", "type": "bytes"}, + {"name": "attestation", "type": "bytes"} + ], + "type": "tuple" + }]` +} + +type EVMTokenDataEncoder struct{} + +func NewEVMTokenDataEncoder() EVMTokenDataEncoder { + return EVMTokenDataEncoder{} +} + +func (e EVMTokenDataEncoder) EncodeUSDC(_ context.Context, message cciptypes.Bytes, attestation cciptypes.Bytes) (cciptypes.Bytes, error) { + return abihelpers.EncodeAbiStruct(usdcAttestationPayload{ + Message: message, + Attestation: attestation, + }) +} diff --git a/core/capabilities/ccip/ccipevm/tokendata_test.go b/core/capabilities/ccip/ccipevm/tokendata_test.go new file mode 100644 index 00000000000..7479d764071 --- /dev/null +++ b/core/capabilities/ccip/ccipevm/tokendata_test.go @@ -0,0 +1,73 @@ +package ccipevm + +import ( + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/stretchr/testify/require" + + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" +) + +func Test_EVMTokenDataEncoder(t *testing.T) { + var empty usdcAttestationPayload + encoder := NewEVMTokenDataEncoder() + + //https://testnet.snowtrace.io/tx/0xeeb0ad6b26bacd1570a9361724a36e338f4aacf1170dec64399220b7483b7eed/eventlog?chainid=43113 + //https://iris-api-sandbox.circle.com/v1/attestations/0x69fb1b419d648cf6c9512acad303746dc85af3b864af81985c76764aba60bf6b + realMessage, err := cciptypes.NewBytesFromString("0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f8000000000000000100000006000000000004ac0d000000000000000000000000eb08f243e5d3fcff26a9e38ae5520a669f4019d00000000000000000000000009f3b8679c73c2fef8b59b4f3444d4e156fb70aa5000000000000000000000000c08835adf4884e51ff076066706e407506826d9d000000000000000000000000000000005425890298aed601595a70ab815c96711a31bc650000000000000000000000004f32ae7f112c26b109357785e5c66dc5d747fbce00000000000000000000000000000000000000000000000000000000000000640000000000000000000000007a4d8f8c18762d362e64b411d7490fba112811cd0000000000000000") + require.NoError(t, err) + realAttestation, err := cciptypes.NewBytesFromString("0xee466fbd340596aa56e3e40d249869573e4008d84d795b4f2c3cba8649083d08653d38190d0df7e0ee12ae685df2f806d100a03b3716ab1ff2013c7201f1c2d01c9af959b55a4b52dbd0319eed69ce9ace25259830e0b1bff79faf0c9c5d1b5e6d6304e824d657db38f802bcff3e97d0bd30f2ffc62b62381f52c1668ceaa5a73a1b") + require.NoError(t, err) + + tt := []struct { + name string + message []byte + attestation []byte + }{ + { + name: "empty both fields", + message: nil, + attestation: []byte{}, + }, + { + name: "empty attestation", + message: []byte("message"), + attestation: nil, + }, + { + name: "both attestation and message are set", + message: realMessage, + attestation: realAttestation, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + got, err := encoder.EncodeUSDC(tests.Context(t), tc.message, tc.attestation) + require.NoError(t, err) + + decoded, err := abihelpers.ABIDecode(empty.AbiString(), got) + require.NoError(t, err) + + converted := abi.ConvertType(decoded[0], &empty) + casted, ok := converted.(*usdcAttestationPayload) + require.True(t, ok) + + if tc.message == nil { + require.Empty(t, casted.Message) + } else { + require.Equal(t, tc.message, casted.Message) + } + + if tc.attestation == nil { + require.Empty(t, casted.Attestation) + } else { + require.Equal(t, tc.attestation, casted.Attestation) + } + }) + } +} diff --git a/core/capabilities/ccip/configs/evm/contract_reader.go b/core/capabilities/ccip/configs/evm/contract_reader.go index 18aa07cc022..fbfbf260b8a 100644 --- a/core/capabilities/ccip/configs/evm/contract_reader.go +++ b/core/capabilities/ccip/configs/evm/contract_reader.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" @@ -26,8 +27,13 @@ var ( feeQuoterABI = evmtypes.MustGetABI(fee_quoter.FeeQuoterABI) nonceManagerABI = evmtypes.MustGetABI(nonce_manager.NonceManagerABI) priceFeedABI = evmtypes.MustGetABI(aggregator_v3_interface.AggregatorV3InterfaceABI) + rmnRemoteABI = evmtypes.MustGetABI(rmn_remote.RMNRemoteABI) + rmnHomeABI = evmtypes.MustGetABI(rmnHomeString) ) +// TODO: replace with generated ABI when the contract will be defined +var rmnHomeString = "[{\"inputs\":[],\"name\":\"getAllConfigs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"num\",\"type\":\"uint256\"}],\"name\":\"store\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" + // MustSourceReaderConfig returns a ChainReaderConfig that can be used to read from the onramp. // The configuration is marshaled into JSON so that it can be passed to the relayer NewContractReader() method. func MustSourceReaderConfig() []byte { @@ -163,6 +169,15 @@ var DestReaderConfig = evmrelaytypes.ChainReaderConfig{ }, }, }, + consts.ContractNameRMNRemote: { + ContractABI: rmn_remote.RMNRemoteABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameGetVersionedConfig: { + ChainSpecificName: mustGetMethodName("getVersionedConfig", rmnRemoteABI), + ReadType: evmrelaytypes.Method, + }, + }, + }, }, } @@ -238,6 +253,14 @@ var HomeChainReaderConfigRaw = evmrelaytypes.ChainReaderConfig{ }, }, }, + consts.ContractNameRMNHome: { + ContractABI: rmnHomeString, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + consts.MethodNameGetAllConfigs: { + ChainSpecificName: mustGetMethodName("getAllConfigs", rmnHomeABI), + }, + }, + }, }, } diff --git a/core/capabilities/ccip/delegate.go b/core/capabilities/ccip/delegate.go index 84f3e7c1b76..30007a7b2cf 100644 --- a/core/capabilities/ccip/delegate.go +++ b/core/capabilities/ccip/delegate.go @@ -3,6 +3,7 @@ package ccip import ( "context" "fmt" + "strconv" "time" "github.com/smartcontractkit/chainlink-common/pkg/loop" @@ -23,7 +24,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + chainsel "github.com/smartcontractkit/chain-selectors" + + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/config" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" @@ -162,6 +167,16 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services ccipConfigBinding, ) + // get the chain selector for the home chain + homeChainChainID, err := strconv.ParseUint(d.capabilityConfig.ExternalRegistry().RelayID().ChainID, 10, 64) + if err != nil { + return nil, fmt.Errorf("failed to parse chain ID %s: %w", d.capabilityConfig.ExternalRegistry().RelayID().ChainID, err) + } + homeChainChainSelector, err := chainsel.SelectorFromChainId(homeChainChainID) + if err != nil { + return nil, fmt.Errorf("failed to get chain selector from chain ID %d", homeChainChainID) + } + // if bootstrappers are provided we assume that the node is a plugin oracle. // the reason for this is that bootstrap oracles do not need to be aware // of other bootstrap oracles. however, plugin oracles, at least initially, @@ -182,6 +197,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services d.monitoringEndpointGen, bootstrapperLocators, hcr, + cciptypes.ChainSelector(homeChainChainSelector), ) } else { oracleCreator = oraclecreator.NewBootstrapOracleCreator( diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go index 43081413ceb..274620926fa 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go @@ -24,6 +24,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -541,6 +542,10 @@ func (t *TestHeadTrackerConfig) SamplingInterval() time.Duration { return 1 * time.Second } +func (t *TestHeadTrackerConfig) PersistenceEnabled() bool { + return true +} + var _ evmconfig.HeadTracker = (*TestHeadTrackerConfig)(nil) type TestEvmConfig struct { diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index d9efe5a58c0..07682ba60e9 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -11,7 +11,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - "github.com/smartcontractkit/chainlink-ccip/execute/tokendata" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" @@ -33,6 +32,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pluginconfig" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -67,6 +67,7 @@ type pluginOracleCreator struct { monitoringEndpointGen telemetry.MonitoringEndpointGenerator bootstrapperLocators []commontypes.BootstrapperLocator homeChainReader ccipreaderpkg.HomeChain + homeChainSelector cciptypes.ChainSelector } func NewPluginOracleCreator( @@ -83,6 +84,7 @@ func NewPluginOracleCreator( monitoringEndpointGen telemetry.MonitoringEndpointGenerator, bootstrapperLocators []commontypes.BootstrapperLocator, homeChainReader ccipreaderpkg.HomeChain, + homeChainSelector cciptypes.ChainSelector, ) cctypes.OracleCreator { return &pluginOracleCreator{ ocrKeyBundles: ocrKeyBundles, @@ -98,6 +100,7 @@ func NewPluginOracleCreator( monitoringEndpointGen: monitoringEndpointGen, bootstrapperLocators: bootstrapperLocators, homeChainReader: homeChainReader, + homeChainSelector: homeChainSelector, } } @@ -220,6 +223,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( ccipevm.NewCommitPluginCodecV1(), ccipevm.NewMessageHasherV1(), i.homeChainReader, + i.homeChainSelector, contractReaders, chainWriters, ) @@ -238,7 +242,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( ccipevm.NewExecutePluginCodecV1(), ccipevm.NewMessageHasherV1(), i.homeChainReader, - &tokendata.NoopTokenDataObserver{}, + ccipevm.NewEVMTokenDataEncoder(), ccipevm.NewGasEstimateProvider(), contractReaders, chainWriters, @@ -273,6 +277,11 @@ func (i *pluginOracleCreator) createReadersAndWriters( execBatchGasLimit = ofc.exec().BatchGasLimit } + homeChainID, err := i.getChainID(i.homeChainSelector) + if err != nil { + return nil, nil, err + } + contractReaders := make(map[cciptypes.ChainSelector]types.ContractReader) chainWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) for _, chain := range i.chains.Slice() { @@ -281,7 +290,7 @@ func (i *pluginOracleCreator) createReadersAndWriters( return nil, nil, err1 } - chainReaderConfig := getChainReaderConfig(chain.ID().Uint64(), destChainID, ofc, chainSelector) + chainReaderConfig := getChainReaderConfig(chain.ID().Uint64(), destChainID, homeChainID, ofc, chainSelector) cr, err1 := createChainReader(i.lggr, chain, chainReaderConfig, pluginType) if err1 != nil { return nil, nil, err1 @@ -348,9 +357,18 @@ func (i *pluginOracleCreator) getChainSelector(chainID uint64) (cciptypes.ChainS return cciptypes.ChainSelector(chainSelector), nil } +func (i *pluginOracleCreator) getChainID(chainSelector cciptypes.ChainSelector) (uint64, error) { + chainID, err := chainsel.ChainIdFromSelector(uint64(chainSelector)) + if err != nil { + return 0, fmt.Errorf("failed to get chain ID from chain selector %d: %w", chainSelector, err) + } + return chainID, nil +} + func getChainReaderConfig( chainID uint64, destChainID uint64, + homeChainID uint64, ofc offChainConfig, chainSelector cciptypes.ChainSelector, ) evmrelaytypes.ChainReaderConfig { @@ -364,6 +382,10 @@ func getChainReaderConfig( if !ofc.commitEmpty() && ofc.commit().PriceFeedChainSelector == chainSelector { chainReaderConfig = evmconfig.MergeReaderConfigs(chainReaderConfig, evmconfig.FeedReaderConfig) } + + if chainID == homeChainID { + chainReaderConfig = evmconfig.MergeReaderConfigs(chainReaderConfig, evmconfig.HomeChainReaderConfigRaw) + } return chainReaderConfig } diff --git a/core/capabilities/encoder_factory.go b/core/capabilities/encoder_factory.go new file mode 100644 index 00000000000..73e129bd855 --- /dev/null +++ b/core/capabilities/encoder_factory.go @@ -0,0 +1,21 @@ +package capabilities + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" +) + +func NewEncoder(name string, config *values.Map, lggr logger.Logger) (types.Encoder, error) { + switch name { + case "EVM": + return evm.NewEVMEncoder(config) + // TODO: add a "no-op" encoder for users who only want to use dynamic ones? + // https://smartcontract-it.atlassian.net/browse/CAPPL-88 + default: + return nil, fmt.Errorf("encoder %s not supported", name) + } +} diff --git a/core/capabilities/integration_tests/setup.go b/core/capabilities/integration_tests/setup.go index f419c05e6c3..1d0ec183e69 100644 --- a/core/capabilities/integration_tests/setup.go +++ b/core/capabilities/integration_tests/setup.go @@ -41,7 +41,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec" "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) @@ -153,7 +152,7 @@ func createDons(ctx context.Context, t *testing.T, lggr logger.Logger, reportsSi requestTimeout := 10 * time.Minute cfg := ocr3.Config{ Logger: lggr, - EncoderFactory: evm.NewEVMEncoder, + EncoderFactory: capabilities.NewEncoder, AggregatorFactory: capabilities.NewAggregator, RequestTimeout: &requestTimeout, } diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 763348173aa..a29ed5e118c 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -129,7 +129,8 @@ type rpcClient struct { ws rawclient http *rawclient - stateMu sync.RWMutex // protects state* fields + stateMu sync.RWMutex // protects state* fields + subsSliceMu sync.RWMutex // protects subscription slice // Need to track subscriptions because closing the RPC does not (always?) // close the underlying subscription @@ -317,8 +318,8 @@ func (r *rpcClient) getRPCDomain() string { // registerSub adds the sub to the rpcClient list func (r *rpcClient) registerSub(sub ethereum.Subscription, stopInFLightCh chan struct{}) error { - r.stateMu.Lock() - defer r.stateMu.Unlock() + r.subsSliceMu.Lock() + defer r.subsSliceMu.Unlock() // ensure that the `sub` belongs to current life cycle of the `rpcClient` and it should not be killed due to // previous `DisconnectAll` call. select { @@ -335,12 +336,16 @@ func (r *rpcClient) registerSub(sub ethereum.Subscription, stopInFLightCh chan s // DisconnectAll disconnects all clients connected to the rpcClient func (r *rpcClient) DisconnectAll() { r.stateMu.Lock() - defer r.stateMu.Unlock() if r.ws.rpc != nil { r.ws.rpc.Close() } r.cancelInflightRequests() + r.stateMu.Unlock() + + r.subsSliceMu.Lock() r.unsubscribeAll() + r.subsSliceMu.Unlock() + r.chainInfoLock.Lock() r.latestChainInfo = commonclient.ChainInfo{} r.chainInfoLock.Unlock() @@ -496,11 +501,30 @@ func (r *rpcClient) SubscribeNewHead(ctx context.Context, channel chan<- *evmtyp if r.newHeadsPollInterval > 0 { interval := r.newHeadsPollInterval timeout := interval - poller, _ := commonclient.NewPoller[*evmtypes.Head](interval, r.latestBlock, timeout, r.rpcLog) + poller, pollerCh := commonclient.NewPoller[*evmtypes.Head](interval, r.latestBlock, timeout, r.rpcLog) if err = poller.Start(ctx); err != nil { return nil, err } + // NOTE this is a temporary special treatment for SubscribeNewHead before we refactor head tracker to use SubscribeToHeads + // as we need to forward new head from the poller channel to the channel passed from caller. + go func() { + for head := range pollerCh { + select { + case channel <- head: + // forwarding new head to the channel passed from caller + case <-poller.Err(): + // return as poller returns error + return + } + } + }() + + err = r.registerSub(&poller, chStopInFlight) + if err != nil { + return nil, err + } + lggr.Debugf("Polling new heads over http") return &poller, nil } @@ -547,6 +571,11 @@ func (r *rpcClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.H return nil, nil, err } + err = r.registerSub(&poller, chStopInFlight) + if err != nil { + return nil, nil, err + } + lggr.Debugf("Polling new heads over http") return channel, &poller, nil } @@ -579,6 +608,8 @@ func (r *rpcClient) SubscribeToHeads(ctx context.Context) (ch <-chan *evmtypes.H } func (r *rpcClient) SubscribeToFinalizedHeads(ctx context.Context) (<-chan *evmtypes.Head, commontypes.Subscription, error) { + ctx, cancel, chStopInFlight, _, _ := r.acquireQueryCtx(ctx, r.rpcTimeout) + defer cancel() interval := r.finalizedBlockPollInterval if interval == 0 { return nil, nil, errors.New("FinalizedBlockPollInterval is 0") @@ -588,6 +619,12 @@ func (r *rpcClient) SubscribeToFinalizedHeads(ctx context.Context) (<-chan *evmt if err := poller.Start(ctx); err != nil { return nil, nil, err } + + err := r.registerSub(&poller, chStopInFlight) + if err != nil { + return nil, nil, err + } + return channel, &poller, nil } diff --git a/core/chains/evm/client/rpc_client_test.go b/core/chains/evm/client/rpc_client_test.go index b594a0ca166..d959f8d1115 100644 --- a/core/chains/evm/client/rpc_client_test.go +++ b/core/chains/evm/client/rpc_client_test.go @@ -19,6 +19,8 @@ import ( "github.com/tidwall/gjson" "go.uber.org/zap" + commontypes "github.com/smartcontractkit/chainlink/v2/common/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -57,6 +59,25 @@ func TestRPCClient_SubscribeNewHead(t *testing.T) { } return } + + checkClosedRPCClientShouldRemoveExistingSub := func(t tests.TestingT, ctx context.Context, sub commontypes.Subscription, rpcClient client.RPCClient) { + errCh := sub.Err() + + // ensure sub exists + require.Equal(t, int32(1), rpcClient.SubscribersCount()) + rpcClient.DisconnectAll() + + // ensure sub is closed + select { + case <-errCh: // ok + default: + assert.Fail(t, "channel should be closed") + } + + require.NoError(t, rpcClient.Dial(ctx)) + require.Equal(t, int32(0), rpcClient.SubscribersCount()) + } + t.Run("Updates chain info on new blocks", func(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() @@ -131,6 +152,50 @@ func TestRPCClient_SubscribeNewHead(t *testing.T) { assert.Equal(t, int64(0), highestUserObservations.FinalizedBlockNumber) assert.Equal(t, (*big.Int)(nil), highestUserObservations.TotalDifficulty) }) + t.Run("SubscribeToHeads with http polling enabled will update new heads", func(t *testing.T) { + type rpcServer struct { + Head *evmtypes.Head + URL *url.URL + } + createRPCServer := func() *rpcServer { + server := &rpcServer{} + server.Head = &evmtypes.Head{Number: 127} + server.URL = testutils.NewWSServer(t, chainId, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { + assert.Equal(t, "eth_getBlockByNumber", method) + if assert.True(t, params.IsArray()) && assert.Equal(t, "latest", params.Array()[0].String()) { + head := server.Head + jsonHead, err := json.Marshal(head) + if err != nil { + panic(fmt.Errorf("failed to marshal head: %w", err)) + } + resp.Result = string(jsonHead) + } + + return + }).WSURL() + return server + } + + server := createRPCServer() + rpc := client.NewRPCClient(lggr, *server.URL, nil, "rpc", 1, chainId, commonclient.Primary, 0, tests.TestInterval, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + latest, highestUserObservations := rpc.GetInterceptedChainInfo() + // latest chain info hasn't been initialized + assert.Equal(t, int64(0), latest.BlockNumber) + assert.Equal(t, int64(0), highestUserObservations.BlockNumber) + + headCh, sub, err := rpc.SubscribeToHeads(commonclient.CtxAddHealthCheckFlag(tests.Context(t))) + require.NoError(t, err) + defer sub.Unsubscribe() + + head := <-headCh + assert.Equal(t, server.Head.Number, head.BlockNumber()) + // the http polling subscription should update the head block + latest, highestUserObservations = rpc.GetInterceptedChainInfo() + assert.Equal(t, server.Head.Number, latest.BlockNumber) + assert.Equal(t, server.Head.Number, highestUserObservations.BlockNumber) + }) t.Run("Concurrent Unsubscribe and onNewHead calls do not lead to a deadlock", func(t *testing.T) { const numberOfAttempts = 1000 // need a large number to increase the odds of reproducing the issue server := testutils.NewWSServer(t, chainId, serverCallBack) @@ -184,6 +249,68 @@ func TestRPCClient_SubscribeNewHead(t *testing.T) { require.ErrorContains(t, err, "RPCClient returned error (rpc)") tests.AssertLogEventually(t, observed, "evmclient.Client#EthSubscribe RPC call failure") }) + t.Run("Closed rpc client should remove existing SubscribeNewHead subscription with WS", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, serverCallBack) + wsURL := server.WSURL() + + rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + + ch := make(chan *evmtypes.Head) + sub, err := rpc.SubscribeNewHead(tests.Context(t), ch) + require.NoError(t, err) + checkClosedRPCClientShouldRemoveExistingSub(t, ctx, sub, rpc) + }) + t.Run("Closed rpc client should remove existing SubscribeNewHead subscription with HTTP polling", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, serverCallBack) + wsURL := server.WSURL() + + rpc := client.NewRPCClient(lggr, *wsURL, &url.URL{}, "rpc", 1, chainId, commonclient.Primary, 0, 1, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + + ch := make(chan *evmtypes.Head) + sub, err := rpc.SubscribeNewHead(tests.Context(t), ch) + require.NoError(t, err) + checkClosedRPCClientShouldRemoveExistingSub(t, ctx, sub, rpc) + }) + t.Run("Closed rpc client should remove existing SubscribeToHeads subscription with WS", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, serverCallBack) + wsURL := server.WSURL() + + rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + + _, sub, err := rpc.SubscribeToHeads(tests.Context(t)) + require.NoError(t, err) + checkClosedRPCClientShouldRemoveExistingSub(t, ctx, sub, rpc) + }) + t.Run("Closed rpc client should remove existing SubscribeToHeads subscription with HTTP polling", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, serverCallBack) + wsURL := server.WSURL() + + rpc := client.NewRPCClient(lggr, *wsURL, &url.URL{}, "rpc", 1, chainId, commonclient.Primary, 0, 1, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + + _, sub, err := rpc.SubscribeToHeads(tests.Context(t)) + require.NoError(t, err) + checkClosedRPCClientShouldRemoveExistingSub(t, ctx, sub, rpc) + }) + t.Run("Closed rpc client should remove existing SubscribeToFinalizedHeads subscription", func(t *testing.T) { + server := testutils.NewWSServer(t, chainId, serverCallBack) + wsURL := server.WSURL() + + rpc := client.NewRPCClient(lggr, *wsURL, &url.URL{}, "rpc", 1, chainId, commonclient.Primary, 1, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + + _, sub, err := rpc.SubscribeToFinalizedHeads(tests.Context(t)) + require.NoError(t, err) + checkClosedRPCClientShouldRemoveExistingSub(t, ctx, sub, rpc) + }) t.Run("Subscription error is properly wrapper", func(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() diff --git a/core/chains/evm/config/chain_scoped_head_tracker.go b/core/chains/evm/config/chain_scoped_head_tracker.go index 8bc1ff188a7..75a630238ec 100644 --- a/core/chains/evm/config/chain_scoped_head_tracker.go +++ b/core/chains/evm/config/chain_scoped_head_tracker.go @@ -29,3 +29,7 @@ func (h *headTrackerConfig) FinalityTagBypass() bool { func (h *headTrackerConfig) MaxAllowedFinalityDepth() uint32 { return *h.c.MaxAllowedFinalityDepth } + +func (h *headTrackerConfig) PersistenceEnabled() bool { + return *h.c.PersistenceEnabled +} diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go index e5b806aa58c..c886f9fb616 100644 --- a/core/chains/evm/config/config.go +++ b/core/chains/evm/config/config.go @@ -76,6 +76,7 @@ type HeadTracker interface { SamplingInterval() time.Duration FinalityTagBypass() bool MaxAllowedFinalityDepth() uint32 + PersistenceEnabled() bool } type BalanceMonitor interface { diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go index dd6ecd0bf4c..53155d7e7d2 100644 --- a/core/chains/evm/config/config_test.go +++ b/core/chains/evm/config/config_test.go @@ -343,6 +343,7 @@ func TestChainScopedConfig_HeadTracker(t *testing.T) { assert.Equal(t, time.Second, ht.SamplingInterval()) assert.Equal(t, true, ht.FinalityTagBypass()) assert.Equal(t, uint32(10000), ht.MaxAllowedFinalityDepth()) + assert.Equal(t, true, ht.PersistenceEnabled()) } func TestNodePoolConfig(t *testing.T) { diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index fd4039f5ea1..b5008a73607 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -778,6 +778,7 @@ type HeadTracker struct { SamplingInterval *commonconfig.Duration MaxAllowedFinalityDepth *uint32 FinalityTagBypass *bool + PersistenceEnabled *bool } func (t *HeadTracker) setFrom(f *HeadTracker) { @@ -796,6 +797,10 @@ func (t *HeadTracker) setFrom(f *HeadTracker) { if v := f.FinalityTagBypass; v != nil { t.FinalityTagBypass = v } + if v := f.PersistenceEnabled; v != nil { + t.PersistenceEnabled = v + } + } func (t *HeadTracker) ValidateConfig() (err error) { diff --git a/core/chains/evm/config/toml/defaults/Arbitrum_Mainnet.toml b/core/chains/evm/config/toml/defaults/Arbitrum_Mainnet.toml index b297db1bc0f..e3dcafd56fb 100644 --- a/core/chains/evm/config/toml/defaults/Arbitrum_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Arbitrum_Mainnet.toml @@ -1,6 +1,7 @@ # Arbitrum is an L2 chain. Pending proper L2 support, for now we rely on their sequencer ChainID = '42161' ChainType = 'arbitrum' +FinalityTagEnabled = true LinkContractAddress = "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4" LogPollInterval = '1s' # Arbitrum only emits blocks when a new tx is received, so this method of liveness detection is not useful diff --git a/core/chains/evm/config/toml/defaults/Arbitrum_Sepolia.toml b/core/chains/evm/config/toml/defaults/Arbitrum_Sepolia.toml index e6d660a2729..2af70d04d35 100644 --- a/core/chains/evm/config/toml/defaults/Arbitrum_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Arbitrum_Sepolia.toml @@ -1,5 +1,6 @@ ChainID = '421614' ChainType = 'arbitrum' +FinalityTagEnabled = true NoNewHeadsThreshold = '0' OCR.ContractConfirmations = 1 LogPollInterval = '1s' diff --git a/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml b/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml index 882a91f1acc..6e95be2c7f7 100644 --- a/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml +++ b/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml @@ -1,5 +1,6 @@ ChainID = '43113' FinalityDepth = 10 +FinalityTagEnabled = true LinkContractAddress = '0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846' LogPollInterval = '3s' MinIncomingConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml b/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml index 78d3bbba77a..930f9a910f6 100644 --- a/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml @@ -1,5 +1,6 @@ ChainID = '43114' FinalityDepth = 10 +FinalityTagEnabled = true LinkContractAddress = '0x5947BB275c521040051D82396192181b413227A3' LogPollInterval = '3s' MinIncomingConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/BSC_Mainnet.toml b/core/chains/evm/config/toml/defaults/BSC_Mainnet.toml index 79ad43ab3e0..b3cf458ad87 100644 --- a/core/chains/evm/config/toml/defaults/BSC_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/BSC_Mainnet.toml @@ -2,6 +2,7 @@ # Clique offers finality within (N/2)+1 blocks where N is number of signers # There are 21 BSC validators so theoretically finality should occur after 21/2+1 = 11 blocks ChainID = '56' +FinalityTagEnabled = true LinkContractAddress = '0x404460C6A5EdE2D891e8297795264fDe62ADBB75' LogPollInterval = '3s' NoNewHeadsThreshold = '30s' diff --git a/core/chains/evm/config/toml/defaults/BSC_Testnet.toml b/core/chains/evm/config/toml/defaults/BSC_Testnet.toml index 252f90accdd..7b8fc481d7b 100644 --- a/core/chains/evm/config/toml/defaults/BSC_Testnet.toml +++ b/core/chains/evm/config/toml/defaults/BSC_Testnet.toml @@ -2,6 +2,7 @@ # Clique offers finality within (N/2)+1 blocks where N is number of signers # There are 21 BSC validators so theoretically finality should occur after 21/2+1 = 11 blocks ChainID = '97' +FinalityTagEnabled = true LinkContractAddress = '0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06' LogPollInterval = '3s' NoNewHeadsThreshold = '30s' diff --git a/core/chains/evm/config/toml/defaults/Base_Mainnet.toml b/core/chains/evm/config/toml/defaults/Base_Mainnet.toml index f0896fba414..da38182b194 100644 --- a/core/chains/evm/config/toml/defaults/Base_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Base_Mainnet.toml @@ -1,6 +1,7 @@ ChainID = '8453' ChainType = 'optimismBedrock' FinalityDepth = 200 +FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' MinIncomingConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/Base_Sepolia.toml b/core/chains/evm/config/toml/defaults/Base_Sepolia.toml index 1fc0b51f1f3..b4a7eb680ab 100644 --- a/core/chains/evm/config/toml/defaults/Base_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Base_Sepolia.toml @@ -1,6 +1,7 @@ ChainID = '84532' ChainType = 'optimismBedrock' FinalityDepth = 200 +FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' MinIncomingConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/Ethereum_Mainnet.toml b/core/chains/evm/config/toml/defaults/Ethereum_Mainnet.toml index 20bb0d8e72a..984150c694d 100644 --- a/core/chains/evm/config/toml/defaults/Ethereum_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Ethereum_Mainnet.toml @@ -1,4 +1,5 @@ ChainID = '1' +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' MinContractPayment = '0.1 link' OperatorFactoryAddress = '0x3E64Cd889482443324F91bFA9c84fE72A511f48A' diff --git a/core/chains/evm/config/toml/defaults/Ethereum_Sepolia.toml b/core/chains/evm/config/toml/defaults/Ethereum_Sepolia.toml index 1c46d4ca7cf..403ecd7c4b1 100644 --- a/core/chains/evm/config/toml/defaults/Ethereum_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Ethereum_Sepolia.toml @@ -1,4 +1,5 @@ ChainID = '11155111' +FinalityTagEnabled = true LinkContractAddress = '0x779877A7B0D9E8603169DdbD7836e478b4624789' MinContractPayment = '0.1 link' diff --git a/core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml b/core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml index 55154bf766c..3a48aa8ae1b 100644 --- a/core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Kroma_Mainnet.toml @@ -1,6 +1,7 @@ ChainID = '255' ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture FinalityDepth = 400 +FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' MinIncomingConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml b/core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml index 643b0556b32..9609a09e076 100644 --- a/core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Kroma_Sepolia.toml @@ -1,6 +1,7 @@ ChainID = '2358' ChainType = 'kroma' # Kroma is based on the Optimism Bedrock architechture FinalityDepth = 400 +FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' MinIncomingConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml b/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml index cfc79f978f5..f057400d014 100644 --- a/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Metis_Mainnet.toml @@ -3,6 +3,7 @@ ChainID = '1088' ChainType = 'metis' # Sequencer offers absolute finality FinalityDepth = 10 +FinalityTagEnabled = true MinIncomingConfirmations = 1 NoNewHeadsThreshold = '0' OCR.ContractConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml b/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml index 4e6307302f5..286b888e1a8 100644 --- a/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml @@ -1,6 +1,7 @@ ChainID = '59902' ChainType = 'metis' FinalityDepth = 10 +FinalityTagEnabled = true MinIncomingConfirmations = 1 NoNewHeadsThreshold = '0' OCR.ContractConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/Optimism_Mainnet.toml b/core/chains/evm/config/toml/defaults/Optimism_Mainnet.toml index 3510aef7047..b0f56a49d90 100644 --- a/core/chains/evm/config/toml/defaults/Optimism_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Optimism_Mainnet.toml @@ -1,6 +1,7 @@ ChainID = '10' ChainType = 'optimismBedrock' FinalityDepth = 200 +FinalityTagEnabled = true LinkContractAddress = '0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6' LogPollInterval = '2s' NoNewHeadsThreshold = '40s' diff --git a/core/chains/evm/config/toml/defaults/Optimism_Sepolia.toml b/core/chains/evm/config/toml/defaults/Optimism_Sepolia.toml index 8da575a5936..1c71aa5dd83 100644 --- a/core/chains/evm/config/toml/defaults/Optimism_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Optimism_Sepolia.toml @@ -1,6 +1,7 @@ ChainID = '11155420' ChainType = 'optimismBedrock' FinalityDepth = 200 +FinalityTagEnabled = true LogPollInterval = '2s' NoNewHeadsThreshold = '40s' MinIncomingConfirmations = 1 diff --git a/core/chains/evm/config/toml/defaults/Polygon_Mainnet.toml b/core/chains/evm/config/toml/defaults/Polygon_Mainnet.toml index 2a520563302..bf605cab3c6 100644 --- a/core/chains/evm/config/toml/defaults/Polygon_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Polygon_Mainnet.toml @@ -2,6 +2,7 @@ ChainID = '137' # It is quite common to see re-orgs on polygon go several hundred blocks deep. See: https://polygonscan.com/blocks_forked FinalityDepth = 500 +FinalityTagEnabled = true LinkContractAddress = '0xb0897686c545045aFc77CF20eC7A532E3120E0F1' LogPollInterval = '1s' MinIncomingConfirmations = 5 diff --git a/core/chains/evm/config/toml/defaults/WeMix_Mainnet.toml b/core/chains/evm/config/toml/defaults/WeMix_Mainnet.toml index 7fcbd18890b..4a55450e47e 100644 --- a/core/chains/evm/config/toml/defaults/WeMix_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/WeMix_Mainnet.toml @@ -1,6 +1,7 @@ ChainID = '1111' ChainType = 'wemix' FinalityDepth = 10 +FinalityTagEnabled = true MinIncomingConfirmations = 1 # WeMix emits a block every 1 second, regardless of transactions LogPollInterval = '3s' diff --git a/core/chains/evm/config/toml/defaults/WeMix_Testnet.toml b/core/chains/evm/config/toml/defaults/WeMix_Testnet.toml index 83c483d0348..d4f829bcfd1 100644 --- a/core/chains/evm/config/toml/defaults/WeMix_Testnet.toml +++ b/core/chains/evm/config/toml/defaults/WeMix_Testnet.toml @@ -1,6 +1,7 @@ ChainID = '1112' ChainType = 'wemix' FinalityDepth = 10 +FinalityTagEnabled = true MinIncomingConfirmations = 1 # WeMix emits a block every 1 second, regardless of transactions LogPollInterval = '3s' diff --git a/core/chains/evm/config/toml/defaults/fallback.toml b/core/chains/evm/config/toml/defaults/fallback.toml index 6f43f956faf..1e18f4a4ebf 100644 --- a/core/chains/evm/config/toml/defaults/fallback.toml +++ b/core/chains/evm/config/toml/defaults/fallback.toml @@ -66,6 +66,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' FinalityTagBypass = true MaxAllowedFinalityDepth = 10000 +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 diff --git a/core/chains/evm/headtracker/head_saver_test.go b/core/chains/evm/headtracker/head_saver_test.go index 43e79235e90..266172b67df 100644 --- a/core/chains/evm/headtracker/head_saver_test.go +++ b/core/chains/evm/headtracker/head_saver_test.go @@ -42,6 +42,9 @@ func (h *headTrackerConfig) FinalityTagBypass() bool { func (h *headTrackerConfig) MaxAllowedFinalityDepth() uint32 { return 10000 } +func (h *headTrackerConfig) PersistenceEnabled() bool { + return true +} type config struct { finalityDepth uint32 diff --git a/core/chains/evm/headtracker/head_tracker_test.go b/core/chains/evm/headtracker/head_tracker_test.go index de54f12ff96..8e846d3122c 100644 --- a/core/chains/evm/headtracker/head_tracker_test.go +++ b/core/chains/evm/headtracker/head_tracker_test.go @@ -221,9 +221,9 @@ func TestHeadTracker_Start(t *testing.T) { FinalityTagEnable *bool MaxAllowedFinalityDepth *uint32 FinalityTagBypass *bool + ORM headtracker.ORM } newHeadTracker := func(t *testing.T, opts opts) *headTrackerUniverse { - db := pgtest.NewSqlxDB(t) config := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) { if opts.FinalityTagEnable != nil { c.FinalityTagEnabled = opts.FinalityTagEnable @@ -238,12 +238,15 @@ func TestHeadTracker_Start(t *testing.T) { c.HeadTracker.FinalityTagBypass = opts.FinalityTagBypass } }) - orm := headtracker.NewORM(*testutils.FixtureChainID, db) + if opts.ORM == nil { + db := pgtest.NewSqlxDB(t) + opts.ORM = headtracker.NewORM(*testutils.FixtureChainID, db) + } ethClient := evmtest.NewEthClientMockWithDefaultChain(t) mockEth := &testutils.MockEth{EthClient: ethClient} sub := mockEth.NewSub(t) ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(sub, nil).Maybe() - return createHeadTracker(t, ethClient, config.EVM(), config.EVM().HeadTracker(), orm) + return createHeadTracker(t, ethClient, config.EVM(), config.EVM().HeadTracker(), opts.ORM) } t.Run("Starts even if failed to get initialHead", func(t *testing.T) { ht := newHeadTracker(t, opts{}) @@ -274,9 +277,9 @@ func TestHeadTracker_Start(t *testing.T) { ht.Start(t) tests.AssertLogEventually(t, ht.observer, "Error handling initial head") }) - t.Run("Happy path (finality tag)", func(t *testing.T) { + happyPathFT := func(t *testing.T, opts opts) { head := testutils.Head(1000) - ht := newHeadTracker(t, opts{FinalityTagEnable: ptr(true), FinalityTagBypass: ptr(false)}) + ht := newHeadTracker(t, opts) ctx := tests.Context(t) require.NoError(t, ht.orm.IdempotentInsertHead(ctx, testutils.Head(799))) ht.ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(head, nil).Once() @@ -287,8 +290,12 @@ func TestHeadTracker_Start(t *testing.T) { ht.ethClient.On("LatestFinalizedBlock", mock.Anything).Return(nil, errors.New("backfill call to finalized failed")).Maybe() ht.ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(nil, errors.New("failed to connect")).Maybe() ht.Start(t) - tests.AssertLogEventually(t, ht.observer, "Loaded chain from DB") - }) + tests.AssertLogEventually(t, ht.observer, "Received new head") + tests.AssertEventually(t, func() bool { + latest := ht.headTracker.LatestChain() + return latest != nil && latest.Number == head.Number + }) + } happyPathFD := func(t *testing.T, opts opts) { head := testutils.Head(1000) ht := newHeadTracker(t, opts) @@ -301,28 +308,46 @@ func TestHeadTracker_Start(t *testing.T) { ht.ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(nil, errors.New("backfill call to finalized failed")).Maybe() ht.ethClient.On("SubscribeNewHead", mock.Anything, mock.Anything).Return(nil, errors.New("failed to connect")).Maybe() ht.Start(t) - tests.AssertLogEventually(t, ht.observer, "Loaded chain from DB") + tests.AssertLogEventually(t, ht.observer, "Received new head") + tests.AssertEventually(t, func() bool { + latest := ht.headTracker.LatestChain() + return latest != nil && latest.Number == head.Number + }) } testCases := []struct { Name string Opts opts + Run func(t *testing.T, opts opts) }{ { Name: "Happy path (Chain FT is disabled & HeadTracker's FT is disabled)", Opts: opts{FinalityTagEnable: ptr(false), FinalityTagBypass: ptr(true)}, + Run: happyPathFD, }, { Name: "Happy path (Chain FT is disabled & HeadTracker's FT is enabled, but ignored)", Opts: opts{FinalityTagEnable: ptr(false), FinalityTagBypass: ptr(false)}, + Run: happyPathFD, }, { Name: "Happy path (Chain FT is enabled & HeadTracker's FT is disabled)", Opts: opts{FinalityTagEnable: ptr(true), FinalityTagBypass: ptr(true)}, + Run: happyPathFD, + }, + { + Name: "Happy path (Chain FT is enabled)", + Opts: opts{FinalityTagEnable: ptr(true), FinalityTagBypass: ptr(false)}, + Run: happyPathFT, }, } for _, tc := range testCases { t.Run(tc.Name, func(t *testing.T) { - happyPathFD(t, tc.Opts) + tc.Run(t, tc.Opts) + }) + t.Run("Disabled Persistence "+tc.Name, func(t *testing.T) { + opts := tc.Opts + opts.ORM = headtracker.NewNullORM() + tc.Run(t, opts) }) } } @@ -769,7 +794,20 @@ func TestHeadTracker_SwitchesToLongestChainWithHeadSamplingDisabled(t *testing.T func TestHeadTracker_Backfill(t *testing.T) { t.Parallel() + t.Run("Enabled Persistence", func(t *testing.T) { + testHeadTrackerBackfill(t, func(t *testing.T) headtracker.ORM { + db := pgtest.NewSqlxDB(t) + return headtracker.NewORM(*testutils.FixtureChainID, db) + }) + }) + t.Run("Disabled Persistence", func(t *testing.T) { + testHeadTrackerBackfill(t, func(t *testing.T) headtracker.ORM { + return headtracker.NewNullORM() + }) + }) +} +func testHeadTrackerBackfill(t *testing.T, newORM func(t *testing.T) headtracker.ORM) { // Heads are arranged as follows: // headN indicates an unpersisted ethereum header // hN indicates a persisted head record @@ -842,14 +880,12 @@ func TestHeadTracker_Backfill(t *testing.T) { } }) - db := pgtest.NewSqlxDB(t) - orm := headtracker.NewORM(*testutils.FixtureChainID, db) - for i := range opts.Heads { - require.NoError(t, orm.IdempotentInsertHead(tests.Context(t), opts.Heads[i])) - } ethClient := testutils.NewEthClientMock(t) ethClient.On("ConfiguredChainID", mock.Anything).Return(evmcfg.EVM().ChainID(), nil) - ht := createHeadTracker(t, ethClient, evmcfg.EVM(), evmcfg.EVM().HeadTracker(), orm) + ht := createHeadTracker(t, ethClient, evmcfg.EVM(), evmcfg.EVM().HeadTracker(), newORM(t)) + for i := range opts.Heads { + require.NoError(t, ht.headSaver.Save(tests.Context(t), opts.Heads[i])) + } _, err := ht.headSaver.Load(tests.Context(t), 0) require.NoError(t, err) return ht @@ -925,7 +961,7 @@ func TestHeadTracker_Backfill(t *testing.T) { h = h.Parent.Load() } - writtenHead, err := htu.orm.HeadByHash(tests.Context(t), head10.Hash) + writtenHead := htu.headSaver.Chain(head10.Hash) require.NoError(t, err) assert.Equal(t, int64(10), writtenHead.Number) }) diff --git a/core/chains/evm/headtracker/orm.go b/core/chains/evm/headtracker/orm.go index 9d569ade08d..5595fc7366a 100644 --- a/core/chains/evm/headtracker/orm.go +++ b/core/chains/evm/headtracker/orm.go @@ -9,6 +9,7 @@ import ( pkgerrors "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" ) @@ -82,3 +83,29 @@ func (orm *DbORM) HeadByHash(ctx context.Context, hash common.Hash) (head *evmty } return head, err } + +type nullORM struct{} + +func NewNullORM() ORM { + return &nullORM{} +} + +func (orm *nullORM) IdempotentInsertHead(ctx context.Context, head *evmtypes.Head) error { + return nil +} + +func (orm *nullORM) TrimOldHeads(ctx context.Context, minBlockNumber int64) (err error) { + return nil +} + +func (orm *nullORM) LatestHead(ctx context.Context) (head *evmtypes.Head, err error) { + return nil, nil +} + +func (orm *nullORM) LatestHeads(ctx context.Context, minBlockNumer int64) (heads []*evmtypes.Head, err error) { + return nil, nil +} + +func (orm *nullORM) HeadByHash(ctx context.Context, hash common.Hash) (head *evmtypes.Head, err error) { + return nil, nil +} diff --git a/core/chains/evm/logpoller/orm_test.go b/core/chains/evm/logpoller/orm_test.go index ba66e166eb5..14f6bbeb6aa 100644 --- a/core/chains/evm/logpoller/orm_test.go +++ b/core/chains/evm/logpoller/orm_test.go @@ -916,7 +916,7 @@ func TestORM_DataWords(t *testing.T) { }, })) - wordFilter := func(wordIdx uint8, word1, word2 uint64) []query.Expression { + wordFilter := func(wordIdx int, word1, word2 uint64) []query.Expression { return []query.Expression{ logpoller.NewAddressFilter(addr), logpoller.NewEventSigFilter(eventSig), diff --git a/core/chains/evm/logpoller/parser.go b/core/chains/evm/logpoller/parser.go index baa681e5efa..19302c89192 100644 --- a/core/chains/evm/logpoller/parser.go +++ b/core/chains/evm/logpoller/parser.go @@ -432,6 +432,12 @@ func orderToString(dir query.SortDirection) (string, error) { } } +// MakeContractReaderCursor is exported to ensure cursor structure remains consistent. +func FormatContractReaderCursor(log Log) string { + return fmt.Sprintf("%d-%d-%s", log.BlockNumber, log.LogIndex, log.TxHash) +} + +// ensure valuesFromCursor remains consistent with the function above that creates a cursor func valuesFromCursor(cursor string) (int64, int, []byte, error) { partCount := 3 @@ -498,11 +504,11 @@ type HashedValueComparator struct { } type eventByWordFilter struct { - WordIndex uint8 + WordIndex int HashedValueComparers []HashedValueComparator } -func NewEventByWordFilter(wordIndex uint8, valueComparers []HashedValueComparator) query.Expression { +func NewEventByWordFilter(wordIndex int, valueComparers []HashedValueComparator) query.Expression { return query.Expression{Primitive: &eventByWordFilter{ WordIndex: wordIndex, HashedValueComparers: valueComparers, diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index f826e9576c1..a6fae4ec5b4 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -221,7 +221,12 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod if !opts.AppConfig.EVMRPCEnabled() { headTracker = headtracker.NullTracker } else if opts.GenHeadTracker == nil { - orm := headtracker.NewORM(*chainID, opts.DS) + var orm headtracker.ORM + if cfg.EVM().HeadTracker().PersistenceEnabled() { + orm = headtracker.NewORM(*chainID, opts.DS) + } else { + orm = headtracker.NewNullORM() + } headSaver = headtracker.NewHeadSaver(l, orm, cfg.EVM(), cfg.EVM().HeadTracker()) headTracker = headtracker.NewHeadTracker(l, client, cfg.EVM(), cfg.EVM().HeadTracker(), headBroadcaster, headSaver, opts.MailMon) } else { diff --git a/core/cmd/solana_node_commands_test.go b/core/cmd/solana_node_commands_test.go index adc699de79b..bc4aa15f7bc 100644 --- a/core/cmd/solana_node_commands_test.go +++ b/core/cmd/solana_node_commands_test.go @@ -20,7 +20,7 @@ import ( func solanaStartNewApplication(t *testing.T, cfgs ...*solcfg.TOMLConfig) *cltest.TestApplication { for i := range cfgs { - cfgs[i].SetDefaults() + cfgs[i].Chain.SetDefaults() } return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Solana = cfgs @@ -72,17 +72,17 @@ func TestShell_IndexSolanaNodes(t *testing.T) { rt := cmd.RendererTable{b} require.NoError(t, nodes.RenderTable(rt)) renderLines := strings.Split(b.String(), "\n") - assert.Equal(t, 17, len(renderLines)) + assert.Equal(t, 19, len(renderLines)) assert.Contains(t, renderLines[2], "Name") assert.Contains(t, renderLines[2], n1.Name) assert.Contains(t, renderLines[3], "Chain ID") assert.Contains(t, renderLines[3], n1.ChainID) assert.Contains(t, renderLines[4], "State") assert.Contains(t, renderLines[4], n1.State) - assert.Contains(t, renderLines[9], "Name") - assert.Contains(t, renderLines[9], n2.Name) - assert.Contains(t, renderLines[10], "Chain ID") - assert.Contains(t, renderLines[10], n2.ChainID) - assert.Contains(t, renderLines[11], "State") - assert.Contains(t, renderLines[11], n2.State) + assert.Contains(t, renderLines[10], "Name") + assert.Contains(t, renderLines[10], n2.Name) + assert.Contains(t, renderLines[11], "Chain ID") + assert.Contains(t, renderLines[11], n2.ChainID) + assert.Contains(t, renderLines[12], "State") + assert.Contains(t, renderLines[12], n2.State) } diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml index bab4385f9fb..660b3e4a7dd 100644 --- a/core/config/docs/chains-evm.toml +++ b/core/config/docs/chains-evm.toml @@ -347,6 +347,11 @@ FinalityTagBypass = true # Default # If actual finality depth exceeds this number, HeadTracker aborts backfill and returns an error. # Has no effect if `FinalityTagsEnabled` = false MaxAllowedFinalityDepth = 10000 # Default +# PersistenceEnabled defines whether HeadTracker needs to store heads in the database. +# Persistence is helpful on chains with large finality depth, where fetching blocks from the latest to the latest finalized takes a lot of time. +# On chains with fast finality, the persistence layer does not improve the chain's load time and only consumes database resources (mainly IO). +# NOTE: persistence should not be disabled for products that use LogBroadcaster, as it might lead to missed on-chain events. +PersistenceEnabled = true # Default [[EVM.KeySpecific]] # Key is the account to apply these settings to diff --git a/core/config/docs/chains-solana.toml b/core/config/docs/chains-solana.toml index 9376445061a..98b777f11c2 100644 --- a/core/config/docs/chains-solana.toml +++ b/core/config/docs/chains-solana.toml @@ -36,9 +36,13 @@ ComputeUnitPriceDefault = 0 # Default FeeBumpPeriod = '3s' # Default # BlockHistoryPollPeriod is the rate to poll for blocks in the block history fee estimator BlockHistoryPollPeriod = '5s' # Default +# ComputeUnitLimitDefault is the compute units limit applied to transactions unless overriden during the txm enqueue +ComputeUnitLimitDefault = 200_000 # Default [[Solana.Nodes]] # Name is a unique (per-chain) identifier for this node. Name = 'primary' # Example # URL is the HTTP(S) endpoint for this node. URL = 'http://solana.web' # Example +# SendOnly is a multinode config that only sends transactions to a node and does not read state +SendOnly = false # Default diff --git a/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go b/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go index 7adf4d8530a..16b8b1d1aad 100644 --- a/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go +++ b/core/gethwrappers/generated/chain_reader_tester/chain_reader_tester.go @@ -30,30 +30,41 @@ var ( _ = abi.ConvertType ) -type InnerTestStruct struct { +type InnerDynamicTestStruct struct { IntVal int64 S string } -type MidLevelTestStruct struct { +type InnerStaticTestStruct struct { + IntVal int64 + A common.Address +} + +type MidLevelDynamicTestStruct struct { + FixedBytes [2]byte + Inner InnerDynamicTestStruct +} + +type MidLevelStaticTestStruct struct { FixedBytes [2]byte - Inner InnerTestStruct + Inner InnerStaticTestStruct } type TestStruct struct { - Field int32 - DifferentField string - OracleId uint8 - OracleIds [32]uint8 - Account common.Address - Accounts []common.Address - BigField *big.Int - NestedStruct MidLevelTestStruct + Field int32 + DifferentField string + OracleId uint8 + OracleIds [32]uint8 + Account common.Address + Accounts []common.Address + BigField *big.Int + NestedDynamicStruct MidLevelDynamicTestStruct + NestedStaticStruct MidLevelStaticTestStruct } var ChainReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int32\",\"name\":\"field\",\"type\":\"int32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"oracleId\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"Accounts\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"indexed\":false,\"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\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"type\":\"tuple\"}],\"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]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"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\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"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]\"},{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"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\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"NestedStruct\",\"type\":\"tuple\"}],\"internalType\":\"structTestStruct\",\"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]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"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\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"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]\"},{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"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\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"NestedStruct\",\"type\":\"tuple\"}],\"internalType\":\"structTestStruct\",\"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\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"string\",\"name\":\"differentField\",\"type\":\"string\"},{\"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\":\"structInnerTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelTestStruct\",\"name\":\"nestedStruct\",\"type\":\"tuple\"}],\"name\":\"triggerEvent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"triggerEventWithDynamicTopic\",\"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\"}]", - Bin: "0x608060405234801561001057600080fd5b50600180548082018255600082905260048082047fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6908101805460086003958616810261010090810a8088026001600160401b0391820219909416939093179093558654808801909755848704909301805496909516909202900a918202910219909216919091179055611a42806100a96000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c8063ab5e0b3811610081578063ef4e1ced1161005b578063ef4e1ced146101de578063f6f871c8146101e5578063fbe9fbf6146101f857600080fd5b8063ab5e0b381461019b578063dbfd7332146101b8578063dd1319b3146101cb57600080fd5b8063679004a4116100b2578063679004a41461012a5780636c9a43b61461013f578063a90e19981461018857600080fd5b80632c45576f146100d95780633272b66c1461010257806349eac2ac14610117575b600080fd5b6100ec6100e7366004610ca3565b61020a565b6040516100f99190610e0c565b60405180910390f35b610115610110366004610f4b565b6104e5565b005b610115610125366004611060565b61053a565b61013261083d565b6040516100f99190611152565b61011561014d3660046111a0565b600280547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b6101156101963660046112d4565b6108c9565b6107c65b60405167ffffffffffffffff90911681526020016100f9565b6101156101c6366004611389565b610923565b6101156101d93660046113cc565b610960565b600361019f565b6100ec6101f3366004611060565b6109b7565b60025467ffffffffffffffff1661019f565b610212610ac0565b600061021f600184611471565b8154811061022f5761022f6114ab565b6000918252602091829020604080516101008101909152600a90920201805460030b8252600181018054929391929184019161026a906114da565b80601f0160208091040260200160405190810160405280929190818152602001828054610296906114da565b80156102e35780601f106102b8576101008083540402835291602001916102e3565b820191906000526020600020905b8154815290600101906020018083116102c657829003601f168201915b5050509183525050600282015460ff166020808301919091526040805161040081018083529190930192916003850191826000855b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161031857505050928452505050600482015473ffffffffffffffffffffffffffffffffffffffff1660208083019190915260058301805460408051828502810185018252828152940193928301828280156103d157602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116103a6575b5050509183525050600682015460170b6020808301919091526040805180820182526007808601805460f01b7fffff0000000000000000000000000000000000000000000000000000000000001683528351808501855260088801805490930b81526009880180549590970196939591948683019491939284019190610456906114da565b80601f0160208091040260200160405190810160405280929190818152602001828054610482906114da565b80156104cf5780601f106104a4576101008083540402835291602001916104cf565b820191906000526020600020905b8154815290600101906020018083116104b257829003601f168201915b5050509190925250505090525090525092915050565b81816040516104f5929190611527565b60405180910390207f3d969732b1bbbb9f1d7eb9f3f14e4cb50a74d950b3ef916a397b85dfbab93c67838360405161052e929190611580565b60405180910390a25050565b60006040518061010001604052808c60030b81526020018b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8a166020808301919091526040805161040081810183529190930192918b9183908390808284376000920191909152505050815273ffffffffffffffffffffffffffffffffffffffff8816602080830191909152604080518883028181018401835289825291909301929189918991829190850190849080828437600092019190915250505090825250601785900b602082015260400161062c846115d6565b905281546001808201845560009384526020938490208351600a9093020180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90931692909217825592820151919290919082019061069290826116c3565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560608201516106e09060038301906020610b0f565b5060808201516004820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905560a08201518051610747916005840191602090910190610ba2565b5060c08201516006820180547fffffffffffffffff0000000000000000000000000000000000000000000000001677ffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905560e082015180516007830180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660f09290921c91909117815560208083015180516008860180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff90921691909117815591810151909190600986019061082a90826116c3565b5050505050505050505050505050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156108bf57602002820191906000526020600020906000905b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff168152602001906008019060208260070104928301926001038202915080841161087a5790505b5050505050905090565b80826040516108d891906117dd565b6040518091039020846040516108ee9190611819565b604051908190038120907f7220e4dbe4e9d0ed5f71acd022bc89c26748ac6784f2c548bc17bb8e52af34b090600090a4505050565b8060030b8260030b8460030b7f91c80dc390f3d041b3a04b0099b19634499541ea26972250986ee4b24a12fac560405160405180910390a4505050565b8960030b7f4f01af651956288a9505cdb2c7565e925522cd4bb7e31f693f331357ec7b1b5f8a8a8a8a8a8a8a8a8a6040516109a39998979695949392919061197a565b60405180910390a250505050505050505050565b6109bf610ac0565b6040518061010001604052808c60030b81526020018b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8a166020808301919091526040805161040081810183529190930192918b9183908390808284376000920191909152505050815273ffffffffffffffffffffffffffffffffffffffff8816602080830191909152604080518883028181018401835289825291909301929189918991829190850190849080828437600092019190915250505090825250601785900b6020820152604001610aaf846115d6565b90529b9a5050505050505050505050565b6040805161010081018252600080825260606020830181905292820152908101610ae8610c1c565b8152600060208201819052606060408301819052820152608001610b0a610c3b565b905290565b600183019183908215610b925791602002820160005b83821115610b6357835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302610b25565b8015610b905782816101000a81549060ff0219169055600101602081600001049283019260010302610b63565b505b50610b9e929150610c8e565b5090565b828054828255906000526020600020908101928215610b92579160200282015b82811115610b9257825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190610bc2565b6040518061040001604052806020906020820280368337509192915050565b604051806040016040528060007dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001610b0a6040518060400160405280600060070b8152602001606081525090565b5b80821115610b9e5760008155600101610c8f565b600060208284031215610cb557600080fd5b5035919050565b60005b83811015610cd7578181015183820152602001610cbf565b50506000910152565b60008151808452610cf8816020860160208601610cbc565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b6020808210610d3d5750610d54565b825160ff1685529384019390910190600101610d2e565b50505050565b600081518084526020808501945080840160005b83811015610da057815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101610d6e565b509495945050505050565b7fffff00000000000000000000000000000000000000000000000000000000000081511682526000602082015160406020850152805160070b60408501526020810151905060406060850152610e046080850182610ce0565b949350505050565b60208152610e2060208201835160030b9052565b600060208301516104e0806040850152610e3e610500850183610ce0565b91506040850151610e54606086018260ff169052565b506060850151610e676080860182610d2a565b50608085015173ffffffffffffffffffffffffffffffffffffffff1661048085015260a08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840381016104a0870152610ec48483610d5a565b935060c08701519150610edd6104c087018360170b9052565b60e0870151915080868503018387015250610ef88382610dab565b9695505050505050565b60008083601f840112610f1457600080fd5b50813567ffffffffffffffff811115610f2c57600080fd5b602083019150836020828501011115610f4457600080fd5b9250929050565b60008060208385031215610f5e57600080fd5b823567ffffffffffffffff811115610f7557600080fd5b610f8185828601610f02565b90969095509350505050565b8035600381900b8114610f9f57600080fd5b919050565b803560ff81168114610f9f57600080fd5b806104008101831015610fc757600080fd5b92915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610f9f57600080fd5b60008083601f84011261100357600080fd5b50813567ffffffffffffffff81111561101b57600080fd5b6020830191508360208260051b8501011115610f4457600080fd5b8035601781900b8114610f9f57600080fd5b60006040828403121561105a57600080fd5b50919050565b6000806000806000806000806000806104e08b8d03121561108057600080fd5b6110898b610f8d565b995060208b013567ffffffffffffffff808211156110a657600080fd5b6110b28e838f01610f02565b909b5099508991506110c660408e01610fa4565b98506110d58e60608f01610fb5565b97506110e46104608e01610fcd565b96506104808d01359150808211156110fb57600080fd5b6111078e838f01610ff1565b909650945084915061111c6104a08e01611036565b93506104c08d013591508082111561113357600080fd5b506111408d828e01611048565b9150509295989b9194979a5092959850565b6020808252825182820181905260009190848201906040850190845b8181101561119457835167ffffffffffffffff168352928401929184019160010161116e565b50909695505050505050565b6000602082840312156111b257600080fd5b813567ffffffffffffffff811681146111ca57600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611223576112236111d1565b60405290565b600082601f83011261123a57600080fd5b813567ffffffffffffffff80821115611255576112556111d1565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561129b5761129b6111d1565b816040528381528660208588010111156112b457600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600061044084860312156112ea57600080fd5b833567ffffffffffffffff8082111561130257600080fd5b61130e87838801611229565b94506020915086603f87011261132357600080fd5b6040516104008101818110838211171561133f5761133f6111d1565b60405290508061042087018881111561135757600080fd5b8388015b818110156113795761136c81610fa4565b845292840192840161135b565b5095989097509435955050505050565b60008060006060848603121561139e57600080fd5b6113a784610f8d565b92506113b560208501610f8d565b91506113c360408501610f8d565b90509250925092565b6000806000806000806000806000806104e08b8d0312156113ec57600080fd5b6113f58b610f8d565b995061140360208c01610fa4565b98506114128c60408d01610fb5565b97506114216104408c01610fcd565b96506104608b013567ffffffffffffffff8082111561143f57600080fd5b61144b8e838f01610ff1565b90985096506104808d013591508082111561146557600080fd5b6111078e838f01610f02565b81810381811115610fc7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c908216806114ee57607f821691505b60208210810361105a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000610e04602083018486611537565b80357fffff00000000000000000000000000000000000000000000000000000000000081168114610f9f57600080fd5b8035600781900b8114610f9f57600080fd5b6000604082360312156115e857600080fd5b6115f0611200565b6115f983611594565b8152602083013567ffffffffffffffff8082111561161657600080fd5b81850191506040823603121561162b57600080fd5b611633611200565b61163c836115c4565b815260208301358281111561165057600080fd5b61165c36828601611229565b60208301525080602085015250505080915050919050565b601f8211156116be57600081815260208120601f850160051c8101602086101561169b5750805b601f850160051c820191505b818110156116ba578281556001016116a7565b5050505b505050565b815167ffffffffffffffff8111156116dd576116dd6111d1565b6116f1816116eb84546114da565b84611674565b602080601f831160018114611744576000841561170e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556116ba565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561179157888601518255948401946001909101908401611772565b50858210156117cd57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60008183825b60208082106117f25750611809565b825160ff16845292830192909101906001016117e3565b5050506104008201905092915050565b6000825161182b818460208701610cbc565b9190910192915050565b8183526000602080850194508260005b85811015610da05773ffffffffffffffffffffffffffffffffffffffff61186b83610fcd565b1687529582019590820190600101611845565b7fffff0000000000000000000000000000000000000000000000000000000000006118a882611594565b168252600060208201357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126118e257600080fd5b6040602085015282016118f4816115c4565b60070b604085015260208101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811261193157600080fd5b0160208101903567ffffffffffffffff81111561194d57600080fd5b80360382131561195c57600080fd5b60406060860152611971608086018284611537565b95945050505050565b60006104c060ff808d16845260208085018d60005b838110156119b457846119a183610fa4565b168352918301919083019060010161198f565b505050505073ffffffffffffffffffffffffffffffffffffffff8a16610420840152806104408401526119ea818401898b611835565b9050828103610460840152611a00818789611537565b9050611a1261048084018660170b9052565b8281036104a0840152611a25818561187e565b9c9b50505050505050505050505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"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\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"structMidLevelDynamicTestStruct\",\"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\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"structMidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"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]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"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\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelDynamicTestStruct\",\"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\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelStaticTestStruct\",\"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]\"},{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"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\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelDynamicTestStruct\",\"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\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelStaticTestStruct\",\"name\":\"NestedStaticStruct\",\"type\":\"tuple\"}],\"internalType\":\"structTestStruct\",\"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]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"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\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelDynamicTestStruct\",\"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\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelStaticTestStruct\",\"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]\"},{\"internalType\":\"address\",\"name\":\"Account\",\"type\":\"address\"},{\"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\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelDynamicTestStruct\",\"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\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelStaticTestStruct\",\"name\":\"NestedStaticStruct\",\"type\":\"tuple\"}],\"internalType\":\"structTestStruct\",\"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\":\"structInnerDynamicTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelDynamicTestStruct\",\"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\":\"structInnerStaticTestStruct\",\"name\":\"Inner\",\"type\":\"tuple\"}],\"internalType\":\"structMidLevelStaticTestStruct\",\"name\":\"nestedStaticStruct\",\"type\":\"tuple\"},{\"internalType\":\"uint8[32]\",\"name\":\"oracleIds\",\"type\":\"uint8[32]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"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\":\"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\"}]", + Bin: "0x608060405234801561001057600080fd5b50600180548082018255600082905260048082047fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6908101805460086003958616810261010090810a8088026001600160401b0391820219909416939093179093558654808801909755848704909301805496909516909202900a918202910219909216919091179055611d9a806100a96000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80636c9a43b611610081578063dbfd73321161005b578063dbfd7332146101de578063ef4e1ced146101f1578063fbe9fbf6146101f857600080fd5b80636c9a43b614610165578063a90e1998146101ae578063ab5e0b38146101c157600080fd5b80634149667f116100b25780634149667f1461012a5780635f7104a21461013d578063679004a41461015057600080fd5b80631b48259e146100d95780632c45576f146100ee5780633272b66c14610117575b600080fd5b6100ec6100e7366004610f5d565b61020a565b005b6101016100fc366004611061565b610264565b60405161010e91906111ca565b60405180910390f35b6100ec610125366004611323565b6105bc565b610101610138366004611365565b610611565b6100ec61014b366004611365565b610731565b610158610af6565b60405161010e9190611458565b6100ec6101733660046114a6565b600280547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b6100ec6101bc3660046115da565b610b82565b6107c65b60405167ffffffffffffffff909116815260200161010e565b6100ec6101ec36600461168f565b610bdc565b60036101c5565b60025467ffffffffffffffff166101c5565b8a60030b7fae927edae02672fdcce7d7e8cf34c611ed3856914a159df5f2a59307b767c25b8b8b8b8b8b8b8b8b8b8b60405161024f9a99989796959493929190611844565b60405180910390a25050505050505050505050565b61026c610c19565b60006102796001846119c4565b81548110610289576102896119fe565b6000918252602091829020604080516101208101909152600c90920201805460030b825260018101805492939192918401916102c490611a2d565b80601f01602080910402602001604051908101604052809291908181526020018280546102f090611a2d565b801561033d5780601f106103125761010080835404028352916020019161033d565b820191906000526020600020905b81548152906001019060200180831161032057829003601f168201915b5050509183525050600282015460ff166020808301919091526040805161040081018083529190930192916003850191826000855b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161037257505050928452505050600482015473ffffffffffffffffffffffffffffffffffffffff16602080830191909152600583018054604080518285028101850182528281529401939283018282801561042b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610400575b5050509183525050600682015460170b6020808301919091526040805180820182526007808601805460f01b7fffff0000000000000000000000000000000000000000000000000000000000001683528351808501855260088801805490930b815260098801805495909701969395919486830194919392840191906104b090611a2d565b80601f01602080910402602001604051908101604052809291908181526020018280546104dc90611a2d565b80156105295780601f106104fe57610100808354040283529160200191610529565b820191906000526020600020905b81548152906001019060200180831161050c57829003601f168201915b505050919092525050509052508152604080518082018252600a84015460f01b7fffff0000000000000000000000000000000000000000000000000000000000001681528151808301909252600b90930154600781900b825268010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1660208083019190915280840191909152015292915050565b81816040516105cc929190611a7a565b60405180910390207f3d969732b1bbbb9f1d7eb9f3f14e4cb50a74d950b3ef916a397b85dfbab93c678383604051610605929190611a8a565b60405180910390a25050565b610619610c19565b6040518061012001604052808d60030b81526020018c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8b166020808301919091526040805161040081810183529190930192918c9183908390808284376000920191909152505050815273ffffffffffffffffffffffffffffffffffffffff891660208083019190915260408051898302818101840183528a82529190930192918a918a91829190850190849080828437600092019190915250505090825250601786900b602082015260400161070985611a9e565b815260200161071d36859003850185611b3c565b905290505b9b9a5050505050505050505050565b60006040518061012001604052808d60030b81526020018c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060ff8b166020808301919091526040805161040081810183529190930192918c9183908390808284376000920191909152505050815273ffffffffffffffffffffffffffffffffffffffff891660208083019190915260408051898302818101840183528a82529190930192918a918a91829190850190849080828437600092019190915250505090825250601786900b602082015260400161082385611a9e565b815260200161083736859003850185611b3c565b905281546001808201845560009384526020938490208351600c9093020180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90931692909217825592820151919290919082019061089d9082611c1b565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560608201516108eb9060038301906020610c9b565b5060808201516004820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905560a08201518051610952916005840191602090910190610d2e565b5060c08201516006820180547fffffffffffffffff0000000000000000000000000000000000000000000000001677ffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905560e082015180516007830180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660f09290921c91909117815560208083015180516008860180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff909216919091178155918101519091906009860190610a359082611c1b565b5050505061010092909201518051600a8301805460f09290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092169190911790556020908101518051600b9093018054919092015173ffffffffffffffffffffffffffffffffffffffff1668010000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090911667ffffffffffffffff90931692909217919091179055505050505050505050505050565b60606001805480602002602001604051908101604052809291908181526020018280548015610b7857602002820191906000526020600020906000905b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff1681526020019060080190602082600701049283019260010382029150808411610b335790505b5050505050905090565b8082604051610b919190611d35565b604051809103902084604051610ba79190611d71565b604051908190038120907f7220e4dbe4e9d0ed5f71acd022bc89c26748ac6784f2c548bc17bb8e52af34b090600090a4505050565b8060030b8260030b8460030b7f91c80dc390f3d041b3a04b0099b19634499541ea26972250986ee4b24a12fac560405160405180910390a4505050565b6040805161012081018252600080825260606020830181905292820152908101610c41610da8565b8152600060208201819052606060408301819052820152608001610c63610dc7565b8152602001610c966040805180820182526000808252825180840190935280835260208381019190915290919082015290565b905290565b600183019183908215610d1e5791602002820160005b83821115610cef57835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302610cb1565b8015610d1c5782816101000a81549060ff0219169055600101602081600001049283019260010302610cef565b505b50610d2a929150610e1a565b5090565b828054828255906000526020600020908101928215610d1e579160200282015b82811115610d1e57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190610d4e565b6040518061040001604052806020906020820280368337509192915050565b604051806040016040528060007dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001610c966040518060400160405280600060070b8152602001606081525090565b5b80821115610d2a5760008155600101610e1b565b8035600381900b8114610e4157600080fd5b919050565b803560ff81168114610e4157600080fd5b600060408284031215610e6957600080fd5b50919050565b600060608284031215610e6957600080fd5b806104008101831015610e9357600080fd5b92915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610e4157600080fd5b60008083601f840112610ecf57600080fd5b50813567ffffffffffffffff811115610ee757600080fd5b6020830191508360208260051b8501011115610f0257600080fd5b9250929050565b60008083601f840112610f1b57600080fd5b50813567ffffffffffffffff811115610f3357600080fd5b602083019150836020828501011115610f0257600080fd5b8035601781900b8114610e4157600080fd5b60008060008060008060008060008060006105408c8e031215610f7f57600080fd5b610f888c610e2f565b9a50610f9660208d01610e46565b995067ffffffffffffffff8060408e01351115610fb257600080fd5b610fc28e60408f01358f01610e57565b9950610fd18e60608f01610e6f565b9850610fe08e60c08f01610e81565b9750610fef6104c08e01610e99565b9650806104e08e0135111561100357600080fd5b6110148e6104e08f01358f01610ebd565b90965094506105008d013581101561102b57600080fd5b5061103d8d6105008e01358e01610f09565b909350915061104f6105208d01610f4b565b90509295989b509295989b9093969950565b60006020828403121561107357600080fd5b5035919050565b60005b8381101561109557818101518382015260200161107d565b50506000910152565b600081518084526110b681602086016020860161107a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60208082106110fb5750611112565b825160ff16855293840193909101906001016110ec565b50505050565b600081518084526020808501945080840160005b8381101561115e57815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161112c565b509495945050505050565b7fffff00000000000000000000000000000000000000000000000000000000000081511682526000602082015160406020850152805160070b604085015260208101519050604060608501526111c2608085018261109e565b949350505050565b602081526111de60208201835160030b9052565b6000602083015161054060408401526111fb61056084018261109e565b90506040840151611211606085018260ff169052565b50606084015161122460808501826110e8565b50608084015173ffffffffffffffffffffffffffffffffffffffff1661048084015260a08401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084830381016104a08601526112818383611118565b925060c0860151915061129a6104c086018360170b9052565b60e0860151915080858403016104e0860152506112b78282611169565b61010086015180517fffff00000000000000000000000000000000000000000000000000000000000016610500870152602080820151805160070b610520890152015173ffffffffffffffffffffffffffffffffffffffff166105408701529092509050509392505050565b6000806020838503121561133657600080fd5b823567ffffffffffffffff81111561134d57600080fd5b61135985828601610f09565b90969095509350505050565b60008060008060008060008060008060006105408c8e03121561138757600080fd5b6113908c610e2f565b9a5067ffffffffffffffff8060208e013511156113ac57600080fd5b6113bc8e60208f01358f01610f09565b909b5099506113cd60408e01610e46565b98506113dc8e60608f01610e81565b97506113eb6104608e01610e99565b9650806104808e013511156113ff57600080fd5b6114108e6104808f01358f01610ebd565b90965094506114226104a08e01610f4b565b9350806104c08e0135111561143657600080fd5b506114488d6104c08e01358e01610e57565b915061104f8d6104e08e01610e6f565b6020808252825182820181905260009190848201906040850190845b8181101561149a57835167ffffffffffffffff1683529284019291840191600101611474565b50909695505050505050565b6000602082840312156114b857600080fd5b813567ffffffffffffffff811681146114d057600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611529576115296114d7565b60405290565b600082601f83011261154057600080fd5b813567ffffffffffffffff8082111561155b5761155b6114d7565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156115a1576115a16114d7565b816040528381528660208588010111156115ba57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600061044084860312156115f057600080fd5b833567ffffffffffffffff8082111561160857600080fd5b6116148783880161152f565b94506020915086603f87011261162957600080fd5b60405161040081018181108382111715611645576116456114d7565b60405290508061042087018881111561165d57600080fd5b8388015b8181101561167f5761167281610e46565b8452928401928401611661565b5095989097509435955050505050565b6000806000606084860312156116a457600080fd5b6116ad84610e2f565b92506116bb60208501610e2f565b91506116c960408501610e2f565b90509250925092565b80357fffff00000000000000000000000000000000000000000000000000000000000081168114610e4157600080fd5b8035600781900b8114610e4157600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b7fffff000000000000000000000000000000000000000000000000000000000000611787826116d2565b16825261179660208201611702565b60070b602083015273ffffffffffffffffffffffffffffffffffffffff6117bf60408301610e99565b1660408301525050565b8060005b60208082106117dc5750611112565b60ff6117e784610e46565b1685529384019391909101906001016117cd565b8183526000602080850194508260005b8581101561115e5773ffffffffffffffffffffffffffffffffffffffff61183183610e99565b168752958201959082019060010161180b565b600061052060ff8d1683528060208401527fffff00000000000000000000000000000000000000000000000000000000000061187f8d6116d2565b16818401525060208b01357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18c36030181126118ba57600080fd5b60406105408401528b016118cd81611702565b60070b61056084015260208101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811261190b57600080fd5b0160208101903567ffffffffffffffff81111561192757600080fd5b80360382131561193657600080fd5b604061058085015261194d6105a085018284611714565b91505061195d604084018c61175d565b61196a60a084018b6117c9565b73ffffffffffffffffffffffffffffffffffffffff89166104a08401528281036104c084015261199b81888a6117fb565b90508281036104e08401526119b1818688611714565b91505061072261050083018460170b9052565b81810381811115610e93577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c90821680611a4157607f821691505b602082108103610e69577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8183823760009101908152919050565b6020815260006111c2602083018486611714565b600060408236031215611ab057600080fd5b611ab8611506565b611ac1836116d2565b8152602083013567ffffffffffffffff80821115611ade57600080fd5b818501915060408236031215611af357600080fd5b611afb611506565b611b0483611702565b8152602083013582811115611b1857600080fd5b611b243682860161152f565b60208301525080602085015250505080915050919050565b60008183036060811215611b4f57600080fd5b611b57611506565b611b60846116d2565b815260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083011215611b9257600080fd5b611b9a611506565b9150611ba860208501611702565b8252611bb660408501610e99565b6020830152816020820152809250505092915050565b601f821115611c1657600081815260208120601f850160051c81016020861015611bf35750805b601f850160051c820191505b81811015611c1257828155600101611bff565b5050505b505050565b815167ffffffffffffffff811115611c3557611c356114d7565b611c4981611c438454611a2d565b84611bcc565b602080601f831160018114611c9c5760008415611c665750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611c12565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611ce957888601518255948401946001909101908401611cca565b5085821015611d2557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60008183825b6020808210611d4a5750611d61565b825160ff1684529283019290910190600101611d3b565b5050506104008201905092915050565b60008251611d8381846020870161107a565b919091019291505056fea164736f6c6343000813000a", } var ChainReaderTesterABI = ChainReaderTesterMetaData.ABI @@ -302,9 +313,9 @@ func (_ChainReaderTester *ChainReaderTesterCallerSession) GetSliceValue() ([]uin return _ChainReaderTester.Contract.GetSliceValue(&_ChainReaderTester.CallOpts) } -func (_ChainReaderTester *ChainReaderTesterCaller) ReturnSeen(opts *bind.CallOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { +func (_ChainReaderTester *ChainReaderTesterCaller) ReturnSeen(opts *bind.CallOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (TestStruct, error) { var out []interface{} - err := _ChainReaderTester.contract.Call(opts, &out, "returnSeen", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) + err := _ChainReaderTester.contract.Call(opts, &out, "returnSeen", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) if err != nil { return *new(TestStruct), err @@ -316,24 +327,24 @@ func (_ChainReaderTester *ChainReaderTesterCaller) ReturnSeen(opts *bind.CallOpt } -func (_ChainReaderTester *ChainReaderTesterSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { - return _ChainReaderTester.Contract.ReturnSeen(&_ChainReaderTester.CallOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (TestStruct, error) { + return _ChainReaderTester.Contract.ReturnSeen(&_ChainReaderTester.CallOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) } -func (_ChainReaderTester *ChainReaderTesterCallerSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) { - return _ChainReaderTester.Contract.ReturnSeen(&_ChainReaderTester.CallOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterCallerSession) ReturnSeen(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (TestStruct, error) { + return _ChainReaderTester.Contract.ReturnSeen(&_ChainReaderTester.CallOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) } -func (_ChainReaderTester *ChainReaderTesterTransactor) AddTestStruct(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.contract.Transact(opts, "addTestStruct", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactor) AddTestStruct(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.contract.Transact(opts, "addTestStruct", field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) } -func (_ChainReaderTester *ChainReaderTesterSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.Contract.AddTestStruct(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.Contract.AddTestStruct(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) } -func (_ChainReaderTester *ChainReaderTesterTransactorSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.Contract.AddTestStruct(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactorSession) AddTestStruct(field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (*types.Transaction, error) { + return _ChainReaderTester.Contract.AddTestStruct(&_ChainReaderTester.TransactOpts, field, differentField, oracleId, oracleIds, account, accounts, bigField, nestedDynamicStruct, nestedStaticStruct) } func (_ChainReaderTester *ChainReaderTesterTransactor) SetAlterablePrimitiveValue(opts *bind.TransactOpts, value uint64) (*types.Transaction, error) { @@ -348,16 +359,16 @@ func (_ChainReaderTester *ChainReaderTesterTransactorSession) SetAlterablePrimit return _ChainReaderTester.Contract.SetAlterablePrimitiveValue(&_ChainReaderTester.TransactOpts, value) } -func (_ChainReaderTester *ChainReaderTesterTransactor) TriggerEvent(opts *bind.TransactOpts, field int32, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, differentField string, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.contract.Transact(opts, "triggerEvent", field, oracleId, oracleIds, account, accounts, differentField, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactor) TriggerEvent(opts *bind.TransactOpts, field int32, oracleId uint8, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct, oracleIds [32]uint8, account common.Address, accounts []common.Address, differentField string, bigField *big.Int) (*types.Transaction, error) { + return _ChainReaderTester.contract.Transact(opts, "triggerEvent", field, oracleId, nestedDynamicStruct, nestedStaticStruct, oracleIds, account, accounts, differentField, bigField) } -func (_ChainReaderTester *ChainReaderTesterSession) TriggerEvent(field int32, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, differentField string, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.Contract.TriggerEvent(&_ChainReaderTester.TransactOpts, field, oracleId, oracleIds, account, accounts, differentField, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterSession) TriggerEvent(field int32, oracleId uint8, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct, oracleIds [32]uint8, account common.Address, accounts []common.Address, differentField string, bigField *big.Int) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerEvent(&_ChainReaderTester.TransactOpts, field, oracleId, nestedDynamicStruct, nestedStaticStruct, oracleIds, account, accounts, differentField, bigField) } -func (_ChainReaderTester *ChainReaderTesterTransactorSession) TriggerEvent(field int32, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, differentField string, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) { - return _ChainReaderTester.Contract.TriggerEvent(&_ChainReaderTester.TransactOpts, field, oracleId, oracleIds, account, accounts, differentField, bigField, nestedStruct) +func (_ChainReaderTester *ChainReaderTesterTransactorSession) TriggerEvent(field int32, oracleId uint8, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct, oracleIds [32]uint8, account common.Address, accounts []common.Address, differentField string, bigField *big.Int) (*types.Transaction, error) { + return _ChainReaderTester.Contract.TriggerEvent(&_ChainReaderTester.TransactOpts, field, oracleId, nestedDynamicStruct, nestedStaticStruct, oracleIds, account, accounts, differentField, bigField) } func (_ChainReaderTester *ChainReaderTesterTransactor) TriggerEventWithDynamicTopic(opts *bind.TransactOpts, field string) (*types.Transaction, error) { @@ -457,15 +468,16 @@ func (it *ChainReaderTesterTriggeredIterator) Close() error { } type ChainReaderTesterTriggered struct { - Field int32 - OracleId uint8 - OracleIds [32]uint8 - Account common.Address - Accounts []common.Address - DifferentField string - BigField *big.Int - NestedStruct MidLevelTestStruct - Raw types.Log + Field int32 + OracleId uint8 + NestedDynamicStruct MidLevelDynamicTestStruct + NestedStaticStruct MidLevelStaticTestStruct + OracleIds [32]uint8 + Account common.Address + Accounts []common.Address + DifferentField string + BigField *big.Int + Raw types.Log } func (_ChainReaderTester *ChainReaderTesterFilterer) FilterTriggered(opts *bind.FilterOpts, field []int32) (*ChainReaderTesterTriggeredIterator, error) { @@ -965,7 +977,7 @@ func (_ChainReaderTester *ChainReaderTester) ParseLog(log types.Log) (generated. } func (ChainReaderTesterTriggered) Topic() common.Hash { - return common.HexToHash("0x4f01af651956288a9505cdb2c7565e925522cd4bb7e31f693f331357ec7b1b5f") + return common.HexToHash("0xae927edae02672fdcce7d7e8cf34c611ed3856914a159df5f2a59307b767c25b") } func (ChainReaderTesterTriggeredEventWithDynamicTopic) Topic() common.Hash { @@ -995,13 +1007,13 @@ type ChainReaderTesterInterface interface { GetSliceValue(opts *bind.CallOpts) ([]uint64, error) - ReturnSeen(opts *bind.CallOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (TestStruct, error) + ReturnSeen(opts *bind.CallOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (TestStruct, error) - AddTestStruct(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) + AddTestStruct(opts *bind.TransactOpts, field int32, differentField string, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, bigField *big.Int, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct) (*types.Transaction, error) SetAlterablePrimitiveValue(opts *bind.TransactOpts, value uint64) (*types.Transaction, error) - TriggerEvent(opts *bind.TransactOpts, field int32, oracleId uint8, oracleIds [32]uint8, account common.Address, accounts []common.Address, differentField string, bigField *big.Int, nestedStruct MidLevelTestStruct) (*types.Transaction, error) + TriggerEvent(opts *bind.TransactOpts, field int32, oracleId uint8, nestedDynamicStruct MidLevelDynamicTestStruct, nestedStaticStruct MidLevelStaticTestStruct, oracleIds [32]uint8, account common.Address, accounts []common.Address, differentField string, bigField *big.Int) (*types.Transaction, error) TriggerEventWithDynamicTopic(opts *bind.TransactOpts, field string) (*types.Transaction, error) diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 18acf5fc30f..b1b5a56186a 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -24,7 +24,7 @@ batch_vrf_coordinator_v2: ../../contracts/solc/v0.8.6/BatchVRFCoordinatorV2/Batc batch_vrf_coordinator_v2plus: ../../contracts/solc/v0.8.19/BatchVRFCoordinatorV2Plus/BatchVRFCoordinatorV2Plus.abi ../../contracts/solc/v0.8.19/BatchVRFCoordinatorV2Plus/BatchVRFCoordinatorV2Plus.bin f13715b38b5b9084b08bffa571fb1c8ef686001535902e1255052f074b31ad4e blockhash_store: ../../contracts/solc/v0.8.19/BlockhashStore/BlockhashStore.abi ../../contracts/solc/v0.8.19/BlockhashStore/BlockhashStore.bin 31b118f9577240c8834c35f8b5a1440e82a6ca8aea702970de2601824b6ab0e1 chain_module_base: ../../contracts/solc/v0.8.19/ChainModuleBase/ChainModuleBase.abi ../../contracts/solc/v0.8.19/ChainModuleBase/ChainModuleBase.bin 7a82cc28014761090185c2650239ad01a0901181f1b2b899b42ca293bcda3741 -chain_reader_tester: ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.abi ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.bin 84c4223c4dbd51aafd77a6787f4b84ce80f661ce86a907c1431c5b82d633f2ad +chain_reader_tester: ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.abi ../../contracts/solc/v0.8.19/ChainReaderTester/ChainReaderTester.bin b9a488fc786f584a617764d8dc1722acdb30defb6b8f638e0ae03442795eaf3e chain_specific_util_helper: ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.abi ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.bin 66eb30b0717fefe05672df5ec863c0b9a5a654623c4757307a2726d8f31e26b1 counter: ../../contracts/solc/v0.8.6/Counter/Counter.abi ../../contracts/solc/v0.8.6/Counter/Counter.bin 6ca06e000e8423573ffa0bdfda749d88236ab3da2a4cbb4a868c706da90488c9 cron_upkeep_factory_wrapper: ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeepFactory.abi - dacb0f8cdf54ae9d2781c5e720fc314b32ed5e58eddccff512c75d6067292cd7 diff --git a/core/scripts/chaincli/DEBUGGING.md b/core/scripts/chaincli/DEBUGGING.md index 3696b225cb6..d032228f3ce 100644 --- a/core/scripts/chaincli/DEBUGGING.md +++ b/core/scripts/chaincli/DEBUGGING.md @@ -6,6 +6,9 @@ Use this script to debug and diagnose possible issues with registered upkeeps in Before starting, you will need: +- An archival RPC URL (required) and Tenderly credential (optional) + In order to get an archive URL, it's recommended to go to your Infura or Alchemy account (free tier should do) and get + a RPC URL. - A registered [upkeep](https://docs.chain.link/chainlink-automation/overview/getting-started) - A working [Go](https://go.dev/doc/install) installation, please use this Go [version](https://github.com/smartcontractkit/chainlink/blob/develop/go.mod#L3) diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go index 79dfc5d0182..e60bc8749ff 100644 --- a/core/scripts/chaincli/handler/debug.go +++ b/core/scripts/chaincli/handler/debug.go @@ -24,6 +24,8 @@ import ( ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" + "github.com/smartcontractkit/chainlink/v2/core/cbor" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evm21 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21" commonhex "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" @@ -47,6 +49,10 @@ const ( expectedVersion23 = "AutomationRegistry 2.3.0" ) +type UpkeepOffchainConfig struct { + MaxGasPrice *big.Int `json:"maxGasPrice" cbor:"maxGasPrice"` +} + var mercuryPacker = mercury.NewAbiPacker() var packer = encoding.NewAbiPacker() @@ -135,6 +141,10 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { // do basic checks upkeepInfo = getUpkeepInfoAndRunBasicChecks(v2common, triggerCallOpts, upkeepID, chainID) + cgp, mgp := getGasPrice(ctx, k, upkeepInfo) + log.Printf("CURRENT gas price (you cannot call eth_gasPrice on any non latest block) is %s, this upkeep's MAX gas price is %s\n", cgp, mgp) + log.Printf("If upkeep's max gas price (if configured) is lower than the gas price when this upkeep was previously checked, the simulation will fail and this upkeep won't be performed.\n") + var tmpCheckResult autov2common.CheckUpkeep0 tmpCheckResult, err = v2common.CheckUpkeep0(triggerCallOpts, upkeepID) if err != nil { @@ -209,6 +219,10 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { // do basic checks upkeepInfo = getUpkeepInfoAndRunBasicChecks(v2common, triggerCallOpts, upkeepID, chainID) + cgp, mgp := getGasPrice(ctx, k, upkeepInfo) + log.Printf("CURRENT gas price (you cannot call eth_gasPrice on any non latest block) is %s, this upkeep's MAX gas price is %s\n", cgp, mgp) + log.Printf("If upkeep's max gas price (if configured) is lower than the gas price when this upkeep was previously checked, the simulation will fail and this upkeep won't be performed.\n") + var rawTriggerConfig []byte rawTriggerConfig, err = v2common.GetUpkeepTriggerConfig(triggerCallOpts, upkeepID) if err != nil { @@ -387,6 +401,36 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { } } +func getGasPrice(ctx context.Context, k *Keeper, upkeepInfo autov2common.IAutomationV21PlusCommonUpkeepInfoLegacy) (*assets.Wei, *assets.Wei) { + var cgp *assets.Wei + var err error + var gp *big.Int + // get gas price, eth_gasPrice does not take arguments, so we cannot access gas price at an older block + gp, err = k.client.SuggestGasPrice(ctx) + if err != nil { + log.Printf("⚠️ failed to get current gas price due to %v", err) + } else { + cgp = assets.NewWei(gp) + log.Printf("current gas price is %s", cgp) + } + + var mgp *assets.Wei + // check if max gas price is configured + if len(upkeepInfo.OffchainConfig) != 0 { + var offchainConfig UpkeepOffchainConfig + err := cbor.ParseDietCBORToStruct(upkeepInfo.OffchainConfig, &offchainConfig) + if err != nil { + log.Printf("failed to parse offchain config bytes to max gas price\n") + } else { + mgp = assets.NewWei(offchainConfig.MaxGasPrice) + } + } else { + log.Printf("offchain config is not configured for this upkeep\n") + } + + return cgp, mgp +} + func getUpkeepInfoAndRunBasicChecks(keeperRegistry21 *autov2common.IAutomationV21PlusCommon, callOpts *bind.CallOpts, upkeepID *big.Int, chainID int64) autov2common.IAutomationV21PlusCommonUpkeepInfoLegacy { // get upkeep info upkeepInfo, err := keeperRegistry21.GetUpkeep(callOpts, upkeepID) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 26714eb3d14..b32ae445022 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -22,7 +22,7 @@ require ( github.com/prometheus/client_golang v1.20.0 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc + github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 github.com/spf13/cobra v1.8.1 @@ -271,11 +271,11 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.23 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 2ca81055186..6433035ca02 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1081,18 +1081,18 @@ github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnj github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342 h1:uEgdiVPKiPkwSXpsRgK9gxC2TMpjvE5GXpSPl/C20r0= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342/go.mod h1:VyldDDFSelaLyEXO1M7xVoGTTtlT9apfxh90vIMeOwc= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc h1:ALbyaoRzUSXQ2NhGFKVOyJqO22IB5yQjhjKWbIZGbrI= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc/go.mod h1:F6WUS6N4mP5ScwpwyTyAJc9/vjR+GXbMCRUOVekQi1g= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd h1:16Hwnz4hdmWKOy5qVH9wHfyT1XXM0k31M3naexwzpVo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd/go.mod h1:/nGkIe25kgtr+l6y30VH+aTVaxu0NjIEEEhtV1TDlaE= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670 h1:z+XnayyX7pyvVv9OuMQ7oik7RkguQeWHhxcOoVM4oKI= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670/go.mod h1:F6WUS6N4mP5ScwpwyTyAJc9/vjR+GXbMCRUOVekQi1g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7 h1:lTGIOQYLk1Ufn++X/AvZnt6VOcuhste5yp+C157No/Q= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7/go.mod h1:BMYE1vC/pGmdFSsOJdPrAA0/4gZ0Xo0SxTMdGspBtRo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2 h1:yRk4ektpx/UxwarqAfgxUXLrsYXlaNeP1NOwzHGrK2Q= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2/go.mod h1:rNhNSrrRMvkgAm5SA6bNTdh2340bTQQZdUVNtZ2o2bk= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f h1:p4p3jBT91EQyLuAMvHD+zNJsuAYI/QjJbzuGUJ7wIgg= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f/go.mod h1:FLlWBt2hwiMVgt9AcSo6wBJYIRd/nsc8ENbV1Wir1bw= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664 h1:JPs35oSO07PK3Qv7Kyv0GJHVLacIE1IkrvefaPyBjKs= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664/go.mod h1:iJ9DKYo0F64ue7IogAIELwU2DfrhEAh76eSmZOilT8A= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff h1:piMugtrRlbVdcC6xZF37me686eS1YwpLQ0kN2v2b9YE= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff/go.mod h1:5jD47oCERRQ4eGi0iNdk9ZV5HMEdolfQwHpUX1+Ix4s= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae h1:d+B8y2Nd/PrnPMNoaSPn3eDgUgxcVcIqAxGrvYu/gGw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae/go.mod h1:ec/a20UZ7YRK4oxJcnTBFzp1+DBcJcwqEaerUMsktMs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index ed69475a54e..375884d8fea 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -102,7 +102,7 @@ var ( ChainID: ubig.NewI(1), Chain: evmcfg.Chain{ FinalityDepth: ptr[uint32](26), - FinalityTagEnabled: ptr[bool](false), + FinalityTagEnabled: ptr[bool](true), FinalizedBlockOffset: ptr[uint32](12), }, Nodes: []*evmcfg.Node{ @@ -534,7 +534,7 @@ func TestConfig_Marshal(t *testing.T) { BlockBackfillSkip: ptr(true), ChainType: chaintype.NewConfig("Optimism"), FinalityDepth: ptr[uint32](42), - FinalityTagEnabled: ptr[bool](false), + FinalityTagEnabled: ptr[bool](true), FlagsContractAddress: mustAddress("0xae4E781a6218A8031764928E88d457937A954fC3"), FinalizedBlockOffset: ptr[uint32](16), @@ -622,6 +622,7 @@ func TestConfig_Marshal(t *testing.T) { SamplingInterval: &hour, FinalityTagBypass: ptr[bool](false), MaxAllowedFinalityDepth: ptr[uint32](1500), + PersistenceEnabled: ptr(false), }, NodePool: evmcfg.NodePool{ @@ -709,11 +710,12 @@ func TestConfig_Marshal(t *testing.T) { ComputeUnitPriceDefault: ptr[uint64](100), FeeBumpPeriod: commoncfg.MustNewDuration(time.Minute), BlockHistoryPollPeriod: commoncfg.MustNewDuration(time.Minute), + ComputeUnitLimitDefault: ptr[uint32](100_000), }, Nodes: []*solcfg.Node{ {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://solana.web")}, - {Name: ptr("foo"), URL: commoncfg.MustParseURL("http://solana.foo")}, - {Name: ptr("bar"), URL: commoncfg.MustParseURL("http://solana.bar")}, + {Name: ptr("foo"), URL: commoncfg.MustParseURL("http://solana.foo"), SendOnly: true}, + {Name: ptr("bar"), URL: commoncfg.MustParseURL("http://solana.bar"), SendOnly: true}, }, }, } @@ -1024,7 +1026,7 @@ BlockBackfillDepth = 100 BlockBackfillSkip = true ChainType = 'Optimism' FinalityDepth = 42 -FinalityTagEnabled = false +FinalityTagEnabled = true FlagsContractAddress = '0xae4E781a6218A8031764928E88d457937A954fC3' LinkContractAddress = '0x538aAaB4ea120b2bC2fe5D296852D948F07D849e' LogBackfillBatchSize = 17 @@ -1101,6 +1103,7 @@ MaxBufferSize = 17 SamplingInterval = '1h0m0s' MaxAllowedFinalityDepth = 1500 FinalityTagBypass = false +PersistenceEnabled = false [[EVM.KeySpecific]] Key = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' @@ -1213,18 +1216,22 @@ ComputeUnitPriceMin = 10 ComputeUnitPriceDefault = 100 FeeBumpPeriod = '1m0s' BlockHistoryPollPeriod = '1m0s' +ComputeUnitLimitDefault = 100000 [[Solana.Nodes]] Name = 'primary' URL = 'http://solana.web' +SendOnly = false [[Solana.Nodes]] Name = 'foo' URL = 'http://solana.foo' +SendOnly = true [[Solana.Nodes]] Name = 'bar' URL = 'http://solana.bar' +SendOnly = true `}, {"Starknet", Config{Starknet: full.Starknet}, `[[Starknet]] ChainID = 'foobar' diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 36002f46c5f..2cd36c34ff8 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -309,7 +309,7 @@ BlockBackfillDepth = 100 BlockBackfillSkip = true ChainType = 'Optimism' FinalityDepth = 42 -FinalityTagEnabled = false +FinalityTagEnabled = true FlagsContractAddress = '0xae4E781a6218A8031764928E88d457937A954fC3' LinkContractAddress = '0x538aAaB4ea120b2bC2fe5D296852D948F07D849e' LogBackfillBatchSize = 17 @@ -386,6 +386,7 @@ MaxBufferSize = 17 SamplingInterval = '1h0m0s' MaxAllowedFinalityDepth = 1500 FinalityTagBypass = false +PersistenceEnabled = false [[EVM.KeySpecific]] Key = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' @@ -498,18 +499,22 @@ ComputeUnitPriceMin = 10 ComputeUnitPriceDefault = 100 FeeBumpPeriod = '1m0s' BlockHistoryPollPeriod = '1m0s' +ComputeUnitLimitDefault = 100000 [[Solana.Nodes]] Name = 'primary' URL = 'http://solana.web' +SendOnly = false [[Solana.Nodes]] Name = 'foo' URL = 'http://solana.foo' +SendOnly = true [[Solana.Nodes]] Name = 'bar' URL = 'http://solana.bar' +SendOnly = true [[Starknet]] ChainID = 'foobar' diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 5d16b9b87cb..b4cb107cdef 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -293,7 +293,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 26 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -359,6 +359,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 @@ -468,6 +469,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 @@ -506,7 +508,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 500 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0xb0897686c545045aFc77CF20eC7A532E3120E0F1' LogBackfillBatchSize = 1000 LogPollInterval = '1s' @@ -571,6 +573,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 @@ -657,10 +660,12 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 [[Solana.Nodes]] Name = 'primary' URL = 'http://mainnet.solana.com' +SendOnly = false [[Solana]] ChainID = 'testnet' @@ -680,10 +685,12 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 [[Solana.Nodes]] Name = 'secondary' URL = 'http://testnet.solana.com' +SendOnly = false [[Starknet]] ChainID = 'foobar' diff --git a/core/services/chainlink/testdata/config-multi-chain.toml b/core/services/chainlink/testdata/config-multi-chain.toml index 5373e0e62d3..45a6de47a98 100644 --- a/core/services/chainlink/testdata/config-multi-chain.toml +++ b/core/services/chainlink/testdata/config-multi-chain.toml @@ -38,7 +38,7 @@ CPUProfileRate = 7 [[EVM]] ChainID = '1' FinalityDepth = 26 -FinalityTagEnabled = false +FinalityTagEnabled = true FinalizedBlockOffset = 12 [[EVM.Nodes]] @@ -93,6 +93,7 @@ MaxRetries = 12 [[Solana.Nodes]] Name = 'primary' URL = 'http://mainnet.solana.com' +SendOnly = false [[Solana]] ChainID = 'testnet' @@ -101,6 +102,7 @@ OCR2CachePollPeriod = '1m0s' [[Solana.Nodes]] Name = 'secondary' URL = 'http://testnet.solana.com' +SendOnly = false [[Starknet]] ChainID = 'foobar' diff --git a/core/services/relay/evm/chain_reader.go b/core/services/relay/evm/chain_reader.go index 8a770d47446..e5041f5486a 100644 --- a/core/services/relay/evm/chain_reader.go +++ b/core/services/relay/evm/chain_reader.go @@ -365,8 +365,10 @@ func (cr *chainReader) initDWQuerying(contractName, eventName string, eventDWs m dWsDetail := make(map[string]read.DataWordDetail) for genericName, onChainName := range dWDefs { - for _, dWDetail := range eventDWs { - if dWDetail.Name == onChainName { + for eventID, dWDetail := range eventDWs { + // Extract field name in this manner to account for nested fields + fieldName := strings.Join(strings.Split(eventID, ".")[1:], ".") + if fieldName == onChainName { dWsDetail[genericName] = dWDetail dwTypeID := eventName + "." + genericName @@ -425,24 +427,11 @@ func getEventTypes(event abi.Event) ([]abi.Argument, types.CodecEntry, map[strin indexedAsUnIndexedTypes := make([]abi.Argument, 0, types.MaxTopicFields) indexedTypes := make([]abi.Argument, 0, len(event.Inputs)) dataWords := make(map[string]read.DataWordDetail) - hadDynamicType := false - var dwIndex uint8 + var dwIndex int for _, input := range event.Inputs { if !input.Indexed { - // there are some cases where we can calculate the exact data word index even if there was a dynamic type before, but it is complex and probably not needed. - if input.Type.T == abi.TupleTy || input.Type.T == abi.SliceTy || input.Type.T == abi.StringTy || input.Type.T == abi.BytesTy { - hadDynamicType = true - } - if hadDynamicType { - continue - } - - dataWords[event.Name+"."+input.Name] = read.DataWordDetail{ - Index: dwIndex, - Argument: input, - } - dwIndex++ + dwIndex = calculateFieldDWIndex(input, event.Name+"."+input.Name, dataWords, dwIndex) continue } @@ -456,6 +445,54 @@ func getEventTypes(event abi.Event) ([]abi.Argument, types.CodecEntry, map[strin return indexedAsUnIndexedTypes, types.NewCodecEntry(indexedTypes, nil, nil), dataWords } +// calculateFieldDWIndex recursively calculates the indices of all static unindexed fields in the event +// and calculates the offset for all unsearchable / dynamic fields. +func calculateFieldDWIndex(arg abi.Argument, fieldPath string, dataWords map[string]read.DataWordDetail, index int) int { + if isDynamic(arg.Type) { + return index + 1 + } + + return processFields(arg.Type, fieldPath, dataWords, index) +} + +func processFields(fieldType abi.Type, parentFieldPath string, dataWords map[string]read.DataWordDetail, index int) int { + switch fieldType.T { + case abi.TupleTy: + // Recursively process tuple elements + for i, tupleElem := range fieldType.TupleElems { + fieldName := fieldType.TupleRawNames[i] + fullFieldPath := fmt.Sprintf("%s.%s", parentFieldPath, fieldName) + index = processFields(*tupleElem, fullFieldPath, dataWords, index) + } + return index + case abi.ArrayTy: + // Static arrays are not searchable, however, we can reliably calculate their size so that the fields + // after them can be searched. + return index + fieldType.Size + default: + dataWords[parentFieldPath] = read.DataWordDetail{ + Index: index, + Argument: abi.Argument{Type: fieldType}, + } + return index + 1 + } +} + +func isDynamic(fieldType abi.Type) bool { + switch fieldType.T { + case abi.StringTy, abi.SliceTy, abi.BytesTy: + return true + case abi.TupleTy: + // If one element in a struct is dynamic, the whole struct is treated as dynamic. + for _, elem := range fieldType.TupleElems { + if isDynamic(*elem) { + return true + } + } + } + return false +} + // ConfirmationsFromConfig maps chain agnostic confidence levels defined in config to predefined EVM finality. func ConfirmationsFromConfig(values map[string]int) (map[primitives.ConfidenceLevel]evmtypes.Confirmations, error) { mappings := map[primitives.ConfidenceLevel]evmtypes.Confirmations{ diff --git a/core/services/relay/evm/codec/codec.go b/core/services/relay/evm/codec/codec.go index 3a859c89a8b..b0572b54791 100644 --- a/core/services/relay/evm/codec/codec.go +++ b/core/services/relay/evm/codec/codec.go @@ -93,6 +93,11 @@ func (c *evmCodec) CreateType(itemType string, forEncoding bool) (any, error) { return nil, fmt.Errorf("%w: cannot find type name %s", commontypes.ErrInvalidType, itemType) } + // we don't need double pointers, and they can also mess up reflection variable creation and mapstruct decode + if def.CheckedType().Kind() == reflect.Pointer { + return reflect.New(def.CheckedType()).Elem().Interface(), nil + } + return reflect.New(def.CheckedType()).Interface(), nil } diff --git a/core/services/relay/evm/codec/codec_test.go b/core/services/relay/evm/codec/codec_test.go index d43f1180108..7cb242c13de 100644 --- a/core/services/relay/evm/codec/codec_test.go +++ b/core/services/relay/evm/codec/codec_test.go @@ -205,7 +205,8 @@ func (it *codecInterfaceTester) GetCodec(t *testing.T) commontypes.Codec { if k != sizeItemType && k != NilType { entry.ModifierConfigs = commoncodec.ModifiersConfig{ - &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &commoncodec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, } } @@ -280,14 +281,24 @@ func packArgs(t *testing.T, allArgs []any, oargs abi.Arguments, request *EncodeR return bytes } -var inner = []abi.ArgumentMarshaling{ +var innerDynamic = []abi.ArgumentMarshaling{ {Name: "IntVal", Type: "int64"}, {Name: "S", Type: "string"}, } -var nested = []abi.ArgumentMarshaling{ +var nestedDynamic = []abi.ArgumentMarshaling{ {Name: "FixedBytes", Type: "bytes2"}, - {Name: "Inner", Type: "tuple", Components: inner}, + {Name: "Inner", Type: "tuple", Components: innerDynamic}, +} + +var innerStatic = []abi.ArgumentMarshaling{ + {Name: "IntVal", Type: "int64"}, + {Name: "A", Type: "address"}, +} + +var nestedStatic = []abi.ArgumentMarshaling{ + {Name: "FixedBytes", Type: "bytes2"}, + {Name: "Inner", Type: "tuple", Components: innerStatic}, } var ts = []abi.ArgumentMarshaling{ @@ -298,7 +309,8 @@ var ts = []abi.ArgumentMarshaling{ {Name: "Account", Type: "address"}, {Name: "Accounts", Type: "address[]"}, {Name: "BigField", Type: "int192"}, - {Name: "NestedStruct", Type: "tuple", Components: nested}, + {Name: "NestedDynamicStruct", Type: "tuple", Components: nestedDynamic}, + {Name: "NestedStaticStruct", Type: "tuple", Components: nestedStatic}, } const sizeItemType = "item for size" @@ -355,6 +367,7 @@ func argsFromTestStruct(ts TestStruct) []any { common.Address(ts.Account), getAccounts(ts), ts.BigField, - evmtesting.MidToInternalType(ts.NestedStruct), + evmtesting.MidDynamicToInternalType(ts.NestedDynamicStruct), + evmtesting.MidStaticToInternalType(ts.NestedStaticStruct), } } diff --git a/core/services/relay/evm/codec/encoder.go b/core/services/relay/evm/codec/encoder.go index b7facde328a..18ad32831c2 100644 --- a/core/services/relay/evm/codec/encoder.go +++ b/core/services/relay/evm/codec/encoder.go @@ -97,7 +97,7 @@ func RepresentArray(item reflect.Value, info types.CodecEntry) (any, error) { return nil, err } - return native.Elem().Interface(), nil + return native.Interface(), nil } func UnrollItem(item reflect.Value, info types.CodecEntry) ([]any, error) { @@ -122,7 +122,6 @@ func UnrollItem(item reflect.Value, info types.CodecEntry) ([]any, error) { } } - item = reflect.Indirect(item) length := item.NumField() values := make([]any, length) iType := item.Type() 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 df34d63fc42..ac8ece9b37f 100644 --- a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go +++ b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go @@ -110,7 +110,8 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { methodTakingLatestParamsReturningTestStructConfig := types.ChainReaderDefinition{ ChainSpecificName: "getElementAtIndex", OutputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, }, } @@ -136,11 +137,16 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { ChainSpecificName: "Triggered", ReadType: types.Event, EventDefinitions: &types.EventDefinitions{ - GenericTopicNames: map[string]string{"field": "Field"}, - GenericDataWordNames: map[string]string{"OracleID": "oracleId"}, + GenericTopicNames: map[string]string{"field": "Field"}, + GenericDataWordNames: map[string]string{ + "OracleID": "oracleId", + "NestedStaticStruct.Inner.IntVal": "nestedStaticStruct.Inner.IntVal", + "BigField": "bigField", + }, }, OutputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, }, }, EventWithFilterName: { @@ -183,11 +189,13 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { "Account": hexutil.Encode(testStruct.Account), }, }, - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, }, OutputModifications: codec.ModifiersConfig{ &codec.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": AnyExtraValue}}, - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, }, }, }, @@ -217,7 +225,8 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { GasLimit: 2_000_000, Checker: "simulate", InputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, }, }, "setAlterablePrimitiveValue": { @@ -232,7 +241,8 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { GasLimit: 2_000_000, Checker: "simulate", InputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, }, }, "triggerEventWithDynamicTopic": { @@ -264,7 +274,8 @@ func (it *EVMChainComponentsInterfaceTester[T]) Setup(t T) { GasLimit: 2_000_000, Checker: "simulate", InputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedDynamicStruct.Inner.IntVal": "I"}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStaticStruct.Inner.IntVal": "I"}}, }, }, }, @@ -425,23 +436,34 @@ func ConvertAccounts(accounts [][]byte) []common.Address { func ToInternalType(testStruct TestStruct) chain_reader_tester.TestStruct { return chain_reader_tester.TestStruct{ - Field: *testStruct.Field, - DifferentField: testStruct.DifferentField, - OracleId: byte(testStruct.OracleID), - OracleIds: OracleIDsToBytes(testStruct.OracleIDs), - Account: common.Address(testStruct.Account), - Accounts: ConvertAccounts(testStruct.Accounts), - BigField: testStruct.BigField, - NestedStruct: MidToInternalType(testStruct.NestedStruct), + Field: *testStruct.Field, + DifferentField: testStruct.DifferentField, + OracleId: byte(testStruct.OracleID), + OracleIds: OracleIDsToBytes(testStruct.OracleIDs), + Account: common.Address(testStruct.Account), + Accounts: ConvertAccounts(testStruct.Accounts), + BigField: testStruct.BigField, + NestedDynamicStruct: MidDynamicToInternalType(testStruct.NestedDynamicStruct), + NestedStaticStruct: MidStaticToInternalType(testStruct.NestedStaticStruct), } } -func MidToInternalType(m MidLevelTestStruct) chain_reader_tester.MidLevelTestStruct { - return chain_reader_tester.MidLevelTestStruct{ +func MidDynamicToInternalType(m MidLevelDynamicTestStruct) chain_reader_tester.MidLevelDynamicTestStruct { + return chain_reader_tester.MidLevelDynamicTestStruct{ FixedBytes: m.FixedBytes, - Inner: chain_reader_tester.InnerTestStruct{ + Inner: chain_reader_tester.InnerDynamicTestStruct{ IntVal: int64(m.Inner.I), S: m.Inner.S, }, } } + +func MidStaticToInternalType(m MidLevelStaticTestStruct) chain_reader_tester.MidLevelStaticTestStruct { + return chain_reader_tester.MidLevelStaticTestStruct{ + FixedBytes: m.FixedBytes, + Inner: chain_reader_tester.InnerStaticTestStruct{ + IntVal: int64(m.Inner.I), + A: common.BytesToAddress(m.Inner.A), + }, + } +} diff --git a/core/services/relay/evm/evmtesting/run_tests.go b/core/services/relay/evm/evmtesting/run_tests.go index c999693de50..7e01cf2b657 100644 --- a/core/services/relay/evm/evmtesting/run_tests.go +++ b/core/services/relay/evm/evmtesting/run_tests.go @@ -152,23 +152,57 @@ func RunContractReaderEvmTests[T TestingT[T]](t T, it *EVMChainComponentsInterfa func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfaceTester[T]) { RunContractReaderInterfaceTests[T](t, it, false) - t.Run("Filtering can be done on data words using value comparator", func(t T) { - it.Setup(t) + 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) - 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)) + 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, + }), + }, + }, query.LimitAndSort{}, ts) + return err == nil && len(sequences) == 1 && reflect.DeepEqual(&ts2, sequences[0].Data) + }, it.MaxWaitTimeForEvents(), time.Millisecond*10) + }) - 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 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, + }), + }, + }, 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{ @@ -177,6 +211,11 @@ func RunContractReaderInLoopTests[T TestingT[T]](t T, it ChainComponentsInterfac 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) diff --git a/core/services/relay/evm/read/event.go b/core/services/relay/evm/read/event.go index 03bee7472bc..a2cf95a2da2 100644 --- a/core/services/relay/evm/read/event.go +++ b/core/services/relay/evm/read/event.go @@ -81,7 +81,7 @@ type TopicDetail struct { // DataWordDetail contains all the information about a single evm Data word. // For b.g. first evm data word(32bytes) of USDC log event is uint256 var called valub. type DataWordDetail struct { - Index uint8 + Index int abi.Argument } @@ -338,7 +338,7 @@ func (b *EventBinding) decodeLogsIntoSequences(ctx context.Context, logs []logpo for idx := range logs { sequences[idx] = commontypes.Sequence{ - Cursor: fmt.Sprintf("%s-%s-%d", logs[idx].BlockHash, logs[idx].TxHash, logs[idx].LogIndex), + Cursor: logpoller.FormatContractReaderCursor(logs[idx]), Head: commontypes.Head{ Height: fmt.Sprint(logs[idx].BlockNumber), Hash: logs[idx].BlockHash.Bytes(), @@ -548,6 +548,12 @@ func (b *EventBinding) encodeComparator(comparator *primitives.Comparator) (quer } func (b *EventBinding) encodeValComparatorDataWord(dwTypeID string, value any) (hash common.Hash, err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("%w: cannot encode %s data word comparator. Recovered from panic: %v", commontypes.ErrInvalidType, dwTypeID, r) + } + }() + dwTypes, exists := b.eventTypes[dwTypeID] if !exists { return common.Hash{}, fmt.Errorf("cannot find data word type for %s", dwTypeID) @@ -601,10 +607,6 @@ func (b *EventBinding) toNativeOnChainType(itemType string, value any) (any, err return query.Expression{}, err } - for native.Kind() == reflect.Pointer { - native = reflect.Indirect(native) - } - return native.Interface(), nil } diff --git a/core/services/relay/evm/types/codec_entry.go b/core/services/relay/evm/types/codec_entry.go index 4e18f4d9f9f..6a39f9d226f 100644 --- a/core/services/relay/evm/types/codec_entry.go +++ b/core/services/relay/evm/types/codec_entry.go @@ -64,11 +64,18 @@ func (entry *codecEntry) ToNative(checked reflect.Value) (val reflect.Value, err err = fmt.Errorf("invalid checked value: %v", r) } }() - if checked.Type() != reflect.PointerTo(entry.checkedType) { + + // some checked types are expected to be pointers already for e.g. big numbers, so this is fine + checkedTypeIsPtr := entry.checkedType == checked.Type() + if checked.Type() != reflect.PointerTo(entry.checkedType) && !checkedTypeIsPtr { return reflect.Value{}, fmt.Errorf("%w: checked type %v does not match expected type %v", commontypes.ErrInvalidType, checked.Type(), entry.checkedType) } - return reflect.NewAt(entry.nativeType, checked.UnsafePointer()), nil + if checkedTypeIsPtr { + return reflect.NewAt(entry.nativeType.Elem(), checked.UnsafePointer()), nil + } + + return reflect.Indirect(reflect.NewAt(entry.nativeType, checked.UnsafePointer())), nil } func (entry *codecEntry) IsNativePointer(item reflect.Type) bool { diff --git a/core/services/relay/evm/types/codec_entry_test.go b/core/services/relay/evm/types/codec_entry_test.go index 64e0998716a..c71d5c0ad33 100644 --- a/core/services/relay/evm/types/codec_entry_test.go +++ b/core/services/relay/evm/types/codec_entry_test.go @@ -47,14 +47,13 @@ func TestCodecEntry(t *testing.T) { f4 := big.NewInt( /*2^23 - 1*/ 8388607) setAndVerifyLimit(t, (*int24)(f4), f4, iChecked.FieldByName("Field4")) - rNative, err := entry.ToNative(checked) - require.NoError(t, err) - iNative := reflect.Indirect(rNative) - assert.Equal(t, iNative.Field(0).Interface(), iChecked.Field(0).Interface()) - assert.Equal(t, iNative.Field(1).Interface(), iChecked.Field(1).Interface()) - assert.Equal(t, iNative.Field(2).Interface(), f3) - assert.Equal(t, iNative.Field(3).Interface(), f4) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + native, err := entry.ToNative(checked) + require.NoError(t, err) + assert.Equal(t, native.Field(0).Interface(), iChecked.Field(0).Interface()) + assert.Equal(t, native.Field(1).Interface(), iChecked.Field(1).Interface()) + assert.Equal(t, native.Field(2).Interface(), f3) + assert.Equal(t, native.Field(3).Interface(), f4) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("tuples", func(t *testing.T) { @@ -86,12 +85,11 @@ func TestCodecEntry(t *testing.T) { native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - require.Equal(t, iNative.Field(0).Interface(), iChecked.Field(0).Interface()) - nF2 := reflect.Indirect(iNative.Field(1)) + require.Equal(t, native.Field(0).Interface(), iChecked.Field(0).Interface()) + nF2 := reflect.Indirect(native.Field(1)) assert.Equal(t, nF2.Field(0).Interface(), f3) assert.Equal(t, nF2.Field(1).Interface(), f4) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("nested tuple member names are capitalized", func(t *testing.T) { @@ -123,12 +121,11 @@ func TestCodecEntry(t *testing.T) { native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - require.Equal(t, iNative.Field(0).Interface(), iChecked.Field(0).Interface()) - nF2 := reflect.Indirect(iNative.Field(1)) + require.Equal(t, native.Field(0).Interface(), iChecked.Field(0).Interface()) + nF2 := reflect.Indirect(native.Field(1)) assert.Equal(t, nF2.Field(0).Interface(), f3) assert.Equal(t, nF2.Field(1).Interface(), f4) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("unwrapped types", func(t *testing.T) { @@ -145,9 +142,8 @@ func TestCodecEntry(t *testing.T) { iChecked.FieldByName("Field1").Set(reflect.ValueOf(&anyValue)) native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - assert.Equal(t, &anyValue, iNative.FieldByName("Field1").Interface()) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assert.Equal(t, &anyValue, native.FieldByName("Field1").Interface()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("slice types", func(t *testing.T) { @@ -162,9 +158,8 @@ func TestCodecEntry(t *testing.T) { iChecked.FieldByName("Field1").Set(reflect.ValueOf(anySliceValue)) native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - assert.Equal(t, anySliceValue, iNative.FieldByName("Field1").Interface()) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assert.Equal(t, anySliceValue, native.FieldByName("Field1").Interface()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("array types", func(t *testing.T) { @@ -178,8 +173,7 @@ func TestCodecEntry(t *testing.T) { iChecked.FieldByName("Field1").Set(reflect.ValueOf(anySliceValue)) native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - assert.Equal(t, anySliceValue, iNative.FieldByName("Field1").Interface()) + assert.Equal(t, anySliceValue, native.FieldByName("Field1").Interface()) }) t.Run("Not return values makes struct{}", func(t *testing.T) { @@ -188,7 +182,7 @@ func TestCodecEntry(t *testing.T) { assert.Equal(t, reflect.TypeOf(struct{}{}), entry.CheckedType()) native, err := entry.ToNative(reflect.ValueOf(&struct{}{})) require.NoError(t, err) - assert.Equal(t, &struct{}{}, native.Interface()) + assert.Equal(t, struct{}{}, native.Interface()) }) t.Run("Address works", func(t *testing.T) { @@ -204,9 +198,8 @@ func TestCodecEntry(t *testing.T) { native, err := entry.ToNative(checked) require.NoError(t, err) - iNative := reflect.Indirect(native) - assert.Equal(t, anyAddr, iNative.FieldByName("Foo").Interface()) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assert.Equal(t, anyAddr, native.FieldByName("Foo").Interface()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("Unnamed parameters are named after their locations", func(t *testing.T) { @@ -269,8 +262,7 @@ func TestCodecEntry(t *testing.T) { assert.Equal(t, reflect.TypeOf((*int16)(nil)), checkedField.Type) native, err := entry.ToNative(reflect.New(entry.CheckedType())) require.NoError(t, err) - iNative := reflect.Indirect(native) - assertHaveSameStructureAndNames(t, iNative.Type(), entry.CheckedType()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) }) t.Run("Indexed string and bytes array change to hash", func(t *testing.T) { @@ -292,7 +284,7 @@ func TestCodecEntry(t *testing.T) { assert.Equal(t, reflect.TypeOf(&common.Hash{}), nativeField.Type) native, err := entry.ToNative(reflect.New(entry.CheckedType())) require.NoError(t, err) - assertHaveSameStructureAndNames(t, native.Type().Elem(), entry.CheckedType()) + assertHaveSameStructureAndNames(t, native.Type(), entry.CheckedType()) } }) diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 971036991f2..b26e1068ac8 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -309,7 +309,7 @@ BlockBackfillDepth = 100 BlockBackfillSkip = true ChainType = 'Optimism' FinalityDepth = 42 -FinalityTagEnabled = false +FinalityTagEnabled = true FlagsContractAddress = '0xae4E781a6218A8031764928E88d457937A954fC3' LinkContractAddress = '0x538aAaB4ea120b2bC2fe5D296852D948F07D849e' LogBackfillBatchSize = 17 @@ -385,6 +385,7 @@ MaxBufferSize = 17 SamplingInterval = '1h0m0s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [[EVM.KeySpecific]] Key = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' @@ -497,18 +498,22 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 [[Solana.Nodes]] Name = 'primary' URL = 'http://solana.web' +SendOnly = false [[Solana.Nodes]] Name = 'foo' URL = 'http://solana.foo' +SendOnly = false [[Solana.Nodes]] Name = 'bar' URL = 'http://solana.bar' +SendOnly = false [[Starknet]] ChainID = 'foobar' diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 480fc1b4c09..303843cf8bf 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -293,7 +293,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 26 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -359,6 +359,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 @@ -468,6 +469,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 @@ -506,7 +508,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 500 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0xb0897686c545045aFc77CF20eC7A532E3120E0F1' LogBackfillBatchSize = 1000 LogPollInterval = '1s' @@ -571,6 +573,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 @@ -657,10 +660,12 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 [[Solana.Nodes]] Name = 'primary' URL = 'http://mainnet.solana.com' +SendOnly = false [[Solana]] ChainID = 'testnet' @@ -680,10 +685,12 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 [[Solana.Nodes]] Name = 'secondary' URL = 'http://testnet.solana.com' +SendOnly = false [[Starknet]] ChainID = 'foobar' diff --git a/core/web/resolver/testdata/config-multi-chain.toml b/core/web/resolver/testdata/config-multi-chain.toml index 9abb1719402..7d72ef55de7 100644 --- a/core/web/resolver/testdata/config-multi-chain.toml +++ b/core/web/resolver/testdata/config-multi-chain.toml @@ -38,7 +38,7 @@ CPUProfileRate = 7 [[EVM]] ChainID = '1' FinalityDepth = 26 -FinalityTagEnabled = false +FinalityTagEnabled = true FinalizedBlockOffset = 0 [EVM.OCR2] @@ -101,6 +101,7 @@ MaxRetries = 12 [[Solana.Nodes]] Name = 'primary' URL = 'http://mainnet.solana.com' +SendOnly = false [[Solana]] ChainID = 'testnet' @@ -109,6 +110,7 @@ OCR2CachePollPeriod = '1m0s' [[Solana.Nodes]] Name = 'secondary' URL = 'http://testnet.solana.com' +SendOnly = false [[Starknet]] ChainID = 'foobar' diff --git a/core/web/solana_chains_controller_test.go b/core/web/solana_chains_controller_test.go index 048a3790b1a..3f64431b049 100644 --- a/core/web/solana_chains_controller_test.go +++ b/core/web/solana_chains_controller_test.go @@ -58,6 +58,7 @@ ComputeUnitPriceMin = 0 ComputeUnitPriceDefault = 0 FeeBumpPeriod = '3s' BlockHistoryPollPeriod = '5s' +ComputeUnitLimitDefault = 200000 Nodes = [] `, } diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 628692f7c33..79fe03d5e37 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1965,7 +1965,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -2031,6 +2031,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2134,6 +2135,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2237,6 +2239,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2340,6 +2343,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2379,7 +2383,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'optimismBedrock' FinalityDepth = 200 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6' LogBackfillBatchSize = 1000 LogPollInterval = '2s' @@ -2444,6 +2448,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2547,6 +2552,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2650,6 +2656,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2754,6 +2761,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2792,7 +2800,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x404460C6A5EdE2D891e8297795264fDe62ADBB75' LogBackfillBatchSize = 1000 LogPollInterval = '3s' @@ -2857,6 +2865,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -2959,6 +2968,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3061,6 +3071,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3099,7 +3110,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06' LogBackfillBatchSize = 1000 LogPollInterval = '3s' @@ -3164,6 +3175,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = false +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3268,6 +3280,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3371,6 +3384,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3409,7 +3423,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 500 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0xb0897686c545045aFc77CF20eC7A532E3120E0F1' LogBackfillBatchSize = 1000 LogPollInterval = '1s' @@ -3474,6 +3488,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3577,6 +3592,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3680,6 +3696,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3783,6 +3800,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3822,7 +3840,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'kroma' FinalityDepth = 400 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 @@ -3886,6 +3904,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -3989,6 +4008,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4092,6 +4112,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4195,6 +4216,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4298,6 +4320,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4401,6 +4424,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4505,6 +4529,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4608,6 +4633,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4710,6 +4736,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4749,7 +4776,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'metis' FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '15s' LogKeepBlocksDepth = 100000 @@ -4813,6 +4840,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4916,6 +4944,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -4955,7 +4984,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'wemix' FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '3s' LogKeepBlocksDepth = 100000 @@ -5019,6 +5048,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5058,7 +5088,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'wemix' FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '3s' LogKeepBlocksDepth = 100000 @@ -5122,6 +5152,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = false +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5224,6 +5255,7 @@ MaxBufferSize = 100 SamplingInterval = '0s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5328,6 +5360,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5367,7 +5400,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'kroma' FinalityDepth = 400 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 @@ -5431,6 +5464,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5534,6 +5568,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5637,6 +5672,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5739,6 +5775,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5778,7 +5815,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'optimismBedrock' FinalityDepth = 200 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 @@ -5842,6 +5879,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -5945,6 +5983,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6049,6 +6088,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6153,6 +6193,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6192,7 +6233,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'arbitrum' FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0xf97f4df75117a78c1A5a0DBb814Af92458539FB4' LogBackfillBatchSize = 1000 LogPollInterval = '1s' @@ -6257,6 +6298,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6360,6 +6402,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6398,7 +6441,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846' LogBackfillBatchSize = 1000 LogPollInterval = '3s' @@ -6463,6 +6506,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = false +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6501,7 +6545,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x5947BB275c521040051D82396192181b413227A3' LogBackfillBatchSize = 1000 LogPollInterval = '3s' @@ -6566,6 +6610,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6669,6 +6714,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6775,6 +6821,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6881,6 +6928,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -6983,6 +7031,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7085,6 +7134,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7187,6 +7237,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7226,7 +7277,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'metis' FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '15s' LogKeepBlocksDepth = 100000 @@ -7290,6 +7341,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7393,6 +7445,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7495,6 +7548,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7598,6 +7652,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7637,7 +7692,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'optimismBedrock' FinalityDepth = 200 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 @@ -7701,6 +7756,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7805,6 +7861,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7909,6 +7966,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -7948,7 +8006,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'arbitrum' FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '1s' LogKeepBlocksDepth = 100000 @@ -8012,6 +8070,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -8115,6 +8174,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -8218,6 +8278,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -8256,7 +8317,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x779877A7B0D9E8603169DdbD7836e478b4624789' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -8321,6 +8382,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = false +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -8360,7 +8422,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false ChainType = 'optimismBedrock' FinalityDepth = 200 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 @@ -8424,6 +8486,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -8527,6 +8590,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -8630,6 +8694,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [NodePool] PollFailureThreshold = 5 @@ -9320,6 +9385,7 @@ MaxBufferSize = 3 # Default SamplingInterval = '1s' # Default FinalityTagBypass = true # Default MaxAllowedFinalityDepth = 10000 # Default +PersistenceEnabled = true # Default ``` The head tracker continually listens for new heads from the chain. @@ -9366,6 +9432,15 @@ MaxAllowedFinalityDepth - defines maximum number of blocks between the most rece If actual finality depth exceeds this number, HeadTracker aborts backfill and returns an error. Has no effect if `FinalityTagsEnabled` = false +### PersistenceEnabled +```toml +PersistenceEnabled = true # Default +``` +PersistenceEnabled defines whether HeadTracker needs to store heads in the database. +Persistence is helpful on chains with large finality depth, where fetching blocks from the latest to the latest finalized takes a lot of time. +On chains with fast finality, the persistence layer does not improve the chain's load time and only consumes database resources (mainly IO). +NOTE: persistence should not be disabled for products that use LogBroadcaster, as it might lead to missed on-chain events. + ## EVM.KeySpecific ```toml [[EVM.KeySpecific]] @@ -9882,6 +9957,7 @@ ComputeUnitPriceMin = 0 # Default ComputeUnitPriceDefault = 0 # Default FeeBumpPeriod = '3s' # Default BlockHistoryPollPeriod = '5s' # Default +ComputeUnitLimitDefault = 200_000 # Default ``` @@ -9994,11 +10070,18 @@ BlockHistoryPollPeriod = '5s' # Default ``` BlockHistoryPollPeriod is the rate to poll for blocks in the block history fee estimator +### ComputeUnitLimitDefault +```toml +ComputeUnitLimitDefault = 200_000 # Default +``` +ComputeUnitLimitDefault is the compute units limit applied to transactions unless overriden during the txm enqueue + ## Solana.Nodes ```toml [[Solana.Nodes]] Name = 'primary' # Example URL = 'http://solana.web' # Example +SendOnly = false # Default ``` @@ -10014,6 +10097,12 @@ URL = 'http://solana.web' # Example ``` URL is the HTTP(S) endpoint for this node. +### SendOnly +```toml +SendOnly = false # Default +``` +SendOnly is a multinode config that only sends transactions to a node and does not read state + ## Starknet ```toml [[Starknet]] diff --git a/go.mod b/go.mod index 552e9750e54..73c38b8c2db 100644 --- a/go.mod +++ b/go.mod @@ -74,12 +74,12 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.23 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342 - github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd + github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664 + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 diff --git a/go.sum b/go.sum index 6b218dabf81..ea1df80842d 100644 --- a/go.sum +++ b/go.sum @@ -1042,18 +1042,18 @@ github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnj github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342 h1:uEgdiVPKiPkwSXpsRgK9gxC2TMpjvE5GXpSPl/C20r0= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342/go.mod h1:VyldDDFSelaLyEXO1M7xVoGTTtlT9apfxh90vIMeOwc= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc h1:ALbyaoRzUSXQ2NhGFKVOyJqO22IB5yQjhjKWbIZGbrI= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc/go.mod h1:F6WUS6N4mP5ScwpwyTyAJc9/vjR+GXbMCRUOVekQi1g= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd h1:16Hwnz4hdmWKOy5qVH9wHfyT1XXM0k31M3naexwzpVo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd/go.mod h1:/nGkIe25kgtr+l6y30VH+aTVaxu0NjIEEEhtV1TDlaE= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670 h1:z+XnayyX7pyvVv9OuMQ7oik7RkguQeWHhxcOoVM4oKI= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670/go.mod h1:F6WUS6N4mP5ScwpwyTyAJc9/vjR+GXbMCRUOVekQi1g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7 h1:lTGIOQYLk1Ufn++X/AvZnt6VOcuhste5yp+C157No/Q= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7/go.mod h1:BMYE1vC/pGmdFSsOJdPrAA0/4gZ0Xo0SxTMdGspBtRo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2 h1:yRk4ektpx/UxwarqAfgxUXLrsYXlaNeP1NOwzHGrK2Q= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2/go.mod h1:rNhNSrrRMvkgAm5SA6bNTdh2340bTQQZdUVNtZ2o2bk= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f h1:p4p3jBT91EQyLuAMvHD+zNJsuAYI/QjJbzuGUJ7wIgg= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f/go.mod h1:FLlWBt2hwiMVgt9AcSo6wBJYIRd/nsc8ENbV1Wir1bw= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664 h1:JPs35oSO07PK3Qv7Kyv0GJHVLacIE1IkrvefaPyBjKs= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664/go.mod h1:iJ9DKYo0F64ue7IogAIELwU2DfrhEAh76eSmZOilT8A= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff h1:piMugtrRlbVdcC6xZF37me686eS1YwpLQ0kN2v2b9YE= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff/go.mod h1:5jD47oCERRQ4eGi0iNdk9ZV5HMEdolfQwHpUX1+Ix4s= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae h1:d+B8y2Nd/PrnPMNoaSPn3eDgUgxcVcIqAxGrvYu/gGw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae/go.mod h1:ec/a20UZ7YRK4oxJcnTBFzp1+DBcJcwqEaerUMsktMs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= diff --git a/integration-tests/deployment/ccip/add_chain.go b/integration-tests/deployment/ccip/add_chain.go index 0ae87d38344..48cf7542d7f 100644 --- a/integration-tests/deployment/ccip/add_chain.go +++ b/integration-tests/deployment/ccip/add_chain.go @@ -4,8 +4,8 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/tools/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/tools/proposal/timelock" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" chainsel "github.com/smartcontractkit/chain-selectors" diff --git a/integration-tests/deployment/ccip/changeset/1_cap_reg.go b/integration-tests/deployment/ccip/changeset/1_cap_reg.go index 90c1a94fe8d..1ca288321cd 100644 --- a/integration-tests/deployment/ccip/changeset/1_cap_reg.go +++ b/integration-tests/deployment/ccip/changeset/1_cap_reg.go @@ -1,7 +1,7 @@ package changeset import ( - "github.com/smartcontractkit/ccip-owner-contracts/tools/proposal/timelock" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/integration-tests/deployment" ccipdeployment "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" diff --git a/integration-tests/deployment/ccip/changeset/2_initial_deploy.go b/integration-tests/deployment/ccip/changeset/2_initial_deploy.go index 93c408bf45a..99d16d21c40 100644 --- a/integration-tests/deployment/ccip/changeset/2_initial_deploy.go +++ b/integration-tests/deployment/ccip/changeset/2_initial_deploy.go @@ -1,7 +1,7 @@ package changeset import ( - "github.com/smartcontractkit/ccip-owner-contracts/tools/proposal/timelock" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/integration-tests/deployment" diff --git a/integration-tests/deployment/ccip/deploy.go b/integration-tests/deployment/ccip/deploy.go index 358a72bad11..0f42bd235b9 100644 --- a/integration-tests/deployment/ccip/deploy.go +++ b/integration-tests/deployment/ccip/deploy.go @@ -10,9 +10,9 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" - "github.com/smartcontractkit/ccip-owner-contracts/tools/configwrappers" - owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/tools/gethwrappers" + owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -41,6 +41,7 @@ var ( ARMProxy deployment.ContractType = "ARMProxy" WETH9 deployment.ContractType = "WETH9" Router deployment.ContractType = "Router" + CommitStore deployment.ContractType = "CommitStore" TokenAdminRegistry deployment.ContractType = "TokenAdminRegistry" NonceManager deployment.ContractType = "NonceManager" FeeQuoter deployment.ContractType = "FeeQuoter" @@ -276,7 +277,7 @@ func DeployChainContracts( publicKey := TestXXXMCMSSigner.Public().(*ecdsa.PublicKey) // Convert the public key to an Ethereum address address := crypto.PubkeyToAddress(*publicKey) - c, err := configwrappers.NewConfig(1, []common.Address{address}, []configwrappers.Config{}) + c, err := config.NewConfig(1, []common.Address{address}, []config.Config{}) if err != nil { e.Logger.Errorw("Failed to create config", "err", err) return ab, err diff --git a/integration-tests/deployment/ccip/propose.go b/integration-tests/deployment/ccip/propose.go index fca971aaf0d..df4fe90a76a 100644 --- a/integration-tests/deployment/ccip/propose.go +++ b/integration-tests/deployment/ccip/propose.go @@ -10,9 +10,9 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/tools/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/tools/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/tools/proposal/timelock" + owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" chainsel "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/require" diff --git a/integration-tests/deployment/ccip/state.go b/integration-tests/deployment/ccip/state.go index 334c945707b..6b894d93b0e 100644 --- a/integration-tests/deployment/ccip/state.go +++ b/integration-tests/deployment/ccip/state.go @@ -9,6 +9,8 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view" "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_2" @@ -21,7 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" - owner_wrappers "github.com/smartcontractkit/ccip-owner-contracts/tools/gethwrappers" + owner_wrappers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" @@ -40,10 +42,11 @@ type CCIPChainState struct { OnRamp *onramp.OnRamp OffRamp *offramp.OffRamp FeeQuoter *fee_quoter.FeeQuoter - ArmProxy *rmn_proxy_contract.RMNProxyContract + RMNProxy *rmn_proxy_contract.RMNProxyContract NonceManager *nonce_manager.NonceManager TokenAdminRegistry *token_admin_registry.TokenAdminRegistry Router *router.Router + CommitStore *commit_store.CommitStore Weth9 *weth9.WETH9 RMNRemote *rmn_remote.RMNRemote // TODO: May need to support older link too @@ -128,6 +131,22 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { } chainView.OffRamp[c.OffRamp.Address().Hex()] = offRampView } + + if c.CommitStore != nil { + commitStoreView, err := v1_5.GenerateCommitStoreView(c.CommitStore) + if err != nil { + return chainView, err + } + chainView.CommitStore[c.CommitStore.Address().Hex()] = commitStoreView + } + + if c.RMNProxy != nil { + rmnProxyView, err := v1_0.GenerateRMNProxyView(c.RMNProxy) + if err != nil { + return chainView, err + } + chainView.RMNProxy[c.RMNProxy.Address().Hex()] = rmnProxyView + } return chainView, nil } @@ -238,7 +257,7 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type if err != nil { return state, err } - state.ArmProxy = armProxy + state.RMNProxy = armProxy case deployment.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0_dev).String(): rmnRemote, err := rmn_remote.NewRMNRemote(common.HexToAddress(address), chain.Client) if err != nil { @@ -257,6 +276,12 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type return state, err } state.NonceManager = nm + case deployment.NewTypeAndVersion(CommitStore, deployment.Version1_5_0).String(): + cs, err := commit_store.NewCommitStore(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.CommitStore = cs case deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0).String(): tm, err := token_admin_registry.NewTokenAdminRegistry(common.HexToAddress(address), chain.Client) if err != nil { diff --git a/integration-tests/deployment/ccip/view/chain.go b/integration-tests/deployment/ccip/view/chain.go index 8dbd6cabbba..06f0059e67b 100644 --- a/integration-tests/deployment/ccip/view/chain.go +++ b/integration-tests/deployment/ccip/view/chain.go @@ -1,29 +1,42 @@ package view import ( + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_0" "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_2" "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_5" "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/v1_6" ) type ChainView struct { + // v1.0 + RMNProxy map[string]v1_0.RMNProxyView `json:"rmnProxy,omitempty"` + // v1.2 + Router map[string]v1_2.RouterView `json:"router,omitempty"` + // v1.5 TokenAdminRegistry map[string]v1_5.TokenAdminRegistryView `json:"tokenAdminRegistry,omitempty"` - FeeQuoter map[string]v1_6.FeeQuoterView `json:"feeQuoter,omitempty"` - NonceManager map[string]v1_6.NonceManagerView `json:"nonceManager,omitempty"` - Router map[string]v1_2.RouterView `json:"router,omitempty"` - RMN map[string]v1_6.RMNRemoteView `json:"rmn,omitempty"` - OnRamp map[string]v1_6.OnRampView `json:"onRamp,omitempty"` - OffRamp map[string]v1_6.OffRampView `json:"offRamp,omitempty"` + CommitStore map[string]v1_5.CommitStoreView `json:"commitStore,omitempty"` + // v1.6 + FeeQuoter map[string]v1_6.FeeQuoterView `json:"feeQuoter,omitempty"` + NonceManager map[string]v1_6.NonceManagerView `json:"nonceManager,omitempty"` + RMN map[string]v1_6.RMNRemoteView `json:"rmn,omitempty"` + OnRamp map[string]v1_6.OnRampView `json:"onRamp,omitempty"` + OffRamp map[string]v1_6.OffRampView `json:"offRamp,omitempty"` } func NewChain() ChainView { return ChainView{ + // v1.0 + RMNProxy: make(map[string]v1_0.RMNProxyView), + // v1.2 + Router: make(map[string]v1_2.RouterView), + // v1.5 TokenAdminRegistry: make(map[string]v1_5.TokenAdminRegistryView), - NonceManager: make(map[string]v1_6.NonceManagerView), - Router: make(map[string]v1_2.RouterView), - RMN: make(map[string]v1_6.RMNRemoteView), - OnRamp: make(map[string]v1_6.OnRampView), - OffRamp: make(map[string]v1_6.OffRampView), - FeeQuoter: make(map[string]v1_6.FeeQuoterView), + CommitStore: make(map[string]v1_5.CommitStoreView), + // v1.6 + FeeQuoter: make(map[string]v1_6.FeeQuoterView), + NonceManager: make(map[string]v1_6.NonceManagerView), + RMN: make(map[string]v1_6.RMNRemoteView), + OnRamp: make(map[string]v1_6.OnRampView), + OffRamp: make(map[string]v1_6.OffRampView), } } diff --git a/integration-tests/deployment/ccip/view/v1_0/rmn_proxy_contract.go b/integration-tests/deployment/ccip/view/v1_0/rmn_proxy_contract.go new file mode 100644 index 00000000000..bac32bf0f26 --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_0/rmn_proxy_contract.go @@ -0,0 +1,33 @@ +package v1_0 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" +) + +type RMNProxyView struct { + types.ContractMetaData + RMN common.Address `json:"rmn"` +} + +func GenerateRMNProxyView(r *rmn_proxy_contract.RMNProxyContract) (RMNProxyView, error) { + if r == nil { + return RMNProxyView{}, fmt.Errorf("cannot generate view for nil RMNProxy") + } + meta, err := types.NewContractMetaData(r, r.Address()) + if err != nil { + return RMNProxyView{}, fmt.Errorf("failed to generate contract metadata for RMNProxy: %w", err) + } + rmn, err := r.GetARM(nil) + if err != nil { + return RMNProxyView{}, fmt.Errorf("failed to get ARM: %w", err) + } + return RMNProxyView{ + ContractMetaData: meta, + RMN: rmn, + }, nil +} diff --git a/integration-tests/deployment/ccip/view/v1_5/commit_store.go b/integration-tests/deployment/ccip/view/v1_5/commit_store.go new file mode 100644 index 00000000000..0aa483e1678 --- /dev/null +++ b/integration-tests/deployment/ccip/view/v1_5/commit_store.go @@ -0,0 +1,81 @@ +package v1_5 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" +) + +type CommitStoreView struct { + types.ContractMetaData + DynamicConfig commit_store.CommitStoreDynamicConfig `json:"dynamicConfig"` + ExpectedNextSequenceNumber uint64 `json:"expectedNextSequenceNumber"` + LatestPriceEpochAndRound uint64 `json:"latestPriceEpochAndRound"` + StaticConfig commit_store.CommitStoreStaticConfig `json:"staticConfig"` + Transmitters []common.Address `json:"transmitters"` + IsUnpausedAndNotCursed bool `json:"isUnpausedAndNotCursed"` + LatestConfigDetails commit_store.LatestConfigDetails `json:"latestConfigDetails"` + LatestConfigDigestAndEpoch commit_store.LatestConfigDigestAndEpoch `json:"latestConfigDigestAndEpoch"` + Paused bool `json:"paused"` +} + +func GenerateCommitStoreView(c *commit_store.CommitStore) (CommitStoreView, error) { + if c == nil { + return CommitStoreView{}, fmt.Errorf("cannot generate view for nil CommitStore") + } + meta, err := types.NewContractMetaData(c, c.Address()) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to generate contract metadata for CommitStore: %w", err) + } + dynamicConfig, err := c.GetDynamicConfig(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get dynamic config: %w", err) + } + expectedNextSequenceNumber, err := c.GetExpectedNextSequenceNumber(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get expected next sequence number: %w", err) + } + latestPriceEpochAndRound, err := c.GetLatestPriceEpochAndRound(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get latest price epoch and round: %w", err) + } + staticConfig, err := c.GetStaticConfig(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get static config: %w", err) + } + transmitters, err := c.GetTransmitters(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get transmitters: %w", err) + } + isUnpausedAndNotCursed, err := c.IsUnpausedAndNotCursed(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get is unpaused and not cursed: %w", err) + } + latestConfigDetails, err := c.LatestConfigDetails(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get latest config details: %w", err) + } + latestConfigDigestAndEpoch, err := c.LatestConfigDigestAndEpoch(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get latest config digest and epoch: %w", err) + } + paused, err := c.Paused(nil) + if err != nil { + return CommitStoreView{}, fmt.Errorf("failed to get paused: %w", err) + } + return CommitStoreView{ + ContractMetaData: meta, + DynamicConfig: dynamicConfig, + ExpectedNextSequenceNumber: expectedNextSequenceNumber, + LatestPriceEpochAndRound: latestPriceEpochAndRound, + StaticConfig: staticConfig, + Transmitters: transmitters, + IsUnpausedAndNotCursed: isUnpausedAndNotCursed, + LatestConfigDetails: latestConfigDetails, + LatestConfigDigestAndEpoch: latestConfigDigestAndEpoch, + Paused: paused, + }, nil +} diff --git a/integration-tests/deployment/changeset.go b/integration-tests/deployment/changeset.go index aeac3e8e722..6473bc1320a 100644 --- a/integration-tests/deployment/changeset.go +++ b/integration-tests/deployment/changeset.go @@ -1,7 +1,7 @@ package deployment import ( - "github.com/smartcontractkit/ccip-owner-contracts/tools/proposal/timelock" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" ) // Services as input to CI/Async tasks diff --git a/integration-tests/go.mod b/integration-tests/go.mod index ba22ea75aee..b6dab3a01f9 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -36,11 +36,11 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/shopspring/decimal v1.4.0 github.com/slack-go/slack v0.12.2 - github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240919155713-f4bf4ae0b9c6 + github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 github.com/smartcontractkit/chain-selectors v1.0.23 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342 - github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd + github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 @@ -408,7 +408,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index bb9f3809a9a..7ab1481ca95 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1417,24 +1417,24 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240919155713-f4bf4ae0b9c6 h1:e4lR/xTK7iOeCniSwH6hdaNZZ/sJs1eYWpnJoz3CXxI= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240919155713-f4bf4ae0b9c6/go.mod h1:nlRI0m23HFMAHf7cKYdE58mPbXsTyY1y3ZLJxnuuoCM= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnjjIQAEBnutCtksPzVDY= github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342 h1:uEgdiVPKiPkwSXpsRgK9gxC2TMpjvE5GXpSPl/C20r0= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342/go.mod h1:VyldDDFSelaLyEXO1M7xVoGTTtlT9apfxh90vIMeOwc= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc h1:ALbyaoRzUSXQ2NhGFKVOyJqO22IB5yQjhjKWbIZGbrI= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc/go.mod h1:F6WUS6N4mP5ScwpwyTyAJc9/vjR+GXbMCRUOVekQi1g= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd h1:16Hwnz4hdmWKOy5qVH9wHfyT1XXM0k31M3naexwzpVo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd/go.mod h1:/nGkIe25kgtr+l6y30VH+aTVaxu0NjIEEEhtV1TDlaE= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670 h1:z+XnayyX7pyvVv9OuMQ7oik7RkguQeWHhxcOoVM4oKI= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670/go.mod h1:F6WUS6N4mP5ScwpwyTyAJc9/vjR+GXbMCRUOVekQi1g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7 h1:lTGIOQYLk1Ufn++X/AvZnt6VOcuhste5yp+C157No/Q= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7/go.mod h1:BMYE1vC/pGmdFSsOJdPrAA0/4gZ0Xo0SxTMdGspBtRo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2 h1:yRk4ektpx/UxwarqAfgxUXLrsYXlaNeP1NOwzHGrK2Q= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2/go.mod h1:rNhNSrrRMvkgAm5SA6bNTdh2340bTQQZdUVNtZ2o2bk= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f h1:p4p3jBT91EQyLuAMvHD+zNJsuAYI/QjJbzuGUJ7wIgg= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f/go.mod h1:FLlWBt2hwiMVgt9AcSo6wBJYIRd/nsc8ENbV1Wir1bw= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664 h1:JPs35oSO07PK3Qv7Kyv0GJHVLacIE1IkrvefaPyBjKs= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664/go.mod h1:iJ9DKYo0F64ue7IogAIELwU2DfrhEAh76eSmZOilT8A= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff h1:piMugtrRlbVdcC6xZF37me686eS1YwpLQ0kN2v2b9YE= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff/go.mod h1:5jD47oCERRQ4eGi0iNdk9ZV5HMEdolfQwHpUX1+Ix4s= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae h1:d+B8y2Nd/PrnPMNoaSPn3eDgUgxcVcIqAxGrvYu/gGw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae/go.mod h1:ec/a20UZ7YRK4oxJcnTBFzp1+DBcJcwqEaerUMsktMs= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 h1:mgjBQIEy+3V3G6K8e+6by3xndgsXdYYsdy+7kzQZwSk= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 11c0ac7a9da..975b1a13d35 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -15,7 +15,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.12.2 - github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc + github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.9 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.1 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0 @@ -30,7 +30,7 @@ require ( require ( github.com/AlekSi/pointer v1.1.0 // indirect github.com/smartcontractkit/chainlink-automation v1.0.4 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd // indirect github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 // indirect ) @@ -390,7 +390,7 @@ require ( github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae // indirect github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 0278df28ee4..3d40c225116 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1397,18 +1397,18 @@ github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnj github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342 h1:uEgdiVPKiPkwSXpsRgK9gxC2TMpjvE5GXpSPl/C20r0= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240925142036-56f243802342/go.mod h1:VyldDDFSelaLyEXO1M7xVoGTTtlT9apfxh90vIMeOwc= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc h1:ALbyaoRzUSXQ2NhGFKVOyJqO22IB5yQjhjKWbIZGbrI= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240925085218-aded1b263ecc/go.mod h1:F6WUS6N4mP5ScwpwyTyAJc9/vjR+GXbMCRUOVekQi1g= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd h1:16Hwnz4hdmWKOy5qVH9wHfyT1XXM0k31M3naexwzpVo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240930150148-1c731b9602dd/go.mod h1:/nGkIe25kgtr+l6y30VH+aTVaxu0NjIEEEhtV1TDlaE= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670 h1:z+XnayyX7pyvVv9OuMQ7oik7RkguQeWHhxcOoVM4oKI= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240930142117-ef04dd443670/go.mod h1:F6WUS6N4mP5ScwpwyTyAJc9/vjR+GXbMCRUOVekQi1g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7 h1:lTGIOQYLk1Ufn++X/AvZnt6VOcuhste5yp+C157No/Q= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240911175228-daf2600bb7b7/go.mod h1:BMYE1vC/pGmdFSsOJdPrAA0/4gZ0Xo0SxTMdGspBtRo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2 h1:yRk4ektpx/UxwarqAfgxUXLrsYXlaNeP1NOwzHGrK2Q= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240916152957-433914114bd2/go.mod h1:rNhNSrrRMvkgAm5SA6bNTdh2340bTQQZdUVNtZ2o2bk= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f h1:p4p3jBT91EQyLuAMvHD+zNJsuAYI/QjJbzuGUJ7wIgg= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240910155501-42f20443189f/go.mod h1:FLlWBt2hwiMVgt9AcSo6wBJYIRd/nsc8ENbV1Wir1bw= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664 h1:JPs35oSO07PK3Qv7Kyv0GJHVLacIE1IkrvefaPyBjKs= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240911182932-3c609a6ac664/go.mod h1:iJ9DKYo0F64ue7IogAIELwU2DfrhEAh76eSmZOilT8A= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff h1:piMugtrRlbVdcC6xZF37me686eS1YwpLQ0kN2v2b9YE= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20240927143737-7e527aa85bff/go.mod h1:5jD47oCERRQ4eGi0iNdk9ZV5HMEdolfQwHpUX1+Ix4s= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae h1:d+B8y2Nd/PrnPMNoaSPn3eDgUgxcVcIqAxGrvYu/gGw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240911194142-506bc469d8ae/go.mod h1:ec/a20UZ7YRK4oxJcnTBFzp1+DBcJcwqEaerUMsktMs= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 h1:mgjBQIEy+3V3G6K8e+6by3xndgsXdYYsdy+7kzQZwSk= diff --git a/plugins/cmd/chainlink-ocr3-capability/main.go b/plugins/cmd/chainlink-ocr3-capability/main.go index c70a5a6f2ad..fad82c7b73b 100644 --- a/plugins/cmd/chainlink-ocr3-capability/main.go +++ b/plugins/cmd/chainlink-ocr3-capability/main.go @@ -11,7 +11,6 @@ import ( ocr3rp "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins/ocr3" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) const ( @@ -24,7 +23,7 @@ func main() { c := ocr3.Config{ Logger: s.Logger, - EncoderFactory: evm.NewEVMEncoder, + EncoderFactory: capabilities.NewEncoder, AggregatorFactory: capabilities.NewAggregator, } p := ocr3.NewOCR3(c) diff --git a/testdata/scripts/node/validate/defaults-override.txtar b/testdata/scripts/node/validate/defaults-override.txtar index 85228771ce1..5c36fddeaf1 100644 --- a/testdata/scripts/node/validate/defaults-override.txtar +++ b/testdata/scripts/node/validate/defaults-override.txtar @@ -19,11 +19,11 @@ stderr 'contains duplicate ChainID' -- default_overrides/evm/Ethereum_Mainnet.toml -- ChainID = '1' -FinalityTagEnabled = true +FinalityTagEnabled = false -- default_overrides2/Ethereum_Mainnet.toml -- ChainID = '1' -FinalityTagEnabled = true +FinalityTagEnabled = false -- default_overrides3/evm/Ethereum_Mainnet.toml -- ChainID = '1' @@ -366,7 +366,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = true +FinalityTagEnabled = false LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -432,6 +432,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index 75ab3bb55c7..9a9f5e88811 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -349,7 +349,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -415,6 +415,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index de2bdf3209e..8b4089832eb 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -349,7 +349,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -415,6 +415,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index ec0c4423928..ef496ddfd8b 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -349,7 +349,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -415,6 +415,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index dbef892b275..81c5a494440 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -339,7 +339,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -405,6 +405,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5 diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index 83cb6f451af..063436f1079 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -346,7 +346,7 @@ AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 50 -FinalityTagEnabled = false +FinalityTagEnabled = true LinkContractAddress = '0x514910771AF9Ca656af840dff83E8264EcF986CA' LogBackfillBatchSize = 1000 LogPollInterval = '15s' @@ -412,6 +412,7 @@ MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true +PersistenceEnabled = true [EVM.NodePool] PollFailureThreshold = 5