diff --git a/contracts/src/v0.8/ccip/interfaces/IMessageTransformer.sol b/contracts/src/v0.8/ccip/interfaces/IMessageTransformer.sol new file mode 100644 index 00000000000..c0a7f083fc4 --- /dev/null +++ b/contracts/src/v0.8/ccip/interfaces/IMessageTransformer.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Internal} from "../libraries/Internal.sol"; + +/// @notice Interface for plug-in message hook contracts that transform OffRamp & OnRamp messages. +/// The transformer functions are expected to revert on transform failures. +interface IMessageTransformer { + /// @notice Common error that can be thrown on transform failures and used by consumers + /// @param errorReason abi encoded revert reason + error MessageTransformError(bytes errorReason); + + /// @notice Transforms the given OffRamp message. Reverts on transform failure + /// @param message to transform + /// @return transformed message + function transformInboundMessage( + Internal.Any2EVMRampMessage memory message + ) external returns (Internal.Any2EVMRampMessage memory); + + /// @notice Transforms the given OnRamp message. Reverts on transform failure + /// @param message to transform + /// @return transformed message + function transformOutboundMessage( + Internal.EVM2AnyRampMessage memory message + ) external returns (Internal.EVM2AnyRampMessage memory); +} \ No newline at end of file diff --git a/contracts/src/v0.8/ccip/offRamp/MessageTransformerOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/MessageTransformerOffRamp.sol new file mode 100644 index 00000000000..9551de9a08d --- /dev/null +++ b/contracts/src/v0.8/ccip/offRamp/MessageTransformerOffRamp.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {OffRamp} from "./OffRamp.sol"; +import {IMessageTransformer} from "../interfaces/IMessageTransformer.sol"; +import {Internal} from "../libraries/Internal.sol"; + +contract MessageTransformerOffRamp is OffRamp { + + address internal s_messageTransformer; + + constructor( + StaticConfig memory staticConfig, + DynamicConfig memory dynamicConfig, + SourceChainConfigArgs[] memory sourceChainConfigs, + address messageTransformerAddr + ) OffRamp(staticConfig, dynamicConfig, sourceChainConfigs) { + if (address(messageTransformerAddr) == address(0)) { + revert ZeroAddressNotAllowed(); + } + s_messageTransformer = messageTransformerAddr; + } + + function getMessageTransformerAddress() external view returns (address) { + return s_messageTransformer; + } + + function _beforeExecuteSingleMessage( + Internal.Any2EVMRampMessage memory message + ) internal override returns (Internal.Any2EVMRampMessage memory transformedMessage) { + try IMessageTransformer(s_messageTransformer).transformInboundMessage(message) returns ( + Internal.Any2EVMRampMessage memory m + ) { + transformedMessage = m; + } catch (bytes memory err) { + revert IMessageTransformer.MessageTransformError(err); + } + } +} \ No newline at end of file diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 1a38ece9102..e3f62a4c89c 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -5,7 +5,6 @@ import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; -import {IMessageTransformer} from "../interfaces/IMessageTransformer.sol"; import {INonceManager} from "../interfaces/INonceManager.sol"; import {IPoolV1} from "../interfaces/IPool.sol"; import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; @@ -124,7 +123,6 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { uint32 permissionLessExecutionThresholdSeconds; // │ Waiting time before manual execution is enabled. bool isRMNVerificationDisabled; // ────────────────╯ Flag whether the RMN verification is disabled or not. address messageInterceptor; // Optional, validates incoming messages (zero address = no interceptor). - address messageTransformer; // Optional message transformer to transform incoming messages (zero address = no transformer) } /// @dev Report that is committed by the observing DON at the committing phase. @@ -554,6 +552,14 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { return (Internal.MessageExecutionState.SUCCESS, ""); } + /// @notice hook for applying custom logic to the input message before executeSingleMessage() + /// @param message initial message + /// @return transformedMessage modified message + function _beforeExecuteSingleMessage( + Internal.Any2EVMRampMessage memory message + ) internal virtual returns (Internal.Any2EVMRampMessage memory transformedMessage) { + } + /// @notice Executes a single message. /// @param message The message that will be executed. /// @param offchainTokenData Token transfer data to be passed to TokenPool. @@ -568,15 +574,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { ) external { if (msg.sender != address(this)) revert CanOnlySelfCall(); - if (s_dynamicConfig.messageTransformer != address(0)) { - try IMessageTransformer(s_dynamicConfig.messageTransformer).transformInboundMessage(message) returns ( - Internal.Any2EVMRampMessage memory transformedMessage - ) { - message = transformedMessage; - } catch (bytes memory err) { - revert IMessageTransformer.MessageTransformError(err); - } - } + message = _beforeExecuteSingleMessage(message); Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](0); if (message.tokenAmounts.length > 0) { diff --git a/contracts/src/v0.8/ccip/onRamp/MessageTransformerOnRamp.sol b/contracts/src/v0.8/ccip/onRamp/MessageTransformerOnRamp.sol new file mode 100644 index 00000000000..56f7822c8a5 --- /dev/null +++ b/contracts/src/v0.8/ccip/onRamp/MessageTransformerOnRamp.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {OnRamp} from "./OnRamp.sol"; +import {IMessageTransformer} from "../interfaces/IMessageTransformer.sol"; +import {Internal} from "../libraries/Internal.sol"; + +contract MessageTransformerOnRamp is OnRamp { + + address internal s_messageTransformer; + + error ZeroAddressNotAllowed(); + + constructor( + StaticConfig memory staticConfig, + DynamicConfig memory dynamicConfig, + DestChainConfigArgs[] memory destChainConfigs, + address messageTransformerAddr + ) OnRamp(staticConfig, dynamicConfig, destChainConfigs) { + if (address(messageTransformerAddr) == address(0)) { + revert ZeroAddressNotAllowed(); + } + s_messageTransformer = messageTransformerAddr; + } + + function getMessageTransformerAddress() external view returns (address) { + return s_messageTransformer; + } + + function _postProcessMessage( + Internal.EVM2AnyRampMessage memory message + ) internal override returns (Internal.EVM2AnyRampMessage memory transformedMessage) { + try IMessageTransformer(s_messageTransformer).transformOutboundMessage( + message + ) returns (Internal.EVM2AnyRampMessage memory m) { + transformedMessage = m; + } catch (bytes memory err) { + revert IMessageTransformer.MessageTransformError(err); + } + } +} \ No newline at end of file diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index f96dc616d8c..7898c9fd319 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -5,7 +5,6 @@ import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IEVM2AnyOnRampClient} from "../interfaces/IEVM2AnyOnRampClient.sol"; import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; -import {IMessageTransformer} from "../interfaces/IMessageTransformer.sol"; import {INonceManager} from "../interfaces/INonceManager.sol"; import {IPoolV1} from "../interfaces/IPool.sol"; import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; @@ -72,7 +71,6 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, Ownable2StepMsgSender address feeQuoter; // FeeQuoter address. bool reentrancyGuardEntered; // Reentrancy protection. address messageInterceptor; // Optional message interceptor to validate messages. Zero address = no interceptor. - address messageTransformer; // Optional message transformer to transform outbound messages (zero address = no transformer) address feeAggregator; // Fee aggregator address. address allowlistAdmin; // authorized admin to add or remove allowed senders. } @@ -241,15 +239,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, Ownable2StepMsgSender newMessage.tokenAmounts[i].destExecData = destExecDataPerToken[i]; } - if (s_dynamicConfig.messageTransformer != address(0)) { - try IMessageTransformer(s_dynamicConfig.messageTransformer).transformOutboundMessage( - destChainSelector, newMessage - ) returns (Internal.EVM2AnyRampMessage memory transformedMessage) { - newMessage = transformedMessage; - } catch (bytes memory err) { - revert IMessageTransformer.MessageTransformError(err); - } - } + newMessage = _postProcessMessage(newMessage); // Hash only after all fields have been set. newMessage.header.messageId = Internal._hash( @@ -269,6 +259,14 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, Ownable2StepMsgSender return newMessage.header.messageId; } + /// @notice hook for applying custom logic to the message from router + /// @param message router message + /// @return transformedMessage modified message + function _postProcessMessage( + Internal.EVM2AnyRampMessage memory message + ) internal virtual returns (Internal.EVM2AnyRampMessage memory transformedMessage) { + } + /// @notice Uses a pool to lock or burn a token. /// @param tokenAndAmount Token address and amount to lock or burn. /// @param destChainSelector Target destination chain selector of the message. diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageTransformerHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MessageTransformerHelper.sol index cd2ac5cfdc8..eb50fa8e3b9 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageTransformerHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageTransformerHelper.sol @@ -28,8 +28,6 @@ contract MessageTransformerHelper is IMessageTransformer { /// @inheritdoc IMessageTransformer function transformOutboundMessage( - // solhint-disable-next-line no-unused-vars - uint64 _destChainSelector, Internal.EVM2AnyRampMessage memory message ) public view returns (Internal.EVM2AnyRampMessage memory) { if (s_shouldRevert) { diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/MessageTransformerOffRamp.executeSingleMessage.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/MessageTransformerOffRamp.executeSingleMessage.t.sol new file mode 100644 index 00000000000..ded2c97e371 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/MessageTransformerOffRamp.executeSingleMessage.t.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {OffRamp} from "../../../offRamp/OffRamp.sol"; +import {MessageTransformerOffRamp} from "../../../offRamp/MessageTransformerOffRamp.sol"; +import {OffRampSetup} from "./OffRampSetup.t.sol"; +import {Internal} from "../../../libraries/Internal.sol"; +import {IMessageTransformer} from "../../../interfaces/IMessageTransformer.sol"; +import {MessageTransformerHelper} from "../../helpers/MessageTransformerHelper.sol"; +import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; +import {Router} from "../../../Router.sol"; + +contract MessageTransformerOffRamp_executeSingleMessage is OffRampSetup { + + MessageTransformerOffRamp internal s_messageTransformerOffRamp; + + + function setUp() public virtual override { + super.setUp(); + s_messageTransformerOffRamp = new MessageTransformerOffRamp( + s_offRamp.getStaticConfig(), + s_offRamp.getDynamicConfig(), + new OffRamp.SourceChainConfigArgs[](0), + address(s_inboundMessageTransformer) + ); + + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + s_messageTransformerOffRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2 * sourceChainConfigs.length); + + for (uint256 i = 0; i < sourceChainConfigs.length; ++i) { + uint64 sourceChainSelector = sourceChainConfigs[i].sourceChainSelector; + + offRampUpdates[2 * i] = Router.OffRamp({sourceChainSelector: sourceChainSelector, offRamp: address(s_messageTransformerOffRamp)}); + offRampUpdates[2 * i + 1] = Router.OffRamp({ + sourceChainSelector: sourceChainSelector, + offRamp: s_inboundNonceManager.getPreviousRamps(sourceChainSelector).prevOffRamp + }); + } + + s_destRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function test_executeSingleMessage_WithMessageTransformer() public { + vm.stopPrank(); + vm.startPrank(address(s_messageTransformerOffRamp)); + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + s_messageTransformerOffRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + } + + function test_executeSingleMessage_WithMessageTransformer_RevertWhen_UnknownChain() public { + vm.stopPrank(); + vm.startPrank(address(s_messageTransformerOffRamp)); + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + // Fail with any error (UnknownChain in this case) to check if OffRamp wraps the error with MessageTransformError during the revert + s_inboundMessageTransformer.setShouldRevert(true); + vm.expectRevert( + abi.encodeWithSelector( + IMessageTransformer.MessageTransformError.selector, + abi.encodeWithSelector(MessageTransformerHelper.UnknownChain.selector) + ) + ); + s_messageTransformerOffRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + } +} \ No newline at end of file diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol index 2397c4e484e..40535ad4f7f 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.24; import {IMessageInterceptor} from "../../../interfaces/IMessageInterceptor.sol"; -import {IMessageTransformer} from "../../../interfaces/IMessageTransformer.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; import {Client} from "../../../libraries/Client.sol"; @@ -11,7 +10,6 @@ import {Pool} from "../../../libraries/Pool.sol"; import {OffRamp} from "../../../offRamp/OffRamp.sol"; import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; -import {MessageTransformerHelper} from "../../helpers/MessageTransformerHelper.sol"; import {MaybeRevertMessageReceiverNo165} from "../../helpers/receivers/MaybeRevertMessageReceiverNo165.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; @@ -81,36 +79,6 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_executeSingleMessage_WithMessageTransformer() public { - vm.stopPrank(); - vm.startPrank(OWNER); - _enableInboundMessageTransformer(); - vm.startPrank(address(s_offRamp)); - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - } - - function test_executeSingleMessage_WithMessageTransformer_RevertWhen_UnknownChain() public { - vm.stopPrank(); - vm.startPrank(OWNER); - _enableInboundMessageTransformer(); - vm.startPrank(address(s_offRamp)); - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - - // Fail with any error (UnknownChain in this case) to check if OffRamp wraps the error with MessageTransformError during the revert - s_inboundMessageTransformer.setShouldRevert(true); - - vm.expectRevert( - abi.encodeWithSelector( - IMessageTransformer.MessageTransformError.selector, - abi.encodeWithSelector(MessageTransformerHelper.UnknownChain.selector) - ) - ); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - } - function test_executeSingleMessage_NonContract() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol index 065b313f2db..c98e92b0470 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol @@ -173,8 +173,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { feeQuoter: feeQuoter, permissionLessExecutionThresholdSeconds: 60 * 60, isRMNVerificationDisabled: false, - messageInterceptor: address(0), - messageTransformer: address(0) + messageInterceptor: address(0) }); } @@ -349,12 +348,6 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { s_offRamp.setDynamicConfig(dynamicConfig); } - function _enableInboundMessageTransformer() internal { - OffRamp.DynamicConfig memory dynamicConfig = s_offRamp.getDynamicConfig(); - dynamicConfig.messageTransformer = address(s_inboundMessageTransformer); - s_offRamp.setDynamicConfig(dynamicConfig); - } - function _redeployOffRampWithNoOCRConfigs() internal { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/MessageTransformerOnRamp.forwardFromRouter.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/MessageTransformerOnRamp.forwardFromRouter.t.sol new file mode 100644 index 00000000000..7e163722925 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/MessageTransformerOnRamp.forwardFromRouter.t.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.24; + +import {OnRampSetup} from "./OnRampSetup.t.sol"; +import {OnRamp} from "../../../onRamp/OnRamp.sol"; +import {MessageTransformerOnRamp} from "../../../onRamp/MessageTransformerOnRamp.sol"; +import {MessageTransformerHelper} from "../../helpers/MessageTransformerHelper.sol"; +import {Client} from "../../../libraries/Client.sol"; +import {Internal} from "../../../libraries/Internal.sol"; +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; +import {IMessageTransformer} from "../../../interfaces/IMessageTransformer.sol"; +import {Router} from "../../../Router.sol"; +import {NonceManager} from "../../../NonceManager.sol"; +import {AuthorizedCallers} from "../../../../shared/access/AuthorizedCallers.sol"; + +contract MessageTransformerOnRamp_forwardFromRouter is OnRampSetup { + + MessageTransformerOnRamp internal s_messageTransformerOnRamp; + MessageTransformerHelper internal s_messageTransformer; + + function setUp() public virtual override { + super.setUp(); + s_messageTransformer = new MessageTransformerHelper(); + s_messageTransformerOnRamp = new MessageTransformerOnRamp( + s_onRamp.getStaticConfig(), + s_onRamp.getDynamicConfig(), + _generateDestChainConfigArgs(s_sourceRouter), + address(s_messageTransformer) + ); + s_metadataHash = keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, DEST_CHAIN_SELECTOR, address(s_messageTransformerOnRamp))); + address[] memory authorizedCallers = new address[](1); + authorizedCallers[0] = address(s_messageTransformerOnRamp); + + NonceManager(s_outboundNonceManager).applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) + ); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: address(s_messageTransformerOnRamp)}); + + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: makeAddr("offRamp0")}); + offRampUpdates[1] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: makeAddr("offRamp1")}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + vm.startPrank(address(s_sourceRouter)); + } + + function test_forwardFromRouter_WithMessageTransformer_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); + uint256 feeAmount = 1234567890; + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 1e18; + message.tokenAmounts[0].token = s_sourceTokens[0]; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_messageTransformerOnRamp), feeAmount); + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + s_messageTransformerOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_MessageTransformerError_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); + uint256 feeAmount = 1234567890; + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 1e18; + message.tokenAmounts[0].token = s_sourceTokens[0]; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_messageTransformerOnRamp), feeAmount); + + // Fail with any error (UnknownChain in this case) to check if OnRamp wraps the error with MessageTransformError during the revert + s_messageTransformer.setShouldRevert(true); + vm.expectRevert( + abi.encodeWithSelector( + IMessageTransformer.MessageTransformError.selector, + abi.encodeWithSelector(MessageTransformerHelper.UnknownChain.selector) + ) + ); + s_messageTransformerOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } +} \ No newline at end of file diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol index 12ec4d23b37..8168cff7e1c 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.24; import {IMessageInterceptor} from "../../../interfaces/IMessageInterceptor.sol"; -import {IMessageTransformer} from "../../../interfaces/IMessageTransformer.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; @@ -14,7 +13,6 @@ import {OnRamp} from "../../../onRamp/OnRamp.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; import {MaybeRevertingBurnMintTokenPool} from "../../helpers/MaybeRevertingBurnMintTokenPool.sol"; import {MessageInterceptorHelper} from "../../helpers/MessageInterceptorHelper.sol"; -import {MessageTransformerHelper} from "../../helpers/MessageTransformerHelper.sol"; import {OnRampSetup} from "./OnRampSetup.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; @@ -26,7 +24,6 @@ contract OnRamp_forwardFromRouter is OnRampSetup { } MessageInterceptorHelper internal s_outboundMessageInterceptor; - MessageTransformerHelper internal s_outboundMessageTranformer; address internal s_destTokenPool = makeAddr("destTokenPool"); address internal s_destToken = makeAddr("destToken"); @@ -34,7 +31,6 @@ contract OnRamp_forwardFromRouter is OnRampSetup { function setUp() public virtual override { super.setUp(); s_outboundMessageInterceptor = new MessageInterceptorHelper(); - s_outboundMessageTranformer = new MessageTransformerHelper(); address[] memory feeTokens = new address[](1); feeTokens[0] = s_sourceTokens[1]; @@ -274,23 +270,6 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_forwardFromRouter_WithMessageTransformer_Success() public { - _enableOutboundMessageTransformer(); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); - uint256 feeAmount = 1234567890; - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 1e18; - message.tokenAmounts[0].token = s_sourceTokens[0]; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - // Reverts function test_RevertWhen_Paused() public { @@ -381,30 +360,6 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_MessageTransformerError_Revert() public { - _enableOutboundMessageTransformer(); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); - uint256 feeAmount = 1234567890; - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 1e18; - message.tokenAmounts[0].token = s_sourceTokens[0]; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - // Fail with any error (UnknownChain in this case) to check if OnRamp wraps the error with MessageTransformError during the revert - s_outboundMessageTranformer.setShouldRevert(true); - - vm.expectRevert( - abi.encodeWithSelector( - IMessageTransformer.MessageTransformError.selector, - abi.encodeWithSelector(MessageTransformerHelper.UnknownChain.selector) - ) - ); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - function test_RevertWhen_forwardFromRouter_UnsupportedToken() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.tokenAmounts = new Client.EVMTokenAmount[](1); @@ -528,25 +483,4 @@ contract OnRamp_forwardFromRouter is OnRampSetup { vm.startPrank(msgSender); } } - - function _enableOutboundMessageTransformer() internal { - (, address msgSender,) = vm.readCallers(); - - bool resetPrank = false; - - if (msgSender != OWNER) { - vm.stopPrank(); - vm.startPrank(OWNER); - resetPrank = true; - } - - OnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); - dynamicConfig.messageTransformer = address(s_outboundMessageTranformer); - s_onRamp.setDynamicConfig(dynamicConfig); - - if (resetPrank) { - vm.stopPrank(); - vm.startPrank(msgSender); - } - } } diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol index 177b5582d55..10839968dbe 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol @@ -12,7 +12,6 @@ contract OnRamp_setDynamicConfig is OnRampSetup { feeQuoter: address(23423), reentrancyGuardEntered: false, messageInterceptor: makeAddr("messageInterceptor"), - messageTransformer: address(0), feeAggregator: FEE_AGGREGATOR, allowlistAdmin: address(0) }); @@ -34,7 +33,6 @@ contract OnRamp_setDynamicConfig is OnRampSetup { reentrancyGuardEntered: false, feeAggregator: FEE_AGGREGATOR, messageInterceptor: makeAddr("messageInterceptor"), - messageTransformer: address(0), allowlistAdmin: address(0) }); @@ -47,7 +45,6 @@ contract OnRamp_setDynamicConfig is OnRampSetup { feeQuoter: address(23423), reentrancyGuardEntered: false, messageInterceptor: address(0), - messageTransformer: address(0), feeAggregator: FEE_AGGREGATOR, allowlistAdmin: address(0) }); @@ -63,7 +60,6 @@ contract OnRamp_setDynamicConfig is OnRampSetup { feeQuoter: address(23423), reentrancyGuardEntered: false, messageInterceptor: address(0), - messageTransformer: address(0), feeAggregator: address(0), allowlistAdmin: address(0) }); @@ -83,7 +79,6 @@ contract OnRamp_setDynamicConfig is OnRampSetup { feeQuoter: address(23423), reentrancyGuardEntered: true, messageInterceptor: makeAddr("messageInterceptor"), - messageTransformer: address(0), feeAggregator: FEE_AGGREGATOR, allowlistAdmin: address(0) }); diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol index beaa491485b..e310a733bc6 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol @@ -133,7 +133,6 @@ contract OnRampSetup is FeeQuoterFeeSetup { feeQuoter: feeQuoter, reentrancyGuardEntered: false, messageInterceptor: address(0), - messageTransformer: address(0), feeAggregator: FEE_AGGREGATOR, allowlistAdmin: address(0) });