Skip to content

Commit

Permalink
INTAUTO-306 Add ccip message assertions e2e tests (#16107)
Browse files Browse the repository at this point in the history
* Add ccip message received assertion

* lint fixes

* lint fix

* fix unecessary string conversion

* change set and fixes

* update gas snapshot

* Add function comments

* address pr comments

* update snapshot and add minor validation

* add msg data validation
  • Loading branch information
joaoluisam authored Jan 30, 2025
1 parent 9b1fdce commit 6f4af21
Show file tree
Hide file tree
Showing 9 changed files with 630 additions and 86 deletions.
5 changes: 5 additions & 0 deletions contracts/.changeset/smart-bats-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@chainlink/contracts': patch
---

Update mayberevertmessagereceiver contract to emit message received event and allow token withdrawal
88 changes: 44 additions & 44 deletions contracts/gas-snapshots/ccip.gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ CCIPHome_setCandidate:test_setCandidate() (gas: 1365392)
CCIPHome_supportsInterface:test_supportsInterface() (gas: 9885)
DefensiveExampleTest:test_HappyPath() (gas: 200535)
DefensiveExampleTest:test_Recovery() (gas: 424996)
E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1495937)
ERC165CheckerReverting_supportsInterfaceReverting:test__supportsInterfaceReverting() (gas: 10445)
E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1514547)
ERC165CheckerReverting_supportsInterfaceReverting:test__supportsInterfaceReverting() (gas: 10517)
EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96964)
EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49797)
EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17460)
Expand Down Expand Up @@ -203,11 +203,11 @@ NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123617)
NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySet_overrideAllowed() (gas: 45935)
NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66937)
NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12123)
NonceManager_getInboundNonce:test_getInboundNonce_NoPrevOffRampForChain() (gas: 179167)
NonceManager_getInboundNonce:test_getInboundNonce_Upgraded() (gas: 146356)
NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceNewSenderStartsAtZero() (gas: 182637)
NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceStartsAtV1Nonce() (gas: 245611)
NonceManager_getInboundNonce:test_getInboundNonce_UpgradedOffRampNonceSkipsIfMsgInFlight() (gas: 214256)
NonceManager_getInboundNonce:test_getInboundNonce_NoPrevOffRampForChain() (gas: 183777)
NonceManager_getInboundNonce:test_getInboundNonce_Upgraded() (gas: 150965)
NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceNewSenderStartsAtZero() (gas: 187248)
NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceStartsAtV1Nonce() (gas: 254856)
NonceManager_getInboundNonce:test_getInboundNonce_UpgradedOffRampNonceSkipsIfMsgInFlight() (gas: 218870)
NonceManager_getInboundNonce:test_getInboundNonce_UpgradedSenderNoncesReadsPreviousRamp() (gas: 60418)
NonceManager_getIncrementedOutboundNonce:test_getIncrementedOutboundNonce() (gas: 37974)
NonceManager_getIncrementedOutboundNonce:test_incrementInboundNonce() (gas: 38746)
Expand All @@ -225,12 +225,12 @@ OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates() (gas: 16671)
OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain() (gas: 180998)
OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp() (gas: 168513)
OffRamp_applySourceChainConfigUpdates:test_allowNonOnRampUpdateAfterLaneIsUsed() (gas: 284861)
OffRamp_batchExecute:test_MultipleReportsDifferentChains() (gas: 326824)
OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain() (gas: 171115)
OffRamp_batchExecute:test_MultipleReportsSameChain() (gas: 270123)
OffRamp_batchExecute:test_MultipleReportsSkipDuplicate() (gas: 162336)
OffRamp_batchExecute:test_SingleReport() (gas: 149878)
OffRamp_batchExecute:test_Unhealthy() (gas: 533860)
OffRamp_batchExecute:test_MultipleReportsDifferentChains() (gas: 340742)
OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain() (gas: 175741)
OffRamp_batchExecute:test_MultipleReportsSameChain() (gas: 284041)
OffRamp_batchExecute:test_MultipleReportsSkipDuplicate() (gas: 166949)
OffRamp_batchExecute:test_SingleReport() (gas: 154488)
OffRamp_batchExecute:test_Unhealthy() (gas: 546735)
OffRamp_commit:test_OnlyGasPriceUpdates() (gas: 112995)
OffRamp_commit:test_OnlyTokenPriceUpdates() (gas: 112949)
OffRamp_commit:test_PriceSequenceNumberCleared() (gas: 355405)
Expand All @@ -240,52 +240,52 @@ OffRamp_commit:test_RootWithRMNDisabled() (gas: 153873)
OffRamp_commit:test_StaleReportWithRoot() (gas: 232057)
OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot() (gas: 206722)
OffRamp_constructor:test_Constructor() (gas: 6340113)
OffRamp_execute:test_LargeBatch() (gas: 3383493)
OffRamp_execute:test_MultipleReports() (gas: 292253)
OffRamp_execute:test_MultipleReportsWithPartialValidationFailures() (gas: 365622)
OffRamp_execute:test_SingleReport() (gas: 169111)
OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 51610)
OffRamp_execute:test_LargeBatch() (gas: 3537781)
OffRamp_execute:test_MultipleReports() (gas: 306193)
OffRamp_execute:test_MultipleReportsWithPartialValidationFailures() (gas: 370270)
OffRamp_execute:test_SingleReport() (gas: 173724)
OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 55443)
OffRamp_executeSingleMessage:test_executeSingleMessage_NonContract() (gas: 20514)
OffRamp_executeSingleMessage:test_executeSingleMessage_NonContractWithTokens() (gas: 230418)
OffRamp_executeSingleMessage:test_executeSingleMessage_WithMessageInterceptor() (gas: 87465)
OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 259935)
OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 455918)
OffRamp_executeSingleReport:test_ReceiverError() (gas: 181083)
OffRamp_executeSingleReport:test_SingleMessageNoTokens() (gas: 205792)
OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain() (gas: 241879)
OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered() (gas: 185785)
OffRamp_executeSingleMessage:test_executeSingleMessage_WithMessageInterceptor() (gas: 91298)
OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 265210)
OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 462329)
OffRamp_executeSingleReport:test_ReceiverError() (gas: 181094)
OffRamp_executeSingleReport:test_SingleMessageNoTokens() (gas: 215033)
OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain() (gas: 249545)
OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered() (gas: 195030)
OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver() (gas: 244181)
OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 134917)
OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 139526)
OffRamp_executeSingleReport:test_SkippedIncorrectNonce() (gas: 58558)
OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes() (gas: 392884)
OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE() (gas: 562962)
OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 511342)
OffRamp_executeSingleReport:test_Unhealthy() (gas: 529483)
OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain() (gas: 439833)
OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage() (gas: 158559)
OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered() (gas: 128943)
OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes() (gas: 399284)
OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE() (gas: 575811)
OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 524188)
OffRamp_executeSingleReport:test_Unhealthy() (gas: 542355)
OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain() (gas: 450383)
OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage() (gas: 163171)
OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered() (gas: 133556)
OffRamp_getExecutionState:test_FillExecutionState() (gas: 3955662)
OffRamp_getExecutionState:test_GetDifferentChainExecutionState() (gas: 121311)
OffRamp_getExecutionState:test_GetExecutionState() (gas: 90102)
OffRamp_manuallyExecute:test_manuallyExecute() (gas: 212915)
OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched() (gas: 166028)
OffRamp_manuallyExecute:test_manuallyExecute() (gas: 212742)
OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched() (gas: 166042)
OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit() (gas: 479692)
OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2230185)
OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride() (gas: 213465)
OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride() (gas: 735042)
OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages() (gas: 338095)
OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride() (gas: 213292)
OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride() (gas: 753781)
OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages() (gas: 347264)
OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken() (gas: 94629)
OffRamp_releaseOrMintTokens:test_releaseOrMintTokens() (gas: 161157)
OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride() (gas: 163023)
OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals() (gas: 174276)
OffRamp_setDynamicConfig:test_SetDynamicConfig() (gas: 25442)
OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor() (gas: 47493)
OffRamp_trialExecute:test_trialExecute() (gas: 263680)
OffRamp_trialExecute:test_trialExecute() (gas: 268955)
OffRamp_trialExecute:test_trialExecute_RateLimitError() (gas: 120710)
OffRamp_trialExecute:test_trialExecute_RevertsWhen_SenderIsGasEstimator_InsufficientGasForToCompleteTx() (gas: 67132)
OffRamp_trialExecute:test_trialExecute_SenderIsNotGasEstimator_CallWithExactGasReverts() (gas: 24573)
OffRamp_trialExecute:test_trialExecute_TokenHandlingErrorIsCaught() (gas: 131998)
OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 281305)
OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 286580)
OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy() (gas: 245211)
OnRampWithMessageTransformer_executeSingleMessage:test_forwardFromRouter() (gas: 122477)
OnRampWithMessageTransformer_setMessageTransformer:test_setMessageTransformer() (gas: 701204)
Expand Down Expand Up @@ -342,7 +342,7 @@ RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig() (gas: 38645)
RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin:test_registerAccessControlDefaultAdmin() (gas: 130641)
RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin() (gas: 130136)
RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner() (gas: 129941)
Router_applyRampUpdates:test_applyRampUpdates_OffRampUpdatesWithRouting() (gas: 10413055)
Router_applyRampUpdates:test_applyRampUpdates_OffRampUpdatesWithRouting() (gas: 10864375)
Router_applyRampUpdates:test_applyRampUpdates_OnRampDisable() (gas: 56445)
Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 126090)
Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 213515)
Expand All @@ -359,9 +359,9 @@ Router_constructor:test_Constructor() (gas: 13170)
Router_getArmProxy:test_getArmProxy() (gas: 10573)
Router_getFee:test_GetFeeSupportedChain() (gas: 52367)
Router_recoverTokens:test_RecoverTokens() (gas: 52686)
Router_routeMessage:test_routeMessage_AutoExec() (gas: 38071)
Router_routeMessage:test_routeMessage_ExecutionEvent() (gas: 153593)
Router_routeMessage:test_routeMessage_ManualExec() (gas: 31120)
Router_routeMessage:test_routeMessage_AutoExec() (gas: 41832)
Router_routeMessage:test_routeMessage_ExecutionEvent() (gas: 157232)
Router_routeMessage:test_routeMessage_ManualExec() (gas: 34881)
SiloedLockReleaseTokenPool_lockOrBurn:test_lockOrBurn_SiloedFunds() (gas: 76874)
SiloedLockReleaseTokenPool_lockOrBurn:test_lockOrBurn_UnsiloedFunds() (gas: 76104)
SiloedLockReleaseTokenPool_provideLiqudity:test_ProvideLiquidity_LegacyProvideLiquiditySelector() (gas: 91873)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;

