From e0a5bc246af3577750910ddc2338535b6f19c2d3 Mon Sep 17 00:00:00 2001 From: dimitris Date: Tue, 30 Jul 2024 15:10:27 +0300 Subject: [PATCH] Add CCIPReader e2e tests using simulated backend (#1209) Add CCIPReader e2e tests using the simulated backend. First merge: https://github.com/smartcontractkit/chainlink-ccip/pull/48 and update commitHash of chainlink-common dependency in this branch. --- .../scripts/native_solc_compile_all_ccip | 5 + .../ccip/test/helpers/CCIPReaderTester.sol | 55 ++ .../ccip_reader_tester/ccip_reader_tester.go | 761 ++++++++++++++++++ ...rapper-dependency-versions-do-not-edit.txt | 1 + core/gethwrappers/ccip/go_generate.go | 1 + core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +- .../ccipreader/ccipreader_test.go | 401 +++++++++ go.mod | 2 +- go.sum | 4 +- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 +- 14 files changed, 1236 insertions(+), 12 deletions(-) create mode 100644 contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol create mode 100644 core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go create mode 100644 core/services/ocr3/plugins/ccip_integration_tests/ccipreader/ccipreader_test.go diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 1dbb70502d..a856dea2f7 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -40,6 +40,10 @@ compileContract () { echo "OnRamp uses $OPTIMIZE_RUNS_ONRAMP optimizer runs." optimize_runs=$OPTIMIZE_RUNS_ONRAMP ;; + "ccip/test/helpers/CCIPReaderTester.sol") + echo "CCIPReaderTester uses 1 optimizer runs for reduced contract size." + optimize_runs=1 + ;; esac solc --overwrite --optimize --optimize-runs $optimize_runs --metadata-hash none \ @@ -83,6 +87,7 @@ compileContract ccip/NonceManager.sol compileContract ccip/test/helpers/BurnMintERC677Helper.sol compileContract ccip/test/helpers/CommitStoreHelper.sol compileContract ccip/test/helpers/MessageHasher.sol +compileContract ccip/test/helpers/CCIPReaderTester.sol compileContract ccip/test/helpers/ReportCodec.sol compileContract ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol compileContract ccip/test/helpers/MultiOCR3Helper.sol diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol new file mode 100644 index 0000000000..86abc09e2a --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Internal} from "../../libraries/Internal.sol"; +import {EVM2EVMMultiOffRamp} from "../../offRamp/EVM2EVMMultiOffRamp.sol"; + +contract CCIPReaderTester { + event CCIPSendRequested(uint64 indexed destChainSelector, Internal.EVM2AnyRampMessage message); + + mapping(uint64 sourceChainSelector => EVM2EVMMultiOffRamp.SourceChainConfig sourceChainConfig) internal + s_sourceChainConfigs; + + function getSourceChainConfig(uint64 sourceChainSelector) + external + view + returns (EVM2EVMMultiOffRamp.SourceChainConfig memory) + { + return s_sourceChainConfigs[sourceChainSelector]; + } + + function setSourceChainConfig( + uint64 sourceChainSelector, + EVM2EVMMultiOffRamp.SourceChainConfig memory sourceChainConfig + ) external { + s_sourceChainConfigs[sourceChainSelector] = sourceChainConfig; + } + + function emitCCIPSendRequested(uint64 destChainSelector, Internal.EVM2AnyRampMessage memory message) external { + emit CCIPSendRequested(destChainSelector, message); + } + + event ExecutionStateChanged( + uint64 indexed sourceChainSelector, + uint64 indexed sequenceNumber, + bytes32 indexed messageId, + Internal.MessageExecutionState state, + bytes returnData + ); + + function emitExecutionStateChanged( + uint64 sourceChainSelector, + uint64 sequenceNumber, + bytes32 messageId, + Internal.MessageExecutionState state, + bytes memory returnData + ) external { + emit ExecutionStateChanged(sourceChainSelector, sequenceNumber, messageId, state, returnData); + } + + event CommitReportAccepted(EVM2EVMMultiOffRamp.CommitReport report); + + function emitCommitReportAccepted(EVM2EVMMultiOffRamp.CommitReport memory report) external { + emit CommitReportAccepted(report); + } +} diff --git a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go new file mode 100644 index 0000000000..fdef138528 --- /dev/null +++ b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go @@ -0,0 +1,761 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ccip_reader_tester + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type EVM2EVMMultiOffRampCommitReport struct { + PriceUpdates InternalPriceUpdates + MerkleRoots []EVM2EVMMultiOffRampMerkleRoot +} + +type EVM2EVMMultiOffRampInterval struct { + Min uint64 + Max uint64 +} + +type EVM2EVMMultiOffRampMerkleRoot struct { + SourceChainSelector uint64 + Interval EVM2EVMMultiOffRampInterval + MerkleRoot [32]byte +} + +type EVM2EVMMultiOffRampSourceChainConfig struct { + IsEnabled bool + MinSeqNr uint64 + OnRamp []byte +} + +type InternalEVM2AnyRampMessage struct { + Header InternalRampMessageHeader + Sender common.Address + Data []byte + Receiver []byte + ExtraArgs []byte + FeeToken common.Address + FeeTokenAmount *big.Int + TokenAmounts []InternalRampTokenAmount +} + +type InternalGasPriceUpdate struct { + DestChainSelector uint64 + UsdPerUnitGas *big.Int +} + +type InternalPriceUpdates struct { + TokenPriceUpdates []InternalTokenPriceUpdate + GasPriceUpdates []InternalGasPriceUpdate +} + +type InternalRampMessageHeader struct { + MessageId [32]byte + SourceChainSelector uint64 + DestChainSelector uint64 + SequenceNumber uint64 + Nonce uint64 +} + +type InternalRampTokenAmount struct { + SourcePoolAddress []byte + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int +} + +type InternalTokenPriceUpdate struct { + SourceToken common.Address + UsdPerToken *big.Int +} + +var CCIPReaderTesterMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506110cc806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80634cf66e361461005c578063a65558f614610071578063e44302b714610084578063e9d68a8e14610097578063f831af81146100c0575b600080fd5b61006f61006a366004610462565b6100d3565b005b61006f61007f3660046106c7565b610128565b61006f610092366004610965565b61016d565b6100aa6100a5366004610acd565b6101a7565b6040516100b79190610b35565b60405180910390f35b61006f6100ce366004610b76565b610297565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051610119929190610c1e565b60405180910390a45050505050565b816001600160401b03167f0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29826040516101619190610d06565b60405180910390a25050565b7f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d8160405161019c9190610ec0565b60405180910390a150565b6040805160608082018352600080835260208084018290528385018390526001600160401b0386811683528282529185902085519384018652805460ff81161515855261010090049092169083015260018101805493949293919284019161020e90610f75565b80601f016020809104026020016040519081016040528092919081815260200182805461023a90610f75565b80156102875780601f1061025c57610100808354040283529160200191610287565b820191906000526020600020905b81548152906001019060200180831161026a57829003601f168201915b5050505050815250509050919050565b6001600160401b038281166000908152602081815260409182902084518154928601516001600160481b0319909316901515610100600160481b03191617610100929094169190910292909217825582015182919060018201906102fb9082611000565b5050505050565b80356001600160401b038116811461031957600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156103565761035661031e565b60405290565b60405161010081016001600160401b03811182821017156103565761035661031e565b604080519081016001600160401b03811182821017156103565761035661031e565b604051606081016001600160401b03811182821017156103565761035661031e565b604051601f8201601f191681016001600160401b03811182821017156103eb576103eb61031e565b604052919050565b600082601f83011261040457600080fd5b81356001600160401b0381111561041d5761041d61031e565b610430601f8201601f19166020016103c3565b81815284602083860101111561044557600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561047a57600080fd5b61048386610302565b945061049160208701610302565b9350604086013592506060860135600481106104ac57600080fd5b915060808601356001600160401b038111156104c757600080fd5b6104d3888289016103f3565b9150509295509295909350565b600060a082840312156104f257600080fd5b60405160a081016001600160401b03811182821017156105145761051461031e565b6040528235815290508061052a60208401610302565b602082015261053b60408401610302565b604082015261054c60608401610302565b606082015261055d60808401610302565b60808201525092915050565b80356001600160a01b038116811461031957600080fd5b60006001600160401b038211156105995761059961031e565b5060051b60200190565b600082601f8301126105b457600080fd5b813560206105c96105c483610580565b6103c3565b82815260059290921b840181019181810190868411156105e857600080fd5b8286015b848110156106bc5780356001600160401b038082111561060c5760008081fd5b908801906080828b03601f19018113156106265760008081fd5b61062e610334565b87840135838111156106405760008081fd5b61064e8d8a838801016103f3565b825250604080850135848111156106655760008081fd5b6106738e8b838901016103f3565b8a840152506060808601358581111561068c5760008081fd5b61069a8f8c838a01016103f3565b92840192909252949092013593810193909352505083529183019183016105ec565b509695505050505050565b600080604083850312156106da57600080fd5b6106e383610302565b915060208301356001600160401b03808211156106ff57600080fd5b90840190610180828703121561071457600080fd5b61071c61035c565b61072687846104e0565b815261073460a08401610569565b602082015260c08301358281111561074b57600080fd5b610757888286016103f3565b60408301525060e08301358281111561076f57600080fd5b61077b888286016103f3565b6060830152506101008301358281111561079457600080fd5b6107a0888286016103f3565b6080830152506107b36101208401610569565b60a082015261014083013560c0820152610160830135828111156107d657600080fd5b6107e2888286016105a3565b60e0830152508093505050509250929050565b80356001600160e01b038116811461031957600080fd5b600082601f83011261081d57600080fd5b8135602061082d6105c483610580565b82815260069290921b8401810191818101908684111561084c57600080fd5b8286015b848110156106bc57604081890312156108695760008081fd5b61087161037f565b61087a82610302565b81526108878583016107f5565b81860152835291830191604001610850565b600082601f8301126108aa57600080fd5b813560206108ba6105c483610580565b82815260079290921b840181019181810190868411156108d957600080fd5b8286015b848110156106bc5780880360808112156108f75760008081fd5b6108ff6103a1565b61090883610302565b8152604080601f198401121561091e5760008081fd5b61092661037f565b9250610933878501610302565b8352610940818501610302565b83880152818701929092526060830135918101919091528352918301916080016108dd565b6000602080838503121561097857600080fd5b82356001600160401b038082111561098f57600080fd5b818501915060408083880312156109a557600080fd5b6109ad61037f565b8335838111156109bc57600080fd5b84016040818a0312156109ce57600080fd5b6109d661037f565b8135858111156109e557600080fd5b8201601f81018b136109f657600080fd5b8035610a046105c482610580565b81815260069190911b8201890190898101908d831115610a2357600080fd5b928a01925b82841015610a715787848f031215610a405760008081fd5b610a4861037f565b610a5185610569565b8152610a5e8c86016107f5565b818d0152825292870192908a0190610a28565b845250505081870135935084841115610a8957600080fd5b610a958a85840161080c565b8188015282525083850135915082821115610aaf57600080fd5b610abb88838601610899565b85820152809550505050505092915050565b600060208284031215610adf57600080fd5b610ae882610302565b9392505050565b6000815180845260005b81811015610b1557602081850181015186830182015201610af9565b506000602082860101526020601f19601f83011685010191505092915050565b6020815281511515602082015260018060401b03602083015116604082015260006040830151606080840152610b6e6080840182610aef565b949350505050565b60008060408385031215610b8957600080fd5b610b9283610302565b915060208301356001600160401b0380821115610bae57600080fd5b9084019060608287031215610bc257600080fd5b610bca6103a1565b82358015158114610bda57600080fd5b8152610be860208401610302565b6020820152604083013582811115610bff57600080fd5b610c0b888286016103f3565b6040830152508093505050509250929050565b600060048410610c3e57634e487b7160e01b600052602160045260246000fd5b83825260406020830152610b6e6040830184610aef565b6001600160a01b03169052565b600082825180855260208086019550808260051b84010181860160005b84811015610cf957601f19868403018952815160808151818652610ca582870182610aef565b9150508582015185820387870152610cbd8282610aef565b91505060408083015186830382880152610cd78382610aef565b6060948501519790940196909652505098840198925090830190600101610c7f565b5090979650505050505050565b60208152610d53602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b60006020830151610d6760c0840182610c55565b5060408301516101808060e0850152610d846101a0850183610aef565b91506060850151601f198086850301610100870152610da38483610aef565b9350608087015191508086850301610120870152610dc18483610aef565b935060a08701519150610dd8610140870183610c55565b60c087015161016087015260e0870151915080868503018387015250610dfe8382610c62565b9695505050505050565b60008151808452602080850194506020840160005b83811015610e5657815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610e1d565b509495945050505050565b600081518084526020808501945080840160005b83811015610e5657815180516001600160401b0390811689528482015180518216868b0152850151166040898101919091520151606088015260809096019590820190600101610e75565b6000602080835283516040808386015260a0850182516040606088015281815180845260c0890191508683019350600092505b80831015610f2e57835180516001600160a01b031683528701516001600160e01b031687830152928601926001929092019190840190610ef3565b5093850151878503605f1901608089015293610f4a8186610e08565b945050505050818501519150601f19848203016040850152610f6c8183610e61565b95945050505050565b600181811c90821680610f8957607f821691505b602082108103610fa957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610ffb576000816000526020600020601f850160051c81016020861015610fd85750805b601f850160051c820191505b81811015610ff757828155600101610fe4565b5050505b505050565b81516001600160401b038111156110195761101961031e565b61102d816110278454610f75565b84610faf565b602080601f831160018114611062576000841561104a5750858301515b600019600386901b1c1916600185901b178555610ff7565b600085815260208120601f198616915b8281101561109157888601518255948401946001909101908401611072565b50858210156110af5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", +} + +var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI + +var CCIPReaderTesterBin = CCIPReaderTesterMetaData.Bin + +func DeployCCIPReaderTester(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *CCIPReaderTester, error) { + parsed, err := CCIPReaderTesterMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(CCIPReaderTesterBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &CCIPReaderTester{address: address, abi: *parsed, CCIPReaderTesterCaller: CCIPReaderTesterCaller{contract: contract}, CCIPReaderTesterTransactor: CCIPReaderTesterTransactor{contract: contract}, CCIPReaderTesterFilterer: CCIPReaderTesterFilterer{contract: contract}}, nil +} + +type CCIPReaderTester struct { + address common.Address + abi abi.ABI + CCIPReaderTesterCaller + CCIPReaderTesterTransactor + CCIPReaderTesterFilterer +} + +type CCIPReaderTesterCaller struct { + contract *bind.BoundContract +} + +type CCIPReaderTesterTransactor struct { + contract *bind.BoundContract +} + +type CCIPReaderTesterFilterer struct { + contract *bind.BoundContract +} + +type CCIPReaderTesterSession struct { + Contract *CCIPReaderTester + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type CCIPReaderTesterCallerSession struct { + Contract *CCIPReaderTesterCaller + CallOpts bind.CallOpts +} + +type CCIPReaderTesterTransactorSession struct { + Contract *CCIPReaderTesterTransactor + TransactOpts bind.TransactOpts +} + +type CCIPReaderTesterRaw struct { + Contract *CCIPReaderTester +} + +type CCIPReaderTesterCallerRaw struct { + Contract *CCIPReaderTesterCaller +} + +type CCIPReaderTesterTransactorRaw struct { + Contract *CCIPReaderTesterTransactor +} + +func NewCCIPReaderTester(address common.Address, backend bind.ContractBackend) (*CCIPReaderTester, error) { + abi, err := abi.JSON(strings.NewReader(CCIPReaderTesterABI)) + if err != nil { + return nil, err + } + contract, err := bindCCIPReaderTester(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CCIPReaderTester{address: address, abi: abi, CCIPReaderTesterCaller: CCIPReaderTesterCaller{contract: contract}, CCIPReaderTesterTransactor: CCIPReaderTesterTransactor{contract: contract}, CCIPReaderTesterFilterer: CCIPReaderTesterFilterer{contract: contract}}, nil +} + +func NewCCIPReaderTesterCaller(address common.Address, caller bind.ContractCaller) (*CCIPReaderTesterCaller, error) { + contract, err := bindCCIPReaderTester(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CCIPReaderTesterCaller{contract: contract}, nil +} + +func NewCCIPReaderTesterTransactor(address common.Address, transactor bind.ContractTransactor) (*CCIPReaderTesterTransactor, error) { + contract, err := bindCCIPReaderTester(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CCIPReaderTesterTransactor{contract: contract}, nil +} + +func NewCCIPReaderTesterFilterer(address common.Address, filterer bind.ContractFilterer) (*CCIPReaderTesterFilterer, error) { + contract, err := bindCCIPReaderTester(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CCIPReaderTesterFilterer{contract: contract}, nil +} + +func bindCCIPReaderTester(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CCIPReaderTesterMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_CCIPReaderTester *CCIPReaderTesterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CCIPReaderTester.Contract.CCIPReaderTesterCaller.contract.Call(opts, result, method, params...) +} + +func (_CCIPReaderTester *CCIPReaderTesterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.CCIPReaderTesterTransactor.contract.Transfer(opts) +} + +func (_CCIPReaderTester *CCIPReaderTesterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.CCIPReaderTesterTransactor.contract.Transact(opts, method, params...) +} + +func (_CCIPReaderTester *CCIPReaderTesterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CCIPReaderTester.Contract.contract.Call(opts, result, method, params...) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.contract.Transfer(opts) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.contract.Transact(opts, method, params...) +} + +func (_CCIPReaderTester *CCIPReaderTesterCaller) GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) { + var out []interface{} + err := _CCIPReaderTester.contract.Call(opts, &out, "getSourceChainConfig", sourceChainSelector) + + if err != nil { + return *new(EVM2EVMMultiOffRampSourceChainConfig), err + } + + out0 := *abi.ConvertType(out[0], new(EVM2EVMMultiOffRampSourceChainConfig)).(*EVM2EVMMultiOffRampSourceChainConfig) + + return out0, err + +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) GetSourceChainConfig(sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) { + return _CCIPReaderTester.Contract.GetSourceChainConfig(&_CCIPReaderTester.CallOpts, sourceChainSelector) +} + +func (_CCIPReaderTester *CCIPReaderTesterCallerSession) GetSourceChainConfig(sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) { + return _CCIPReaderTester.Contract.GetSourceChainConfig(&_CCIPReaderTester.CallOpts, sourceChainSelector) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactor) EmitCCIPSendRequested(opts *bind.TransactOpts, destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) { + return _CCIPReaderTester.contract.Transact(opts, "emitCCIPSendRequested", destChainSelector, message) +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) EmitCCIPSendRequested(destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.EmitCCIPSendRequested(&_CCIPReaderTester.TransactOpts, destChainSelector, message) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) EmitCCIPSendRequested(destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.EmitCCIPSendRequested(&_CCIPReaderTester.TransactOpts, destChainSelector, message) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactor) EmitCommitReportAccepted(opts *bind.TransactOpts, report EVM2EVMMultiOffRampCommitReport) (*types.Transaction, error) { + return _CCIPReaderTester.contract.Transact(opts, "emitCommitReportAccepted", report) +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) EmitCommitReportAccepted(report EVM2EVMMultiOffRampCommitReport) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.EmitCommitReportAccepted(&_CCIPReaderTester.TransactOpts, report) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) EmitCommitReportAccepted(report EVM2EVMMultiOffRampCommitReport) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.EmitCommitReportAccepted(&_CCIPReaderTester.TransactOpts, report) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactor) EmitExecutionStateChanged(opts *bind.TransactOpts, sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, state uint8, returnData []byte) (*types.Transaction, error) { + return _CCIPReaderTester.contract.Transact(opts, "emitExecutionStateChanged", sourceChainSelector, sequenceNumber, messageId, state, returnData) +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) EmitExecutionStateChanged(sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, state uint8, returnData []byte) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.EmitExecutionStateChanged(&_CCIPReaderTester.TransactOpts, sourceChainSelector, sequenceNumber, messageId, state, returnData) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) EmitExecutionStateChanged(sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, state uint8, returnData []byte) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.EmitExecutionStateChanged(&_CCIPReaderTester.TransactOpts, sourceChainSelector, sequenceNumber, messageId, state, returnData) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactor) SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig EVM2EVMMultiOffRampSourceChainConfig) (*types.Transaction, error) { + return _CCIPReaderTester.contract.Transact(opts, "setSourceChainConfig", sourceChainSelector, sourceChainConfig) +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) SetSourceChainConfig(sourceChainSelector uint64, sourceChainConfig EVM2EVMMultiOffRampSourceChainConfig) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.SetSourceChainConfig(&_CCIPReaderTester.TransactOpts, sourceChainSelector, sourceChainConfig) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) SetSourceChainConfig(sourceChainSelector uint64, sourceChainConfig EVM2EVMMultiOffRampSourceChainConfig) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.SetSourceChainConfig(&_CCIPReaderTester.TransactOpts, sourceChainSelector, sourceChainConfig) +} + +type CCIPReaderTesterCCIPSendRequestedIterator struct { + Event *CCIPReaderTesterCCIPSendRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPReaderTesterCCIPSendRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPReaderTesterCCIPSendRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPReaderTesterCCIPSendRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPReaderTesterCCIPSendRequestedIterator) Error() error { + return it.fail +} + +func (it *CCIPReaderTesterCCIPSendRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPReaderTesterCCIPSendRequested struct { + DestChainSelector uint64 + Message InternalEVM2AnyRampMessage + Raw types.Log +} + +func (_CCIPReaderTester *CCIPReaderTesterFilterer) FilterCCIPSendRequested(opts *bind.FilterOpts, destChainSelector []uint64) (*CCIPReaderTesterCCIPSendRequestedIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _CCIPReaderTester.contract.FilterLogs(opts, "CCIPSendRequested", destChainSelectorRule) + if err != nil { + return nil, err + } + return &CCIPReaderTesterCCIPSendRequestedIterator{contract: _CCIPReaderTester.contract, event: "CCIPSendRequested", logs: logs, sub: sub}, nil +} + +func (_CCIPReaderTester *CCIPReaderTesterFilterer) WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *CCIPReaderTesterCCIPSendRequested, destChainSelector []uint64) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _CCIPReaderTester.contract.WatchLogs(opts, "CCIPSendRequested", destChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPReaderTesterCCIPSendRequested) + if err := _CCIPReaderTester.contract.UnpackLog(event, "CCIPSendRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPReaderTester *CCIPReaderTesterFilterer) ParseCCIPSendRequested(log types.Log) (*CCIPReaderTesterCCIPSendRequested, error) { + event := new(CCIPReaderTesterCCIPSendRequested) + if err := _CCIPReaderTester.contract.UnpackLog(event, "CCIPSendRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPReaderTesterCommitReportAcceptedIterator struct { + Event *CCIPReaderTesterCommitReportAccepted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPReaderTesterCommitReportAcceptedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPReaderTesterCommitReportAccepted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPReaderTesterCommitReportAccepted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPReaderTesterCommitReportAcceptedIterator) Error() error { + return it.fail +} + +func (it *CCIPReaderTesterCommitReportAcceptedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPReaderTesterCommitReportAccepted struct { + Report EVM2EVMMultiOffRampCommitReport + Raw types.Log +} + +func (_CCIPReaderTester *CCIPReaderTesterFilterer) FilterCommitReportAccepted(opts *bind.FilterOpts) (*CCIPReaderTesterCommitReportAcceptedIterator, error) { + + logs, sub, err := _CCIPReaderTester.contract.FilterLogs(opts, "CommitReportAccepted") + if err != nil { + return nil, err + } + return &CCIPReaderTesterCommitReportAcceptedIterator{contract: _CCIPReaderTester.contract, event: "CommitReportAccepted", logs: logs, sub: sub}, nil +} + +func (_CCIPReaderTester *CCIPReaderTesterFilterer) WatchCommitReportAccepted(opts *bind.WatchOpts, sink chan<- *CCIPReaderTesterCommitReportAccepted) (event.Subscription, error) { + + logs, sub, err := _CCIPReaderTester.contract.WatchLogs(opts, "CommitReportAccepted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPReaderTesterCommitReportAccepted) + if err := _CCIPReaderTester.contract.UnpackLog(event, "CommitReportAccepted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPReaderTester *CCIPReaderTesterFilterer) ParseCommitReportAccepted(log types.Log) (*CCIPReaderTesterCommitReportAccepted, error) { + event := new(CCIPReaderTesterCommitReportAccepted) + if err := _CCIPReaderTester.contract.UnpackLog(event, "CommitReportAccepted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPReaderTesterExecutionStateChangedIterator struct { + Event *CCIPReaderTesterExecutionStateChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPReaderTesterExecutionStateChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPReaderTesterExecutionStateChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPReaderTesterExecutionStateChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPReaderTesterExecutionStateChangedIterator) Error() error { + return it.fail +} + +func (it *CCIPReaderTesterExecutionStateChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPReaderTesterExecutionStateChanged struct { + SourceChainSelector uint64 + SequenceNumber uint64 + MessageId [32]byte + State uint8 + ReturnData []byte + Raw types.Log +} + +func (_CCIPReaderTester *CCIPReaderTesterFilterer) FilterExecutionStateChanged(opts *bind.FilterOpts, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (*CCIPReaderTesterExecutionStateChangedIterator, error) { + + var sourceChainSelectorRule []interface{} + for _, sourceChainSelectorItem := range sourceChainSelector { + sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) + } + var sequenceNumberRule []interface{} + for _, sequenceNumberItem := range sequenceNumber { + sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) + } + var messageIdRule []interface{} + for _, messageIdItem := range messageId { + messageIdRule = append(messageIdRule, messageIdItem) + } + + logs, sub, err := _CCIPReaderTester.contract.FilterLogs(opts, "ExecutionStateChanged", sourceChainSelectorRule, sequenceNumberRule, messageIdRule) + if err != nil { + return nil, err + } + return &CCIPReaderTesterExecutionStateChangedIterator{contract: _CCIPReaderTester.contract, event: "ExecutionStateChanged", logs: logs, sub: sub}, nil +} + +func (_CCIPReaderTester *CCIPReaderTesterFilterer) WatchExecutionStateChanged(opts *bind.WatchOpts, sink chan<- *CCIPReaderTesterExecutionStateChanged, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (event.Subscription, error) { + + var sourceChainSelectorRule []interface{} + for _, sourceChainSelectorItem := range sourceChainSelector { + sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) + } + var sequenceNumberRule []interface{} + for _, sequenceNumberItem := range sequenceNumber { + sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) + } + var messageIdRule []interface{} + for _, messageIdItem := range messageId { + messageIdRule = append(messageIdRule, messageIdItem) + } + + logs, sub, err := _CCIPReaderTester.contract.WatchLogs(opts, "ExecutionStateChanged", sourceChainSelectorRule, sequenceNumberRule, messageIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPReaderTesterExecutionStateChanged) + if err := _CCIPReaderTester.contract.UnpackLog(event, "ExecutionStateChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPReaderTester *CCIPReaderTesterFilterer) ParseExecutionStateChanged(log types.Log) (*CCIPReaderTesterExecutionStateChanged, error) { + event := new(CCIPReaderTesterExecutionStateChanged) + if err := _CCIPReaderTester.contract.UnpackLog(event, "ExecutionStateChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_CCIPReaderTester *CCIPReaderTester) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _CCIPReaderTester.abi.Events["CCIPSendRequested"].ID: + return _CCIPReaderTester.ParseCCIPSendRequested(log) + case _CCIPReaderTester.abi.Events["CommitReportAccepted"].ID: + return _CCIPReaderTester.ParseCommitReportAccepted(log) + case _CCIPReaderTester.abi.Events["ExecutionStateChanged"].ID: + return _CCIPReaderTester.ParseExecutionStateChanged(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (CCIPReaderTesterCCIPSendRequested) Topic() common.Hash { + return common.HexToHash("0x0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29") +} + +func (CCIPReaderTesterCommitReportAccepted) Topic() common.Hash { + return common.HexToHash("0x3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d") +} + +func (CCIPReaderTesterExecutionStateChanged) Topic() common.Hash { + return common.HexToHash("0x8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df2") +} + +func (_CCIPReaderTester *CCIPReaderTester) Address() common.Address { + return _CCIPReaderTester.address +} + +type CCIPReaderTesterInterface interface { + GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (EVM2EVMMultiOffRampSourceChainConfig, error) + + EmitCCIPSendRequested(opts *bind.TransactOpts, destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) + + EmitCommitReportAccepted(opts *bind.TransactOpts, report EVM2EVMMultiOffRampCommitReport) (*types.Transaction, error) + + EmitExecutionStateChanged(opts *bind.TransactOpts, sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, state uint8, returnData []byte) (*types.Transaction, error) + + SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig EVM2EVMMultiOffRampSourceChainConfig) (*types.Transaction, error) + + FilterCCIPSendRequested(opts *bind.FilterOpts, destChainSelector []uint64) (*CCIPReaderTesterCCIPSendRequestedIterator, error) + + WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *CCIPReaderTesterCCIPSendRequested, destChainSelector []uint64) (event.Subscription, error) + + ParseCCIPSendRequested(log types.Log) (*CCIPReaderTesterCCIPSendRequested, error) + + FilterCommitReportAccepted(opts *bind.FilterOpts) (*CCIPReaderTesterCommitReportAcceptedIterator, error) + + WatchCommitReportAccepted(opts *bind.WatchOpts, sink chan<- *CCIPReaderTesterCommitReportAccepted) (event.Subscription, error) + + ParseCommitReportAccepted(log types.Log) (*CCIPReaderTesterCommitReportAccepted, error) + + FilterExecutionStateChanged(opts *bind.FilterOpts, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (*CCIPReaderTesterExecutionStateChangedIterator, error) + + WatchExecutionStateChanged(opts *bind.WatchOpts, sink chan<- *CCIPReaderTesterExecutionStateChanged, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (event.Subscription, error) + + ParseExecutionStateChanged(log types.Log) (*CCIPReaderTesterExecutionStateChanged, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 663eacb5dd..51e2b45f01 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -6,6 +6,7 @@ burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMint burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin 17bcd03828f43f50028bc4d66fdfb0cf576aaf28895d8f86c6ff598159a0cd64 burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6f40135e1488097eafa843839a719fe9a3c21354565b64eb377a24a0a55782ef ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin c06c1cf1d004a803585a2c9d7a71ee5997b5fca86c2e111335cb8b930d9e3b5a +ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 02be3227883ca4b69383892d27ba7a9af747151a06f4815d18ccd8aaf89b4fb9 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin ddc26c10c2a52b59624faae9005827b09b98db4566887a736005e8cc37cf8a51 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin ebd8aac686fa28a71d4212bcd25a28f8f640d50dce5e50498b2f6b8534890b69 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go index 870ac2dd57..5b66529fb4 100644 --- a/core/gethwrappers/ccip/go_generate.go +++ b/core/gethwrappers/ccip/go_generate.go @@ -37,6 +37,7 @@ package ccip //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.abi ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.bin SelfFundedPingPong self_funded_ping_pong //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin MessageHasher message_hasher //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin MultiOCR3Helper multi_ocr3_helper +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin CCIPReaderTester ccip_reader_tester //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin ReportCodec report_codec //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin EtherSenderReceiver ether_sender_receiver //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/WETH9/WETH9.abi ../../../contracts/solc/v0.8.24/WETH9/WETH9.bin WETH9 weth9 diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 73a2f8c60b..0ddefd5a6c 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -274,7 +274,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240725105722-fb2380a3f739 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index bc1a7b6325..21dfdc98fd 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1070,8 +1070,8 @@ github.com/smartcontractkit/chain-selectors v1.0.19 h1:y82TyWaOA6gSvi26bbyDYgfZv github.com/smartcontractkit/chain-selectors v1.0.19/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-20240725105722-fb2380a3f739 h1:eYe/NS0b97yJV5ffLB+v6ww6R9FcUZV1k07tuArhCdY= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240725105722-fb2380a3f739/go.mod h1:K67FldZZmg+//7yyI0yBMXEw6uvYevTj/ErBEvXaBXM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e h1:aFYsUujFGiVwPAlvG94GHMIaLm8AFQ0V+d10AQD9ogY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e/go.mod h1:K67FldZZmg+//7yyI0yBMXEw6uvYevTj/ErBEvXaBXM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/core/services/ocr3/plugins/ccip_integration_tests/ccipreader/ccipreader_test.go b/core/services/ocr3/plugins/ccip_integration_tests/ccipreader/ccipreader_test.go new file mode 100644 index 0000000000..89d69a12b1 --- /dev/null +++ b/core/services/ocr3/plugins/ccip_integration_tests/ccipreader/ccipreader_test.go @@ -0,0 +1,401 @@ +package ccipreader + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-common/pkg/types" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_reader_tester" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" + "github.com/smartcontractkit/chainlink-ccip/plugintypes" +) + +const ( + chainS1 = cciptypes.ChainSelector(1) + chainS2 = cciptypes.ChainSelector(2) + chainS3 = cciptypes.ChainSelector(3) + chainD = cciptypes.ChainSelector(4) +) + +func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { + ctx := testutils.Context(t) + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOffRamp: { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{consts.EventNameCommitReportAccepted}, + }, + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.EventNameCommitReportAccepted: { + ChainSpecificName: consts.EventNameCommitReportAccepted, + ReadType: evmtypes.Event, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainD, chainD, nil, cfg) + + tokenA := common.HexToAddress("123") + const numReports = 5 + + for i := uint8(0); i < numReports; i++ { + _, err := s.contract.EmitCommitReportAccepted(s.auth, ccip_reader_tester.EVM2EVMMultiOffRampCommitReport{ + PriceUpdates: ccip_reader_tester.InternalPriceUpdates{ + TokenPriceUpdates: []ccip_reader_tester.InternalTokenPriceUpdate{ + { + SourceToken: tokenA, + UsdPerToken: big.NewInt(1000), + }, + }, + GasPriceUpdates: []ccip_reader_tester.InternalGasPriceUpdate{ + { + DestChainSelector: uint64(chainD), + UsdPerUnitGas: big.NewInt(90), + }, + }, + }, + MerkleRoots: []ccip_reader_tester.EVM2EVMMultiOffRampMerkleRoot{ + { + SourceChainSelector: uint64(chainS1), + Interval: ccip_reader_tester.EVM2EVMMultiOffRampInterval{ + Min: 10, + Max: 20, + }, + MerkleRoot: [32]byte{i + 1}, + }, + }, + }) + assert.NoError(t, err) + s.sb.Commit() + } + + var reports []plugintypes.CommitPluginReportWithMeta + var err error + require.Eventually(t, func() bool { + reports, err = s.reader.CommitReportsGTETimestamp( + ctx, + chainD, + time.Unix(30, 0), // Skips first report, simulated backend report timestamps are [20, 30, 40, ...] + 10, + ) + require.NoError(t, err) + return len(reports) == numReports-1 + }, testutils.WaitTimeout(t), 50*time.Millisecond) + + assert.Len(t, reports[0].Report.MerkleRoots, 1) + assert.Equal(t, chainS1, reports[0].Report.MerkleRoots[0].ChainSel) + assert.Equal(t, cciptypes.SeqNum(10), reports[0].Report.MerkleRoots[0].SeqNumsRange.Start()) + assert.Equal(t, cciptypes.SeqNum(20), reports[0].Report.MerkleRoots[0].SeqNumsRange.End()) + assert.Equal(t, "0x0200000000000000000000000000000000000000000000000000000000000000", + reports[0].Report.MerkleRoots[0].MerkleRoot.String()) + + assert.Equal(t, tokenA.String(), string(reports[0].Report.PriceUpdates.TokenPriceUpdates[0].TokenID)) + assert.Equal(t, uint64(1000), reports[0].Report.PriceUpdates.TokenPriceUpdates[0].Price.Uint64()) + + assert.Equal(t, chainD, reports[0].Report.PriceUpdates.GasPriceUpdates[0].ChainSel) + assert.Equal(t, uint64(90), reports[0].Report.PriceUpdates.GasPriceUpdates[0].GasPrice.Uint64()) +} + +func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { + ctx := testutils.Context(t) + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOffRamp: { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{consts.EventNameExecutionStateChanged}, + }, + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.EventNameExecutionStateChanged: { + ChainSpecificName: consts.EventNameExecutionStateChanged, + ReadType: evmtypes.Event, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainD, chainD, nil, cfg) + + _, err := s.contract.EmitExecutionStateChanged( + s.auth, + uint64(chainS1), + 14, + cciptypes.Bytes32{1, 0, 0, 1}, + 1, + []byte{1, 2, 3, 4}, + ) + assert.NoError(t, err) + s.sb.Commit() + + _, err = s.contract.EmitExecutionStateChanged( + s.auth, + uint64(chainS1), + 15, + cciptypes.Bytes32{1, 0, 0, 2}, + 1, + []byte{1, 2, 3, 4, 5}, + ) + assert.NoError(t, err) + s.sb.Commit() + + var executedRanges []cciptypes.SeqNumRange + require.Eventually(t, func() bool { + executedRanges, err = s.reader.ExecutedMessageRanges( + ctx, + chainS1, + chainD, + cciptypes.NewSeqNumRange(14, 15), + ) + require.NoError(t, err) + return len(executedRanges) == 2 + }, testutils.WaitTimeout(t), 50*time.Millisecond) + + assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].Start()) + assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].End()) + + assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].Start()) + assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].End()) +} + +func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { + ctx := testutils.Context(t) + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOnRamp: { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{consts.EventNameCCIPSendRequested}, + }, + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.EventNameCCIPSendRequested: { + ChainSpecificName: consts.EventNameCCIPSendRequested, + ReadType: evmtypes.Event, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainS1, chainD, nil, cfg) + + _, err := s.contract.EmitCCIPSendRequested(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ + Header: ccip_reader_tester.InternalRampMessageHeader{ + MessageId: [32]byte{1, 0, 0, 0, 0}, + SourceChainSelector: uint64(chainS1), + DestChainSelector: uint64(chainD), + SequenceNumber: 10, + }, + Sender: utils.RandomAddress(), + Data: make([]byte, 0), + Receiver: utils.RandomAddress().Bytes(), + ExtraArgs: make([]byte, 0), + FeeToken: utils.RandomAddress(), + FeeTokenAmount: big.NewInt(0), + TokenAmounts: make([]ccip_reader_tester.InternalRampTokenAmount, 0), + }) + assert.NoError(t, err) + + _, err = s.contract.EmitCCIPSendRequested(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ + Header: ccip_reader_tester.InternalRampMessageHeader{ + MessageId: [32]byte{1, 0, 0, 0, 1}, + SourceChainSelector: uint64(chainS1), + DestChainSelector: uint64(chainD), + SequenceNumber: 15, + }, + Sender: utils.RandomAddress(), + Data: make([]byte, 0), + Receiver: utils.RandomAddress().Bytes(), + ExtraArgs: make([]byte, 0), + FeeToken: utils.RandomAddress(), + FeeTokenAmount: big.NewInt(0), + TokenAmounts: make([]ccip_reader_tester.InternalRampTokenAmount, 0), + }) + assert.NoError(t, err) + + s.sb.Commit() + + var msgs []cciptypes.Message + require.Eventually(t, func() bool { + msgs, err = s.reader.MsgsBetweenSeqNums( + ctx, + chainS1, + cciptypes.NewSeqNumRange(5, 20), + ) + require.NoError(t, err) + return len(msgs) == 2 + }, testutils.WaitTimeout(t), 100*time.Millisecond) + + require.Len(t, msgs, 2) + require.Equal(t, cciptypes.SeqNum(10), msgs[0].Header.SequenceNumber) + require.Equal(t, cciptypes.SeqNum(15), msgs[1].Header.SequenceNumber) + for _, msg := range msgs { + require.Equal(t, chainS1, msg.Header.SourceChainSelector) + require.Equal(t, chainD, msg.Header.DestChainSelector) + } +} + +func TestCCIPReader_NextSeqNum(t *testing.T) { + ctx := testutils.Context(t) + + onChainSeqNums := map[cciptypes.ChainSelector]cciptypes.SeqNum{ + chainS1: 10, + chainS2: 20, + chainS3: 30, + } + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOffRamp: { + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.MethodNameGetSourceChainConfig: { + ChainSpecificName: "getSourceChainConfig", + ReadType: evmtypes.Method, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainD, chainD, onChainSeqNums, cfg) + + seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) + assert.NoError(t, err) + assert.Len(t, seqNums, 3) + assert.Equal(t, cciptypes.SeqNum(10), seqNums[0]) + assert.Equal(t, cciptypes.SeqNum(20), seqNums[1]) + assert.Equal(t, cciptypes.SeqNum(30), seqNums[2]) +} + +func testSetup(ctx context.Context, t *testing.T, readerChain, destChain cciptypes.ChainSelector, onChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum, cfg evmtypes.ChainReaderConfig) *testSetupData { + const chainID = 1337 + + // Generate a new key pair for the simulated account + privateKey, err := crypto.GenerateKey() + assert.NoError(t, err) + // Set up the genesis account with balance + blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) + assert.True(t, ok) + alloc := map[common.Address]core.GenesisAccount{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} + simulatedBackend := backends.NewSimulatedBackend(alloc, 0) + // Create a transactor + + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(chainID)) + assert.NoError(t, err) + auth.GasLimit = uint64(0) + + // Deploy the contract + address, _, _, err := ccip_reader_tester.DeployCCIPReaderTester(auth, simulatedBackend) + assert.NoError(t, err) + simulatedBackend.Commit() + + // Setup contract client + contract, err := ccip_reader_tester.NewCCIPReaderTester(address, simulatedBackend) + assert.NoError(t, err) + + lggr := logger.TestLogger(t) + db := pgtest.NewSqlxDB(t) + lpOpts := logpoller.Opts{ + PollPeriod: time.Millisecond, + FinalityDepth: 0, + BackfillBatchSize: 10, + RpcBatchSize: 10, + KeepFinalizedBlocksDepth: 100000, + } + cl := client.NewSimulatedBackendClient(t, simulatedBackend, big.NewInt(0).SetUint64(uint64(readerChain))) + headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(readerChain)), db, lggr), + cl, + lggr, + headTracker, + lpOpts, + ) + assert.NoError(t, lp.Start(ctx)) + + for sourceChain, seqNum := range onChainSeqNums { + _, err1 := contract.SetSourceChainConfig(auth, uint64(sourceChain), ccip_reader_tester.EVM2EVMMultiOffRampSourceChainConfig{ + IsEnabled: true, + MinSeqNr: uint64(seqNum), + }) + assert.NoError(t, err1) + simulatedBackend.Commit() + scc, err1 := contract.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, uint64(sourceChain)) + assert.NoError(t, err1) + assert.Equal(t, seqNum, cciptypes.SeqNum(scc.MinSeqNr)) + } + + contractNames := maps.Keys(cfg.Contracts) + assert.Len(t, contractNames, 1, "test setup assumes there is only one contract") + + cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, cfg) + assert.NoError(t, err) + err = cr.Bind(ctx, []types.BoundContract{ + { + Address: address.String(), + Name: contractNames[0], + }, + }) + assert.NoError(t, err) + err = cr.Start(ctx) + assert.NoError(t, err) + + contractReaders := map[cciptypes.ChainSelector]types.ContractReader{readerChain: cr} + contractWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) + reader := ccipreaderpkg.NewCCIPReader(lggr, contractReaders, contractWriters, destChain) + + t.Cleanup(func() { + require.NoError(t, cr.Close()) + require.NoError(t, lp.Close()) + require.NoError(t, db.Close()) + }) + + return &testSetupData{ + contractAddr: address, + contract: contract, + sb: simulatedBackend, + auth: auth, + lp: lp, + cl: cl, + reader: reader, + } +} + +type testSetupData struct { + contractAddr common.Address + contract *ccip_reader_tester.CCIPReaderTester + sb *backends.SimulatedBackend + auth *bind.TransactOpts + lp logpoller.LogPoller + cl client.Client + reader ccipreaderpkg.CCIPReader +} diff --git a/go.mod b/go.mod index 9d2aafa2ca..a5ceee24b6 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.19 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240725105722-fb2380a3f739 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa diff --git a/go.sum b/go.sum index 0e4fa7e870..8a50101eba 100644 --- a/go.sum +++ b/go.sum @@ -1027,8 +1027,8 @@ github.com/smartcontractkit/chain-selectors v1.0.19 h1:y82TyWaOA6gSvi26bbyDYgfZv github.com/smartcontractkit/chain-selectors v1.0.19/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-20240725105722-fb2380a3f739 h1:eYe/NS0b97yJV5ffLB+v6ww6R9FcUZV1k07tuArhCdY= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240725105722-fb2380a3f739/go.mod h1:K67FldZZmg+//7yyI0yBMXEw6uvYevTj/ErBEvXaBXM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e h1:aFYsUujFGiVwPAlvG94GHMIaLm8AFQ0V+d10AQD9ogY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e/go.mod h1:K67FldZZmg+//7yyI0yBMXEw6uvYevTj/ErBEvXaBXM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 3f62303fb8..47a8711ab6 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -384,7 +384,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240725105722-fb2380a3f739 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 3aa9a190d0..20a032c588 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1392,8 +1392,8 @@ github.com/smartcontractkit/chain-selectors v1.0.19 h1:y82TyWaOA6gSvi26bbyDYgfZv github.com/smartcontractkit/chain-selectors v1.0.19/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-20240725105722-fb2380a3f739 h1:eYe/NS0b97yJV5ffLB+v6ww6R9FcUZV1k07tuArhCdY= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240725105722-fb2380a3f739/go.mod h1:K67FldZZmg+//7yyI0yBMXEw6uvYevTj/ErBEvXaBXM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e h1:aFYsUujFGiVwPAlvG94GHMIaLm8AFQ0V+d10AQD9ogY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e/go.mod h1:K67FldZZmg+//7yyI0yBMXEw6uvYevTj/ErBEvXaBXM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index ddf9b8a16a..852c82d9ac 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -40,7 +40,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240725105722-fb2380a3f739 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect k8s.io/apimachinery v0.30.2 // indirect ) diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 92546ccc86..e20c9beac0 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1374,8 +1374,8 @@ github.com/smartcontractkit/chain-selectors v1.0.19 h1:y82TyWaOA6gSvi26bbyDYgfZv github.com/smartcontractkit/chain-selectors v1.0.19/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-20240725105722-fb2380a3f739 h1:eYe/NS0b97yJV5ffLB+v6ww6R9FcUZV1k07tuArhCdY= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240725105722-fb2380a3f739/go.mod h1:K67FldZZmg+//7yyI0yBMXEw6uvYevTj/ErBEvXaBXM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e h1:aFYsUujFGiVwPAlvG94GHMIaLm8AFQ0V+d10AQD9ogY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240729211818-87f9bb698f6e/go.mod h1:K67FldZZmg+//7yyI0yBMXEw6uvYevTj/ErBEvXaBXM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0=