diff --git a/.changeset/three-mayflies-learn.md b/.changeset/three-mayflies-learn.md new file mode 100644 index 00000000000..1ea4fad3924 --- /dev/null +++ b/.changeset/three-mayflies-learn.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#updated Update few incorrect occurences of the password for notreal@fakeemail.ch. diff --git a/contracts/.changeset/wet-eyes-accept.md b/contracts/.changeset/wet-eyes-accept.md new file mode 100644 index 00000000000..ea783366220 --- /dev/null +++ b/contracts/.changeset/wet-eyes-accept.md @@ -0,0 +1,7 @@ +--- +'@chainlink/contracts': patch +--- + +Refactor MockCCIPRouter to support EVMExtraArgsV2 + +PR issue : CCIP-4288 diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 3904b4ef2e6..aa09359e839 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -257,11 +257,14 @@ MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3563) MerkleMultiProofTest:test_MerkleRoot256() (gas: 394891) MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3661) MerkleMultiProofTest:test_SpecSync_gas() (gas: 34152) -MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34081) -MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60886) -MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126631) -MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63521) -MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 44056) +MockRouterTest:test_ccipSendWithEVMExtraArgsV1_Success() (gas: 110095) +MockRouterTest:test_ccipSendWithEVMExtraArgsV2_Success() (gas: 132614) +MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34059) +MockRouterTest:test_ccipSendWithInvalidEVMExtraArgs_Revert() (gas: 106706) +MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60864) +MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126685) +MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63477) +MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 44070) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ConfigRateMoreThanCapacity_Revert() (gas: 16554) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ConfigRateZero_Revert() (gas: 16634) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_DiableConfigCapacityNonZero_Revert() (gas: 16585) diff --git a/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol b/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol index 0abe4fdb7e5..3ded9fd78f0 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol @@ -121,12 +121,19 @@ contract MockCCIPRouter is IRouter, IRouterClient { function _fromBytes( bytes calldata extraArgs - ) internal pure returns (Client.EVMExtraArgsV1 memory) { + ) internal pure returns (Client.EVMExtraArgsV2 memory) { if (extraArgs.length == 0) { - return Client.EVMExtraArgsV1({gasLimit: DEFAULT_GAS_LIMIT}); + return Client.EVMExtraArgsV2({gasLimit: DEFAULT_GAS_LIMIT, allowOutOfOrderExecution: false}); } - if (bytes4(extraArgs) != Client.EVM_EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); - return abi.decode(extraArgs[4:], (Client.EVMExtraArgsV1)); + + bytes4 extraArgsTag = bytes4(extraArgs); + if (extraArgsTag == Client.EVM_EXTRA_ARGS_V2_TAG) { + return abi.decode(extraArgs[4:], (Client.EVMExtraArgsV2)); + } else if (extraArgsTag == Client.EVM_EXTRA_ARGS_V1_TAG) { + return Client.EVMExtraArgsV2({gasLimit: abi.decode(extraArgs[4:], (uint256)), allowOutOfOrderExecution: false}); + } + + revert InvalidExtraArgsTag(); } /// @notice Always returns true to make sure this check can be performed on any chain. diff --git a/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol b/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol index cd0aabf1776..549d6b8f843 100644 --- a/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol +++ b/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol @@ -65,4 +65,24 @@ contract MockRouterTest is TokenSetup { mockRouter.ccipSend(MOCK_CHAIN_SELECTOR, message); } + + function test_ccipSendWithEVMExtraArgsV1_Success() public { + Client.EVMExtraArgsV1 memory extraArgs = Client.EVMExtraArgsV1({gasLimit: 500_000}); + message.extraArgs = Client._argsToBytes(extraArgs); + mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); + } + + function test_ccipSendWithEVMExtraArgsV2_Success() public { + Client.EVMExtraArgsV2 memory extraArgs = Client.EVMExtraArgsV2({gasLimit: 500_000, allowOutOfOrderExecution: true}); + message.extraArgs = Client._argsToBytes(extraArgs); + mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); + } + + function test_ccipSendWithInvalidEVMExtraArgs_Revert() public { + uint256 gasLimit = 500_000; + bytes4 invalidExtraArgsTag = bytes4(keccak256("CCIP EVMExtraArgsInvalid")); + message.extraArgs = abi.encodeWithSelector(invalidExtraArgsTag, gasLimit); + vm.expectRevert(MockCCIPRouter.InvalidExtraArgsTag.selector); + mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); + } } diff --git a/core/scripts/chaincli/README.md b/core/scripts/chaincli/README.md index 992250ae77c..bd32c3cbf11 100644 --- a/core/scripts/chaincli/README.md +++ b/core/scripts/chaincli/README.md @@ -101,7 +101,7 @@ You can also combine the `bootstrap` and `launch-and-test` commands into a singl ```shell ./chaincli keeper launch-and-test --bootstrap ``` -In the output of this command, you will see the http address of the nodes, e.g. `http://localhost:6688`. This is the Chainlink Operator GUI. You can use the default username `notreal@fakeemail.ch` and password `fj293fbBnlQ!f9vNs~#` to log in. +In the output of this command, you will see the http address of the nodes, e.g. `http://localhost:6688`. This is the Chainlink Operator GUI. You can use the default username `notreal@fakeemail.ch` and password `fj293fbBnlQ!f9vNs` to log in. ### Logs Now that the nodes are running, you can use the `logs` subcommand to stream the output of the containers to your local terminal: diff --git a/core/scripts/chaincli/handler/handler.go b/core/scripts/chaincli/handler/handler.go index d40ee84a312..50576fe0fe8 100644 --- a/core/scripts/chaincli/handler/handler.go +++ b/core/scripts/chaincli/handler/handler.go @@ -44,7 +44,7 @@ import ( const ( defaultChainlinkNodeLogin = "notreal@fakeemail.ch" - defaultChainlinkNodePassword = "fj293fbBnlQ!f9vNs~#" + defaultChainlinkNodePassword = "fj293fbBnlQ!f9vNs" ethKeysEndpoint = "/v2/keys/eth" ocr2KeysEndpoint = "/v2/keys/ocr2" p2pKeysEndpoint = "/v2/keys/p2p" diff --git a/core/services/relay/evm/read/batch.go b/core/services/relay/evm/read/batch.go index dbe8c8be549..16333149f11 100644 --- a/core/services/relay/evm/read/batch.go +++ b/core/services/relay/evm/read/batch.go @@ -128,7 +128,7 @@ func newDefaultEvmBatchCaller( } // batchCall formats a batch, calls the rpc client, and unpacks results. -// this function only returns errors of type ErrRead which should wrap lower errors. +// this function only returns errors of type Error which should wrap lower errors. func (c *defaultEvmBatchCaller) batchCall(ctx context.Context, blockNumber uint64, batchCall BatchCall) ([]dataAndErr, error) { if len(batchCall) == 0 { return nil, nil @@ -147,9 +147,9 @@ func (c *defaultEvmBatchCaller) batchCall(ctx context.Context, blockNumber uint6 if err = c.evmClient.BatchCallContext(ctx, rpcBatchCalls); err != nil { // return a basic read error with no detail or result since this is a general client // error instead of an error for a specific batch call. - return nil, ErrRead{ - Err: fmt.Errorf("%w: batch call context: %s", types.ErrInternal, err.Error()), - Batch: true, + return nil, Error{ + Err: fmt.Errorf("%w: batch call context: %s", types.ErrInternal, err.Error()), + Type: batchReadType, } } @@ -176,7 +176,7 @@ func (c *defaultEvmBatchCaller) createBatchCalls( fmt.Errorf("%w: encode params: %s", types.ErrInvalidConfig, err.Error()), call, block, - true, + batchReadType, ) } @@ -217,7 +217,7 @@ func (c *defaultEvmBatchCaller) unpackBatchResults( if rpcBatchCalls[idx].Error != nil { results[idx].err = newErrorFromCall( fmt.Errorf("%w: rpc call error: %w", types.ErrInternal, rpcBatchCalls[idx].Error), - call, block, true, + call, block, batchReadType, ) continue @@ -233,7 +233,7 @@ func (c *defaultEvmBatchCaller) unpackBatchResults( if err != nil { callErr := newErrorFromCall( fmt.Errorf("%w: hex decode result: %s", types.ErrInternal, err.Error()), - call, block, true, + call, block, batchReadType, ) callErr.Result = &hexEncodedOutputs[idx] @@ -250,7 +250,7 @@ func (c *defaultEvmBatchCaller) unpackBatchResults( if len(packedBytes) == 0 { callErr := newErrorFromCall( fmt.Errorf("%w: %w: %s", types.ErrInternal, errEmptyOutput, err.Error()), - call, block, true, + call, block, batchReadType, ) callErr.Result = &hexEncodedOutputs[idx] @@ -259,7 +259,7 @@ func (c *defaultEvmBatchCaller) unpackBatchResults( } else { callErr := newErrorFromCall( fmt.Errorf("%w: codec decode result: %s", types.ErrInvalidType, err.Error()), - call, block, true, + call, block, batchReadType, ) callErr.Result = &hexEncodedOutputs[idx] @@ -290,9 +290,9 @@ func (c *defaultEvmBatchCaller) batchCallDynamicLimitRetries(ctx context.Context } if lim <= 1 { - return nil, ErrRead{ - Err: fmt.Errorf("%w: limited call: call data: %+v", err, calls), - Batch: true, + return nil, Error{ + Err: fmt.Errorf("%w: limited call: call data: %+v", err, calls), + Type: batchReadType, } } diff --git a/core/services/relay/evm/read/errors.go b/core/services/relay/evm/read/errors.go index bec14d7dd4b..422b7ded1d8 100644 --- a/core/services/relay/evm/read/errors.go +++ b/core/services/relay/evm/read/errors.go @@ -10,9 +10,17 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" ) -type ErrRead struct { +type readType string + +const ( + batchReadType readType = "BatchGetLatestValue" + singleReadType readType = "GetLatestValue" + eventReadType readType = "QueryKey" +) + +type Error struct { Err error - Batch bool + Type readType Detail *readDetail Result *string } @@ -25,10 +33,10 @@ type readDetail struct { Block string } -func newErrorFromCall(err error, call Call, block string, batch bool) ErrRead { - return ErrRead{ - Err: err, - Batch: batch, +func newErrorFromCall(err error, call Call, block string, tp readType) Error { + return Error{ + Err: err, + Type: tp, Detail: &readDetail{ Address: call.ContractAddress.Hex(), Contract: call.ContractName, @@ -40,12 +48,12 @@ func newErrorFromCall(err error, call Call, block string, batch bool) ErrRead { } } -func (e ErrRead) Error() string { +func (e Error) Error() string { var builder strings.Builder - builder.WriteString("[rpc error]") - builder.WriteString(fmt.Sprintf(" batch: %T;", e.Batch)) + builder.WriteString("[read error]") builder.WriteString(fmt.Sprintf(" err: %s;", e.Err.Error())) + builder.WriteString(fmt.Sprintf(" type: %s;", e.Type)) if e.Detail != nil { builder.WriteString(fmt.Sprintf(" block: %s;", e.Detail.Block)) @@ -63,7 +71,7 @@ func (e ErrRead) Error() string { return builder.String() } -func (e ErrRead) Unwrap() error { +func (e Error) Unwrap() error { return e.Err } diff --git a/core/services/relay/evm/read/event.go b/core/services/relay/evm/read/event.go index c37b979d7ea..d2b54e5bd64 100644 --- a/core/services/relay/evm/read/event.go +++ b/core/services/relay/evm/read/event.go @@ -247,7 +247,7 @@ func (b *EventBinding) GetLatestValueWithHeadData(ctx context.Context, address c ReadName: b.eventName, Params: params, ReturnVal: into, - }, strconv.Itoa(int(confs)), false) + }, strconv.Itoa(int(confs)), eventReadType) callErr.Result = result @@ -315,7 +315,7 @@ func (b *EventBinding) QueryKey(ctx context.Context, address common.Address, fil ContractName: b.contractName, ReadName: b.eventName, ReturnVal: sequenceDataType, - }, "", false) + }, "", eventReadType) } }() diff --git a/core/services/relay/evm/read/method.go b/core/services/relay/evm/read/method.go index 393077c6d3f..e988e4352f7 100644 --- a/core/services/relay/evm/read/method.go +++ b/core/services/relay/evm/read/method.go @@ -68,8 +68,9 @@ func (b *MethodBinding) Bind(ctx context.Context, bindings ...common.Address) er // check for contract byte code at the latest block and provided address byteCode, err := b.client.CodeAt(ctx, binding, nil) if err != nil { - return ErrRead{ - Err: fmt.Errorf("%w: code at call failure: %s", commontypes.ErrInternal, err.Error()), + return Error{ + Err: fmt.Errorf("%w: code at call failure: %s", commontypes.ErrInternal, err.Error()), + Type: singleReadType, Detail: &readDetail{ Address: binding.Hex(), Contract: b.contractName, @@ -146,7 +147,7 @@ func (b *MethodBinding) GetLatestValueWithHeadData(ctx context.Context, addr com ReadName: b.method, Params: params, ReturnVal: returnVal, - }, blockNum.String(), false) + }, blockNum.String(), singleReadType) return nil, callErr } @@ -167,7 +168,7 @@ func (b *MethodBinding) GetLatestValueWithHeadData(ctx context.Context, addr com ReadName: b.method, Params: params, ReturnVal: returnVal, - }, blockNum.String(), false) + }, blockNum.String(), singleReadType) return nil, callErr } @@ -181,7 +182,7 @@ func (b *MethodBinding) GetLatestValueWithHeadData(ctx context.Context, addr com ReadName: b.method, Params: params, ReturnVal: returnVal, - }, blockNum.String(), false) + }, blockNum.String(), singleReadType) strResult := hexutil.Encode(bytes) callErr.Result = &strResult