import {IERC20} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol";
import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol";
import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol";
import {Client} from "../../../libraries/Client.sol";

import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol";

contract MaybeRevertMessageReceiver is IAny2EVMMessageReceiver, IERC165 {
error ReceiveRevert();
error CustomError(bytes err);
error Unauthorized();
error InsufficientBalance(uint256 available, uint256 required);
error TransferFailed();

event ValueReceived(uint256 amount);
event MessageReceived();
event NativeFundsWithdrawn(address indexed owner, uint256 amount);
event TokensWithdrawn(address indexed token, address indexed owner, uint256 amount);
event MessageReceived(
bytes32 messageId, uint64 sourceChainSelector, bytes sender, bytes data, Client.EVMTokenAmount[] destTokenAmounts
);

address private s_manager;
address private immutable i_manager;
bool public s_toRevert;
bytes private s_err;

constructor(
bool toRevert
) {
s_manager = msg.sender;
i_manager = msg.sender;
s_toRevert = toRevert;
}

modifier onlyManager() {
if (msg.sender != i_manager) {
revert Unauthorized();
}
_;
}

function setRevert(
bool toRevert
) external {
Expand All @@ -46,12 +60,15 @@ contract MaybeRevertMessageReceiver is IAny2EVMMessageReceiver, IERC165 {
}

function ccipReceive(
Client.Any2EVMMessage calldata
Client.Any2EVMMessage calldata message
) external override {
if (s_toRevert) {
revert CustomError(s_err);
}
emit MessageReceived();

emit MessageReceived(
message.messageId, message.sourceChainSelector, message.sender, message.data, message.destTokenAmounts
);
}

// solhint-disable-next-line no-complex-fallback
Expand All @@ -62,4 +79,44 @@ contract MaybeRevertMessageReceiver is IAny2EVMMessageReceiver, IERC165 {

emit ValueReceived(msg.value);
}

/// @notice Allows the manager (deployer) to withdraw all Ether from the contract
function withdrawFunds() external onlyManager {
uint256 balance = address(this).balance;

(bool success,) = i_manager.call{value: balance}("");
if (!success) {
revert TransferFailed();
}

emit NativeFundsWithdrawn(i_manager, balance);
}

/// @notice Allows the manager to withdraw ERC-20 tokens from the contract
/// @param token The address of the ERC-20 token contract
/// @param amount The amount of tokens to withdraw
function withdrawTokens(address token, uint256 amount) external onlyManager {
IERC20 erc20 = IERC20(token);
uint256 balance = erc20.balanceOf(address(this));
if (balance < amount) {
revert InsufficientBalance(balance, amount);
}

bool success = erc20.transfer(i_manager, amount);
if (!success) {
revert TransferFailed();
}

emit TokensWithdrawn(token, i_manager, amount);
}

/// @notice Fetches the balance of an ERC-20 token held by the contract
/// @param token The address of the ERC-20 token contract
/// @return The balance of the specified ERC-20 token
function balanceOfToken(
address token
) external view returns (uint256) {
IERC20 erc20 = IERC20(token);
return erc20.balanceOf(address(this));
}
}
Loading

0 comments on commit 6f4af21

Please sign in to comment.