diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index c4f04f4a5e..fe15519809 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -34,34 +34,84 @@ BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28789) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55208) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243659) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24260) -CCIPClientTest:test_ccipReceiveAndSendAck() (gas: 329845) -CCIPClientTest:test_ccipSendAndReceiveAck_in_return() (gas: 346013) -CCIPClientTest:test_ccipSend_withNativeFeeToken_butInsufficientMsgValue_REVERT() (gas: 84106) -CCIPClientTest:test_ccipSend_withNonNativeFeetoken_andNoDestTokens() (gas: 241012) -CCIPClientTest:test_send_tokens_that_are_not_feeToken() (gas: 552160) -CCIPReceiverTest:test_HappyPath_Success() (gas: 191871) -CCIPReceiverTest:test_Recovery_from_invalid_sender() (gas: 426569) -CCIPReceiverTest:test_Recovery_with_intentional_revert() (gas: 430405) -CCIPReceiverTest:test_disableChain_andRevert_onccipReceive_REVERT() (gas: 195931) -CCIPReceiverTest:test_removeSender_from_approvedList_and_revert() (gas: 422998) -CCIPReceiverTest:test_withdraw_nativeToken_to_owner() (gas: 18764) -CCIPReceiverWithAckTest:test_ccipReceive_ack_message() (gas: 53048) -CCIPReceiverWithAckTest:test_ccipReceive_and_respond_with_ack() (gas: 329799) -CCIPReceiverWithAckTest:test_ccipReceiver_ack_with_invalidMagicBytes_REVERT() (gas: 435470) -CCIPReceiverWithAckTest:test_feeTokenApproval_in_constructor() (gas: 2527173) -CCIPReceiverWithAckTest:test_modifyFeeToken() (gas: 72547) -CCIPSenderTest:test_ccipSend_withNativeFeeToken_butInsufficientMsgValue_REVERT() (gas: 81734) -CCIPSenderTest:test_ccipSend_withNonNativeFeetoken_andDestTokens() (gas: 334866) -CCIPSenderTest:test_ccipSend_withNonNativeFeetoken_andNoDestTokens() (gas: 223788) -CCIPSenderTest:test_ccipSend_with_NativeFeeToken_andDestTokens() (gas: 368070) -CommitStore_constructor:test_Constructor_Success() (gas: 3113994) -CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 74815) -CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28693) -CommitStore_report:test_InvalidInterval_Revert() (gas: 28633) -CommitStore_report:test_InvalidRootRevert() (gas: 27866) -CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 55389) -CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 61208) -CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 55387) +CCIPCapabilityConfigurationSetup:test_getCapabilityConfiguration_Success() (gas: 9561) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70645) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 350565) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 471510) +CCIPCapabilityConfiguration_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 440232) +CCIPCapabilityConfiguration_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 37027) +CCIPCapabilityConfiguration_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61043) +CCIPCapabilityConfiguration_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60963) +CCIPCapabilityConfiguration_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11764) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8897) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 303038) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 49619) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 32253) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 367516) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 120877) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 156973) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 367292) +CCIPCapabilityConfiguration_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 157040) +CCIPCapabilityConfiguration_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9648) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1044370) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 27539) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 23083) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 1992245) +CCIPCapabilityConfiguration__updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2595825) +CCIPCapabilityConfiguration__updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9626) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1833893) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1055282) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1055313) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilityRegistryCanCall_Reverts() (gas: 9576) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16070) +CCIPCapabilityConfiguration_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9626) +CCIPCapabilityConfiguration_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 182909) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 342472) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 19116) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 266071) +CCIPCapabilityConfiguration_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14807) +CCIPCapabilityConfiguration_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9604) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 285383) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 282501) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 283422) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 283588) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 287815) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1068544) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 282309) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 284277) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_Success() (gas: 289222) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_TooManyBootstrapP2PIds_Reverts() (gas: 285518) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 1120660) +CCIPCapabilityConfiguration_validateConfig:test__validateConfig_TooManyTransmitters_Reverts() (gas: 1119000) +CCIPCapabilityConfiguration_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9540) +CCIPClientTest:test_ccipReceiveAndSendAck() (gas: 329842) +CCIPClientTest:test_ccipSendAndReceiveAck_in_return() (gas: 345519) +CCIPClientTest:test_ccipSend_withNativeFeeToken_butInsufficientMsgValue_REVERT() (gas: 84023) +CCIPClientTest:test_ccipSend_withNonNativeFeetoken_andNoDestTokens() (gas: 240978) +CCIPClientTest:test_send_tokens_that_are_not_feeToken() (gas: 551652) +CCIPReceiverTest:test_HappyPath_Success() (gas: 191895) +CCIPReceiverTest:test_Recovery_from_invalid_sender() (gas: 426665) +CCIPReceiverTest:test_Recovery_with_intentional_revert() (gas: 430412) +CCIPReceiverTest:test_disableChain_andRevert_onccipReceive_REVERT() (gas: 195900) +CCIPReceiverTest:test_removeSender_from_approvedList_and_revert() (gas: 422972) +CCIPReceiverTest:test_withdraw_nativeToken_to_owner() (gas: 18786) +CCIPReceiverWithAckTest:test_ccipReceive_ack_message() (gas: 53078) +CCIPReceiverWithAckTest:test_ccipReceive_and_respond_with_ack() (gas: 329840) +CCIPReceiverWithAckTest:test_ccipReceiver_ack_with_invalidMagicBytes_REVERT() (gas: 435500) +CCIPReceiverWithAckTest:test_feeTokenApproval_in_constructor() (gas: 2559441) +CCIPReceiverWithAckTest:test_modifyFeeToken() (gas: 72524) +CCIPSenderTest:test_ccipSend_withNativeFeeToken_butInsufficientMsgValue_REVERT() (gas: 81718) +CCIPSenderTest:test_ccipSend_withNonNativeFeetoken_andDestTokens() (gas: 334315) +CCIPSenderTest:test_ccipSend_withNonNativeFeetoken_andNoDestTokens() (gas: 223821) +CCIPSenderTest:test_ccipSend_with_NativeFeeToken_andDestTokens() (gas: 367519) +CommitStore_constructor:test_Constructor_Success() (gas: 3091440) +CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 75331) +CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28784) +CommitStore_report:test_InvalidInterval_Revert() (gas: 28724) +CommitStore_report:test_InvalidRootRevert() (gas: 27957) +CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 55480) +CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 61390) +CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 55478) CommitStore_report:test_Paused_Revert() (gas: 21259) CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 86469) CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56427) @@ -82,8 +132,6 @@ CommitStore_verify:test_Blessed_Success() (gas: 96279) CommitStore_verify:test_NotBlessed_Success() (gas: 58800) CommitStore_verify:test_Paused_Revert() (gas: 18496) CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36785) -DefensiveExampleTest:test_HappyPath_Success() (gas: 200018) -DefensiveExampleTest:test_Recovery() (gas: 424253) E2E:test_E2E_3MessagesSuccess_gas() (gas: 1106837) EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 38297) EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 108537) @@ -161,7 +209,7 @@ EVM2EVMMultiOffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (ga EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 170378) EVM2EVMMultiOffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 182190) EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 47177) -EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 405951) +EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 1390097) EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 233102) EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 180689) EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 251836) @@ -193,8 +241,8 @@ EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouche EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 199879) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 28213) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 160718) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 497791) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2371474) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 1482012) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 3173532) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 201989) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 202563) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 651271) @@ -333,7 +381,7 @@ EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 101560) EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 165312) EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 178182) EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 41431) -EVM2EVMOffRamp_execute:test_RouterYULCall_Revert() (gas: 402717) +EVM2EVMOffRamp_execute:test_RouterYULCall_Revert() (gas: 1386878) EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 160103) EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 175334) EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 248878) @@ -365,14 +413,14 @@ EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 132026) EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38408) EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3213556) EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83091) -EVM2EVMOffRamp_manuallyExecute:test_LowGasLimitManualExec_Success() (gas: 484053) +EVM2EVMOffRamp_manuallyExecute:test_LowGasLimitManualExec_Success() (gas: 1468371) EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 187049) EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 25894) EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 43519) EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26009) EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithGasOverride_Success() (gas: 189243) EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 188704) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails() (gas: 2028045) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails() (gas: 2853756) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 144226) EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8871) EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40429) @@ -632,9 +680,9 @@ OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23484) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39665) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20557) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 381362) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 148868) -PingPong_plumbing:test_Pausing_Success() (gas: 17803) -PingPong_startPingPong:test_StartPingPong_Success() (gas: 178941) +PingPong_example_ccipReceive:test_CcipReceive_Success() (gas: 200924) +PingPong_example_plumbing:test_Pausing_Success() (gas: 17898) +PingPong_example_startPingPong:test_StartPingPong_Success() (gas: 224406) PriceRegistry_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 79823) PriceRegistry_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12580) PriceRegistry_applyPriceUpdatersUpdates:test_ApplyPriceUpdaterUpdates_Success() (gas: 82654) @@ -763,9 +811,9 @@ Router_routeMessage:test_ManualExec_Success() (gas: 35387) Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25122) Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44669) Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10985) -SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 53600) -SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 419773) -SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20157) +SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 288024) +SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 449940) +SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20226) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51085) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43947) TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12629) diff --git a/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol b/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol deleted file mode 100644 index 7fe8977948..0000000000 --- a/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol +++ /dev/null @@ -1,174 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IRouterClient} from "../interfaces/IRouterClient.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {Client} from "../libraries/Client.sol"; -import {CCIPReceiver} from "./CCIPReceiver.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -// @notice Example of a client which supports EVM/non-EVM chains -// @dev If chain specific logic is required for different chain families (e.g. particular -// decoding the bytes sender for authorization checks), it may be required to point to a helper -// authorization contract unless all chain families are known up front. -// @dev If contract does not implement IAny2EVMMessageReceiver and IERC165, -// and tokens are sent to it, ccipReceive will not be called but tokens will be transferred. -// @dev If the client is upgradeable you have significantly more flexibility and -// can avoid storage based options like the below contract uses. However it's -// worth carefully considering how the trust assumptions of your client dapp will -// change if you introduce upgradeability. An immutable dapp building on top of CCIP -// like the example below will inherit the trust properties of CCIP (i.e. the oracle network). -// @dev The receiver's are encoded offchain and passed as direct arguments to permit supporting -// new chain family receivers (e.g. a solana encoded receiver address) without upgrading. -contract CCIPClientExample is CCIPReceiver, OwnerIsCreator { - error InvalidConfig(); - error InvalidChain(uint64 chainSelector); - - event MessageSent(bytes32 messageId); - event MessageReceived(bytes32 messageId); - - // Current feeToken - IERC20 public s_feeToken; - // Below is a simplistic example (same params for all messages) of using storage to allow for new options without - // upgrading the dapp. Note that extra args are chain family specific (e.g. gasLimit is EVM specific etc.). - // and will always be backwards compatible i.e. upgrades are opt-in. - // Offchain we can compute the V1 extraArgs: - // Client.EVMExtraArgsV1 memory extraArgs = Client.EVMExtraArgsV1({gasLimit: 300_000}); - // bytes memory encodedV1ExtraArgs = Client._argsToBytes(extraArgs); - // Then later compute V2 extraArgs, for example if a refund feature was added: - // Client.EVMExtraArgsV2 memory extraArgs = Client.EVMExtraArgsV2({gasLimit: 300_000, destRefundAddress: 0x1234}); - // bytes memory encodedV2ExtraArgs = Client._argsToBytes(extraArgs); - // and update storage with the new args. - // If different options are required for different messages, for example different gas limits, - // one can simply key based on (chainSelector, messageType) instead of only chainSelector. - mapping(uint64 destChainSelector => bytes extraArgsBytes) public s_chains; - - constructor(IRouterClient router, IERC20 feeToken) CCIPReceiver(address(router)) { - s_feeToken = feeToken; - s_feeToken.approve(address(router), type(uint256).max); - } - - function enableChain(uint64 chainSelector, bytes memory extraArgs) external onlyOwner { - s_chains[chainSelector] = extraArgs; - } - - function disableChain(uint64 chainSelector) external onlyOwner { - delete s_chains[chainSelector]; - } - - function ccipReceive(Client.Any2EVMMessage calldata message) - external - virtual - override - onlyRouter - validChain(message.sourceChainSelector) - { - // Extremely important to ensure only router calls this. - // Tokens in message if any will be transferred to this contract - // TODO: Validate sender/origin chain and process message and/or tokens. - _ccipReceive(message); - } - - function _ccipReceive(Client.Any2EVMMessage memory message) internal override { - emit MessageReceived(message.messageId); - } - - /// @notice sends data to receiver on dest chain. Assumes address(this) has sufficient native asset. - function sendDataPayNative( - uint64 destChainSelector, - bytes memory receiver, - bytes memory data - ) external validChain(destChainSelector) { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](0); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: receiver, - data: data, - tokenAmounts: tokenAmounts, - extraArgs: s_chains[destChainSelector], - feeToken: address(0) // We leave the feeToken empty indicating we'll pay raw native. - }); - bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend{ - value: IRouterClient(i_ccipRouter).getFee(destChainSelector, message) - }(destChainSelector, message); - emit MessageSent(messageId); - } - - /// @notice sends data to receiver on dest chain. Assumes address(this) has sufficient feeToken. - function sendDataPayFeeToken( - uint64 destChainSelector, - bytes memory receiver, - bytes memory data - ) external validChain(destChainSelector) { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](0); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: receiver, - data: data, - tokenAmounts: tokenAmounts, - extraArgs: s_chains[destChainSelector], - feeToken: address(s_feeToken) - }); - // Optional uint256 fee = i_ccipRouter.getFee(destChainSelector, message); - // Can decide if fee is acceptable. - // address(this) must have sufficient feeToken or the send will revert. - bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend(destChainSelector, message); - emit MessageSent(messageId); - } - - /// @notice sends data to receiver on dest chain. Assumes address(this) has sufficient native token. - function sendDataAndTokens( - uint64 destChainSelector, - bytes memory receiver, - bytes memory data, - Client.EVMTokenAmount[] memory tokenAmounts - ) external validChain(destChainSelector) { - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - IERC20(tokenAmounts[i].token).transferFrom(msg.sender, address(this), tokenAmounts[i].amount); - IERC20(tokenAmounts[i].token).approve(i_ccipRouter, tokenAmounts[i].amount); - } - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: receiver, - data: data, - tokenAmounts: tokenAmounts, - extraArgs: s_chains[destChainSelector], - feeToken: address(s_feeToken) - }); - // Optional uint256 fee = i_ccipRouter.getFee(destChainSelector, message); - // Can decide if fee is acceptable. - // address(this) must have sufficient feeToken or the send will revert. - bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend(destChainSelector, message); - emit MessageSent(messageId); - } - - // @notice user sends tokens to a receiver - // Approvals can be optimized with a whitelist of tokens and inf approvals if desired. - function sendTokens( - uint64 destChainSelector, - bytes memory receiver, - Client.EVMTokenAmount[] memory tokenAmounts - ) external validChain(destChainSelector) { - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - IERC20(tokenAmounts[i].token).transferFrom(msg.sender, address(this), tokenAmounts[i].amount); - IERC20(tokenAmounts[i].token).approve(i_ccipRouter, tokenAmounts[i].amount); - } - bytes memory data; - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: receiver, - data: data, - tokenAmounts: tokenAmounts, - extraArgs: s_chains[destChainSelector], - feeToken: address(s_feeToken) - }); - // Optional uint256 fee = i_ccipRouter.getFee(destChainSelector, message); - // Can decide if fee is acceptable. - // address(this) must have sufficient feeToken or the send will revert. - bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend(destChainSelector, message); - emit MessageSent(messageId); - } - - modifier validChain(uint64 chainSelector) { - if (s_chains[chainSelector].length == 0) revert InvalidChain(chainSelector); - _; - } -} diff --git a/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol b/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol deleted file mode 100644 index 10a1d202d9..0000000000 --- a/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol +++ /dev/null @@ -1,182 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -import {IRouterClient} from "../interfaces/IRouterClient.sol"; -import {IWrappedNative} from "../interfaces/IWrappedNative.sol"; - -import {Client} from "./../libraries/Client.sol"; -import {CCIPReceiver} from "./CCIPReceiver.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -interface CCIPRouter { - function getWrappedNative() external view returns (address); -} - -/// @notice A contract that can send raw ether cross-chain using CCIP. -/// Since CCIP only supports ERC-20 token transfers, this contract accepts -/// normal ether, wraps it, and uses CCIP to send it cross-chain. -/// On the receiving side, the wrapped ether is unwrapped and sent to the final receiver. -/// @notice This contract only supports chains where the wrapped native contract -/// is the WETH contract (i.e not WMATIC, or WAVAX, etc.). This is because the -/// receiving contract will always unwrap the ether using it's local wrapped native contract. -/// @dev This contract is both a sender and a receiver. This same contract can be -/// deployed on source and destination chains to facilitate cross-chain ether transfers -/// and act as a sender and a receiver. -/// @dev This contract is intentionally ownerless and permissionless. This contract -/// will never hold any excess funds, native or otherwise, when used correctly. -contract EtherSenderReceiver is CCIPReceiver, ITypeAndVersion { - using SafeERC20 for IERC20; - - error InvalidTokenAmounts(uint256 gotAmounts); - error InvalidToken(address gotToken, address expectedToken); - error TokenAmountNotEqualToMsgValue(uint256 gotAmount, uint256 msgValue); - error InsufficientMsgValue(uint256 gotAmount, uint256 msgValue); - error InsufficientFee(uint256 gotFee, uint256 fee); - error GasLimitTooLow(uint256 minLimit, uint256 gotLimit); - - string public constant override typeAndVersion = "EtherSenderReceiver 1.5.0"; - - /// @notice The wrapped native token address. - /// @dev If the wrapped native token address changes on the router, this contract will need to be redeployed. - IWrappedNative public immutable i_weth; - - /// @param router The CCIP router address. - constructor(address router) CCIPReceiver(router) { - i_weth = IWrappedNative(CCIPRouter(router).getWrappedNative()); - i_weth.approve(router, type(uint256).max); - } - - /// @notice Need this in order to unwrap correctly. - receive() external payable {} - - /// @notice Get the fee for sending a message to a destination chain. - /// This is mirrored from the router for convenience, construct the appropriate - /// message and get it's fee. - /// @param destinationChainSelector The destination chainSelector - /// @param message The cross-chain CCIP message including data and/or tokens - /// @return fee returns execution fee for the message - /// delivery to destination chain, denominated in the feeToken specified in the message. - /// @dev Reverts with appropriate reason upon invalid message. - function getFee( - uint64 destinationChainSelector, - Client.EVM2AnyMessage calldata message - ) external view returns (uint256 fee) { - Client.EVM2AnyMessage memory validatedMessage = _validatedMessage(message); - - return IRouterClient(getRouter()).getFee(destinationChainSelector, validatedMessage); - } - - /// @notice Send raw native tokens cross-chain. - /// @param destinationChainSelector The destination chain selector. - /// @param message The CCIP message with the following fields correctly set: - /// - bytes receiver: The _contract_ address on the destination chain that will receive the wrapped ether. - /// The caller must ensure that this contract address is correct, otherwise funds may be lost forever. - /// - address feeToken: The fee token address. Must be address(0) for native tokens, or a supported CCIP fee token otherwise (i.e, LINK token). - /// In the event a feeToken is set, we will transferFrom the caller the fee amount before sending the message, in order to forward them to the router. - /// - EVMTokenAmount[] tokenAmounts: The tokenAmounts array must contain a single element with the following fields: - /// - uint256 amount: The amount of ether to send. - /// There are a couple of cases here that depend on the fee token specified: - /// 1. If feeToken == address(0), the fee must be included in msg.value. Therefore tokenAmounts[0].amount must be less than msg.value, - /// and the difference will be used as the fee. - /// 2. If feeToken != address(0), the fee is not included in msg.value, and tokenAmounts[0].amount must be equal to msg.value. - /// these fees to the CCIP router. - /// @return messageId The CCIP message ID. - function ccipSend( - uint64 destinationChainSelector, - Client.EVM2AnyMessage calldata message - ) external payable returns (bytes32) { - _validateFeeToken(message); - Client.EVM2AnyMessage memory validatedMessage = _validatedMessage(message); - - i_weth.deposit{value: validatedMessage.tokenAmounts[0].amount}(); - - uint256 fee = IRouterClient(getRouter()).getFee(destinationChainSelector, validatedMessage); - if (validatedMessage.feeToken != address(0)) { - // If the fee token is not native, we need to transfer the fee to this contract and re-approve it to the router. - // Its not possible to have any leftover tokens in this path because we transferFrom the exact fee that CCIP - // requires from the caller. - IERC20(validatedMessage.feeToken).safeTransferFrom(msg.sender, address(this), fee); - - // We gave an infinite approval of weth to the router in the constructor. - if (validatedMessage.feeToken != address(i_weth)) { - IERC20(validatedMessage.feeToken).approve(getRouter(), fee); - } - - return IRouterClient(getRouter()).ccipSend(destinationChainSelector, validatedMessage); - } - - // We don't want to keep any excess ether in this contract, so we send over the entire address(this).balance as the fee. - // CCIP will revert if the fee is insufficient, so we don't need to check here. - return IRouterClient(getRouter()).ccipSend{value: address(this).balance}(destinationChainSelector, validatedMessage); - } - - /// @notice Validate the message content. - /// @dev Only allows a single token to be sent. Always overwritten to be address(i_weth) - /// and receiver is always msg.sender. - function _validatedMessage(Client.EVM2AnyMessage calldata message) - internal - view - returns (Client.EVM2AnyMessage memory) - { - Client.EVM2AnyMessage memory validatedMessage = message; - - if (validatedMessage.tokenAmounts.length != 1) { - revert InvalidTokenAmounts(validatedMessage.tokenAmounts.length); - } - - validatedMessage.data = abi.encode(msg.sender); - validatedMessage.tokenAmounts[0].token = address(i_weth); - - return validatedMessage; - } - - function _validateFeeToken(Client.EVM2AnyMessage calldata message) internal view { - uint256 tokenAmount = message.tokenAmounts[0].amount; - - if (message.feeToken != address(0)) { - // If the fee token is NOT native, then the token amount must be equal to msg.value. - // This is done to ensure that there is no leftover ether in this contract. - if (msg.value != tokenAmount) { - revert TokenAmountNotEqualToMsgValue(tokenAmount, msg.value); - } - } - } - - /// @notice Receive the wrapped ether, unwrap it, and send it to the specified EOA in the data field. - /// @param message The CCIP message containing the wrapped ether amount and the final receiver. - /// @dev The code below should never revert if the message being is valid according - /// to the above _validatedMessage and _validateFeeToken functions. - function _ccipReceive(Client.Any2EVMMessage memory message) internal override { - address receiver = abi.decode(message.data, (address)); - - if (message.destTokenAmounts.length != 1) { - revert InvalidTokenAmounts(message.destTokenAmounts.length); - } - - if (message.destTokenAmounts[0].token != address(i_weth)) { - revert InvalidToken(message.destTokenAmounts[0].token, address(i_weth)); - } - - uint256 tokenAmount = message.destTokenAmounts[0].amount; - i_weth.withdraw(tokenAmount); - - // it is possible that the below call may fail if receiver.code.length > 0 and the contract - // doesn't e.g have a receive() or a fallback() function. - (bool success,) = payable(receiver).call{value: tokenAmount}(""); - if (!success) { - // We have a few options here: - // 1. Revert: this is bad generally because it may mean that these tokens are stuck. - // 2. Store the tokens in a mapping and allow the user to withdraw them with another tx. - // 3. Send WETH to the receiver address. - // We opt for (3) here because at least the receiver will have the funds and can unwrap them if needed. - // However it is worth noting that if receiver is actually a contract AND the contract _cannot_ withdraw - // the WETH, then the WETH will be stuck in this contract. - i_weth.deposit{value: tokenAmount}(); - i_weth.transfer(receiver, tokenAmount); - } - } -} diff --git a/contracts/src/v0.8/ccip/applications/external/CCIPClient.sol b/contracts/src/v0.8/ccip/applications/external/CCIPClient.sol index 7a90084387..ecd94b89af 100644 --- a/contracts/src/v0.8/ccip/applications/external/CCIPClient.sol +++ b/contracts/src/v0.8/ccip/applications/external/CCIPClient.sol @@ -1,12 +1,12 @@ pragma solidity ^0.8.0; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IRouterClient} from "../../interfaces/IRouterClient.sol"; +import {Client} from "../../libraries/Client.sol"; import {CCIPReceiverWithACK} from "./CCIPReceiverWithACK.sol"; -import {IRouterClient} from "../../interfaces/IRouterClient.sol"; -import {Client} from "../../libraries/Client.sol"; +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; contract CCIPClient is CCIPReceiverWithACK { using SafeERC20 for IERC20; @@ -28,10 +28,10 @@ contract CCIPClient is CCIPReceiverWithACK { address feeToken ) public payable validChain(destChainSelector) returns (bytes32 messageId) { Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: s_chains[destChainSelector], + receiver: s_chains[destChainSelector].recipient, data: data, tokenAmounts: tokenAmounts, - extraArgs: s_extraArgsBytes[destChainSelector], + extraArgs: s_chains[destChainSelector].extraArgsBytes, feeToken: feeToken }); diff --git a/contracts/src/v0.8/ccip/applications/external/CCIPClientBase.sol b/contracts/src/v0.8/ccip/applications/external/CCIPClientBase.sol index 6ace66b358..75dc5f3e42 100644 --- a/contracts/src/v0.8/ccip/applications/external/CCIPClientBase.sol +++ b/contracts/src/v0.8/ccip/applications/external/CCIPClientBase.sol @@ -15,12 +15,22 @@ abstract contract CCIPClientBase is ICCIPClientBase, OwnerIsCreator, ITypeAndVer address internal immutable i_ccipRouter; - mapping(uint64 destChainSelector => mapping(bytes sender => bool approved)) public s_approvedSenders; - mapping(uint64 destChainSelector => bytes recipient) public s_chains; - mapping(uint64 destChainselector => bytes extraArgsBytes) public s_extraArgsBytes; + error ZeroAddressNotAllowed(); + + struct ChainInfo { + bytes recipient; + bytes extraArgsBytes; + mapping(bytes => bool) approvedSender; + } + + mapping(uint64 => ChainInfo) public s_chains; + + // mapping(uint64 => mapping(bytes sender => bool)) public s_approvedSenders; + // mapping(uint64 => bytes) public s_chains; + // mapping(uint64 => bytes) public s_extraArgsBytes; constructor(address router) { - if (router == address(0)) revert InvalidRouter(address(0)); + if (router == address(0)) revert ZeroAddressNotAllowed(); i_ccipRouter = router; } @@ -28,7 +38,7 @@ abstract contract CCIPClientBase is ICCIPClientBase, OwnerIsCreator, ITypeAndVer // │ Router Management │ // ================================================================ - function getRouter() public view returns (address) { + function getRouter() public view virtual returns (address) { return i_ccipRouter; } @@ -47,14 +57,20 @@ abstract contract CCIPClientBase is ICCIPClientBase, OwnerIsCreator, ITypeAndVer approvedSenderUpdate[] calldata removes ) external onlyOwner { for (uint256 i = 0; i < removes.length; ++i) { - delete s_approvedSenders[removes[i].destChainSelector][removes[i].sender]; + // delete s_approvedSenders[removes[i].destChainSelector][removes[i].sender]; + delete s_chains[removes[i].destChainSelector].approvedSender[removes[i].sender]; } for (uint256 i = 0; i < adds.length; ++i) { - s_approvedSenders[adds[i].destChainSelector][adds[i].sender] = true; + // s_approvedSenders[adds[i].destChainSelector][adds[i].sender] = true; + s_chains[adds[i].destChainSelector].approvedSender[adds[i].sender] = true; } } + function isApprovedSender(uint64 sourceChainSelector, bytes calldata senderAddr) external view returns (bool) { + return s_chains[sourceChainSelector].approvedSender[senderAddr]; + } + // ================================================================ // │ Fee Token Management │ // =============================================================== @@ -77,25 +93,26 @@ abstract contract CCIPClientBase is ICCIPClientBase, OwnerIsCreator, ITypeAndVer function enableChain( uint64 chainSelector, bytes calldata recipient, - bytes calldata extraArgsBytes + bytes calldata _extraArgsBytes ) external onlyOwner { - s_chains[chainSelector] = recipient; + s_chains[chainSelector].recipient = recipient; - if (extraArgsBytes.length != 0) s_extraArgsBytes[chainSelector] = extraArgsBytes; + if (_extraArgsBytes.length != 0) s_chains[chainSelector].extraArgsBytes = _extraArgsBytes; } function disableChain(uint64 chainSelector) external onlyOwner { delete s_chains[chainSelector]; - delete s_extraArgsBytes[chainSelector]; + // delete s_extraArgsBytes[chainSelector]; } modifier validChain(uint64 chainSelector) { - if (s_chains[chainSelector].length == 0) revert InvalidChain(chainSelector); + if (s_chains[chainSelector].recipient.length == 0) revert InvalidChain(chainSelector); _; } modifier validSender(uint64 chainSelector, bytes memory sender) { - if (!s_approvedSenders[chainSelector][sender]) revert InvalidSender(sender); + // if (!s_approvedSenders[chainSelector][sender]) revert InvalidSender(sender); + if (!s_chains[chainSelector].approvedSender[sender]) revert InvalidSender(sender); _; } } diff --git a/contracts/src/v0.8/ccip/applications/external/CCIPReceiverWithACK.sol b/contracts/src/v0.8/ccip/applications/external/CCIPReceiverWithACK.sol index 9c35f8ab0a..a1384b2153 100644 --- a/contracts/src/v0.8/ccip/applications/external/CCIPReceiverWithACK.sol +++ b/contracts/src/v0.8/ccip/applications/external/CCIPReceiverWithACK.sol @@ -138,7 +138,7 @@ contract CCIPReceiverWithACK is CCIPReceiver { receiver: incomingMessage.sender, data: abi.encode(ACKMESSAGEMAGICBYTES, incomingMessage.messageId), tokenAmounts: tokenAmounts, - extraArgs: s_extraArgsBytes[incomingMessage.sourceChainSelector], + extraArgs: s_chains[incomingMessage.sourceChainSelector].extraArgsBytes, //s_extraArgsBytes[incomingMessage.sourceChainSelector], feeToken: address(s_feeToken) }); diff --git a/contracts/src/v0.8/ccip/applications/external/CCIPSender.sol b/contracts/src/v0.8/ccip/applications/external/CCIPSender.sol index 2ac119c46c..77c95654bb 100644 --- a/contracts/src/v0.8/ccip/applications/external/CCIPSender.sol +++ b/contracts/src/v0.8/ccip/applications/external/CCIPSender.sol @@ -44,11 +44,11 @@ contract CCIPSender is CCIPClientBase { address feeToken ) public payable validChain(destChainSelector) returns (bytes32 messageId) { Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: s_chains[destChainSelector], + receiver: s_chains[destChainSelector].recipient, data: data, tokenAmounts: tokenAmounts, feeToken: feeToken, - extraArgs: s_extraArgsBytes[destChainSelector] + extraArgs: s_chains[destChainSelector].extraArgsBytes }); uint256 fee = IRouterClient(i_ccipRouter).getFee(destChainSelector, message); diff --git a/contracts/src/v0.8/ccip/applications/internal/PingPongDemo.sol b/contracts/src/v0.8/ccip/applications/internal/PingPongDemo.sol index c9cf40bb68..5bb7914d93 100644 --- a/contracts/src/v0.8/ccip/applications/internal/PingPongDemo.sol +++ b/contracts/src/v0.8/ccip/applications/internal/PingPongDemo.sol @@ -81,10 +81,11 @@ contract PingPongDemo is CCIPClient { s_counterpartAddress = counterpartAddress; // Approve the counterpart contract under validSender - s_approvedSenders[counterpartChainSelector][abi.encode(counterpartAddress)] = true; + // s_approvedSenders[counterpartChainSelector][abi.encode(counterpartAddress)] = true; + s_chains[counterpartChainSelector].approvedSender[abi.encode(counterpartAddress)] = true; // Approve the counterpart Chain selector under validChain - s_chains[counterpartChainSelector] = abi.encode(counterpartAddress); + s_chains[counterpartChainSelector].recipient = abi.encode(counterpartAddress); } function setCounterpartChainSelector(uint64 counterpartChainSelector) external onlyOwner { @@ -94,7 +95,7 @@ contract PingPongDemo is CCIPClient { function setCounterpartAddress(address counterpartAddress) external onlyOwner { s_counterpartAddress = counterpartAddress; - s_chains[s_counterpartChainSelector] = abi.encode(counterpartAddress); + s_chains[s_counterpartChainSelector].recipient = abi.encode(counterpartAddress); } function setPaused(bool pause) external onlyOwner { diff --git a/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol b/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol deleted file mode 100644 index c1ea303d68..0000000000 --- a/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol +++ /dev/null @@ -1,61 +0,0 @@ -pragma solidity ^0.8.0; - -import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; - -import {CCIPClientExample} from "../../applications/CCIPClientExample.sol"; -import {Client} from "../../libraries/Client.sol"; -import {EVM2EVMOnRampSetup} from "../onRamp/EVM2EVMOnRampSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {ERC165Checker} from - "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; - -contract CCIPClientExample_sanity is EVM2EVMOnRampSetup { - function test_Examples() public { - CCIPClientExample exampleContract = new CCIPClientExample(s_sourceRouter, IERC20(s_sourceFeeToken)); - deal(address(exampleContract), 100 ether); - deal(s_sourceFeeToken, address(exampleContract), 100 ether); - - // feeToken approval works - assertEq(IERC20(s_sourceFeeToken).allowance(address(exampleContract), address(s_sourceRouter)), 2 ** 256 - 1); - - // Can set chain - Client.EVMExtraArgsV1 memory extraArgs = Client.EVMExtraArgsV1({gasLimit: 300_000}); - bytes memory encodedExtraArgs = Client._argsToBytes(extraArgs); - exampleContract.enableChain(DEST_CHAIN_SELECTOR, encodedExtraArgs); - assertEq(exampleContract.s_chains(DEST_CHAIN_SELECTOR), encodedExtraArgs); - - address toAddress = address(100); - - // Can send data pay native - exampleContract.sendDataPayNative(DEST_CHAIN_SELECTOR, abi.encode(toAddress), bytes("hello")); - - // Can send data pay feeToken - exampleContract.sendDataPayFeeToken(DEST_CHAIN_SELECTOR, abi.encode(toAddress), bytes("hello")); - - // Can send data tokens - address sourceToken = s_sourceTokens[1]; - assertEq( - address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(sourceToken))), - address(s_sourcePoolByToken[sourceToken]) - ); - deal(sourceToken, OWNER, 100 ether); - IERC20(sourceToken).approve(address(exampleContract), 1 ether); - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: sourceToken, amount: 1 ether}); - exampleContract.sendDataAndTokens(DEST_CHAIN_SELECTOR, abi.encode(toAddress), bytes("hello"), tokenAmounts); - // Tokens transferred from owner to router then burned in pool. - assertEq(IERC20(sourceToken).balanceOf(OWNER), 99 ether); - assertEq(IERC20(sourceToken).balanceOf(address(s_sourceRouter)), 0); - - // Can send just tokens - IERC20(sourceToken).approve(address(exampleContract), 1 ether); - exampleContract.sendTokens(DEST_CHAIN_SELECTOR, abi.encode(toAddress), tokenAmounts); - - // Can receive - assertTrue(ERC165Checker.supportsInterface(address(exampleContract), type(IAny2EVMMessageReceiver).interfaceId)); - - // Can disable chain - exampleContract.disableChain(DEST_CHAIN_SELECTOR); - } -} diff --git a/contracts/src/v0.8/ccip/test/applications/external/CCIPReceiverTest.t.sol b/contracts/src/v0.8/ccip/test/applications/external/CCIPReceiverTest.t.sol index 952fbcc1e4..95037f3359 100644 --- a/contracts/src/v0.8/ccip/test/applications/external/CCIPReceiverTest.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/external/CCIPReceiverTest.t.sol @@ -199,7 +199,8 @@ contract CCIPReceiverTest is EVM2EVMOnRampSetup { s_receiver.updateApprovedSenders(new ICCIPClientBase.approvedSenderUpdate[](0), senderUpdates); - assertFalse(s_receiver.s_approvedSenders(sourceChainSelector, abi.encode(address(s_receiver)))); + // assertFalse(s_receiver.s_approvedSenders(sourceChainSelector, abi.encode(address(s_receiver)))); + assertFalse(s_receiver.isApprovedSender(sourceChainSelector, abi.encode(address(s_receiver)))); bytes32 messageId = keccak256("messageId"); address token = address(s_destFeeToken);