Skip to content

Commit

Permalink
First commit to new branch after messed up PR
Browse files Browse the repository at this point in the history
  • Loading branch information
jhweintraub committed Jun 21, 2024
1 parent 292ac45 commit 3f3db71
Show file tree
Hide file tree
Showing 2 changed files with 203 additions and 26 deletions.
52 changes: 26 additions & 26 deletions contracts/gas-snapshots/ccip.gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -358,32 +358,32 @@ EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17096)
EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153464)
EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5491136)
EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144220)
EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21485)
EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36464)
EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51767)
EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 474062)
EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 46423)
EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152496)
EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 101289)
EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 165140)
EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 177988)
EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 41295)
EVM2EVMOffRamp_execute:test_RouterYULCall_Revert() (gas: 402660)
EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 159781)
EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 175004)
EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 248776)
EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 115214)
EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 409600)
EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54216)
EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 132270)
EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52165)
EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 560816)
EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 500116)
EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35486)
EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 548791)
EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64049)
EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 123455)
EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 143607)
EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21459)
EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36556)
EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51824)
EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 474330)
EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 46537)
EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152576)
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_SingleMessageNoTokensUnordered_Success() (gas: 160103)
EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 175334)
EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 248878)
EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 115349)
EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 409892)
EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54296)
EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 132420)
EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52323)
EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 561156)
EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 500392)
EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35556)
EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 549423)
EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64168)
EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 123671)
EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 143834)
EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20615)
EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 282106)
EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20264)
Expand Down
177 changes: 177 additions & 0 deletions contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRamp.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {IPoolV1} from "../../interfaces/IPool.sol";
import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol";

import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol";

import {GenericReceiver} from "../../../shared/test/testhelpers/GenericReceiver.sol";
import {AggregateRateLimiter} from "../../AggregateRateLimiter.sol";
import {RMN} from "../../RMN.sol";
import {Router} from "../../Router.sol";
Expand Down Expand Up @@ -188,6 +190,125 @@ contract EVM2EVMOffRamp_ccipReceive is EVM2EVMOffRampSetup {
contract EVM2EVMOffRamp_execute is EVM2EVMOffRampSetup {
error PausedError();

function _generateMsgWithoutTokens(
uint256 gasLimit,
bytes memory messageData
) internal view returns (Internal.EVM2EVMMessage memory) {
Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageNoTokens(1);
message.gasLimit = gasLimit;
message.data = messageData;
message.messageId = Internal._hash(
message,
keccak256(
abi.encode(Internal.EVM_2_EVM_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, DEST_CHAIN_SELECTOR, ON_RAMP_ADDRESS)
)
);
return message;
}

function test_Fuzz_trialExecuteWithoutTokens_Success(bytes4 funcSelector, bytes memory messageData) public {
vm.assume(
funcSelector != GenericReceiver.setRevert.selector && funcSelector != GenericReceiver.setErr.selector
&& funcSelector != 0x5100fc21 && funcSelector != 0x00000000 // s_toRevert(), which is public and therefore has a function selector
);

// Convert bytes4 into bytes memory to use in the message
Internal.EVM2EVMMessage memory message = _generateMsgWithoutTokens(GAS_LIMIT, messageData);

// Convert an Internal.EVM2EVMMessage into a Client.Any2EVMMessage digestable by the client
Client.Any2EVMMessage memory receivedMessage = _convertToGeneralMessage(message);
bytes memory expectedCallData =
abi.encodeWithSelector(MaybeRevertMessageReceiver.ccipReceive.selector, receivedMessage);

vm.expectCall(address(s_receiver), expectedCallData);
(Internal.MessageExecutionState newState, bytes memory err) =
s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length));
assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState));
assertEq("", err);
}

function test_Fuzz_trialExecuteWithTokens_Success(uint16 tokenAmount, bytes calldata messageData) public {
vm.assume(tokenAmount != 0);

uint256[] memory amounts = new uint256[](2);
amounts[0] = uint256(tokenAmount);
amounts[1] = uint256(tokenAmount);

Internal.EVM2EVMMessage memory message = _generateAny2EVMMessageWithTokens(1, amounts);
// console.log(message.length);
message.data = messageData;

IERC20 dstToken0 = IERC20(s_destTokens[0]);
uint256 startingBalance = dstToken0.balanceOf(message.receiver);

vm.expectCall(s_destTokens[0], abi.encodeWithSelector(IERC20.transfer.selector, address(s_receiver), amounts[0]));

(Internal.MessageExecutionState newState, bytes memory err) =
s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length));
assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState));
assertEq("", err);

// Check that the tokens were transferred
assertEq(startingBalance + amounts[0], dstToken0.balanceOf(message.receiver));
}

function test_Fuzz_getSenderNonce(uint8 trialExecutions) public {
vm.assume(trialExecutions > 1);

Internal.EVM2EVMMessage[] memory messages;

if (trialExecutions == 1) {
messages = new Internal.EVM2EVMMessage[](1);
messages[0] = _generateAny2EVMMessageNoTokens(0);
} else {
messages = _generateSingleBasicMessage();
}

// Fuzz the number of calls from the sender to ensure that getSenderNonce works
for (uint256 i = 1; i < trialExecutions; ++i) {
s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0));

messages[0].nonce++;
messages[0].sequenceNumber++;
messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash());
}

messages[0].nonce = 0;
messages[0].sequenceNumber = 0;
messages[0].messageId = Internal._hash(messages[0], s_offRamp.metadataHash());
s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0));

uint64 nonceBefore = s_offRamp.getSenderNonce(messages[0].sender);
s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0));
assertEq(s_offRamp.getSenderNonce(messages[0].sender), nonceBefore, "sender nonce is not as expected");
}

function test_Fuzz_getSenderNonceWithPrevOffRamp_Success(uint8 trialExecutions) public {
vm.assume(trialExecutions > 1);
// Fuzz a random nonce for getSenderNonce
test_Fuzz_getSenderNonce(trialExecutions);

address prevOffRamp = address(s_offRamp);
deployOffRamp(s_mockCommitStore, s_destRouter, prevOffRamp);

// Make sure the off-ramp address has changed by querying the static config
assertNotEq(address(s_offRamp), prevOffRamp);
EVM2EVMOffRamp.StaticConfig memory staticConfig = s_offRamp.getStaticConfig();
assertEq(staticConfig.prevOffRamp, prevOffRamp, "Previous offRamp does not match expected address");

// Since i_prevOffRamp != address(0) and senderNonce == 0, there should be a call to the previous offRamp
vm.expectCall(prevOffRamp, abi.encodeWithSelector(s_offRamp.getSenderNonce.selector, OWNER));
uint256 currentSenderNonce = s_offRamp.getSenderNonce(OWNER);
assertNotEq(currentSenderNonce, 0, "Sender nonce should not be zero");
assertEq(currentSenderNonce, trialExecutions - 1, "Sender Nonce does not match expected trial executions");

Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage();
s_offRamp.execute(_generateReportFromMessages(messages), new uint256[](0));

currentSenderNonce = s_offRamp.getSenderNonce(OWNER);
assertEq(currentSenderNonce, trialExecutions - 1, "Sender Nonce on new offramp does not match expected executions");
}

function test_SingleMessageNoTokens_Success() public {
Internal.EVM2EVMMessage[] memory messages = _generateSingleBasicMessage();
vm.expectEmit();
Expand Down Expand Up @@ -1797,6 +1918,62 @@ contract EVM2EVMOffRamp_updateRateLimitTokens is EVM2EVMOffRampSetup {
assertEq(adds[1].destToken, destTokens[0]);
}

function test_Fuzz_UpdateRateLimitTokens(uint8 numTokens) public {
// Needs to be more than 1 so that the division doesn't round down and the even makes the comparisons simpler
vm.assume(numTokens > 1 && numTokens % 2 == 0);

// Clear the Rate limit tokens array so the test can start from a baseline
(address[] memory sourceTokens, address[] memory destTokens) = s_offRamp.getAllRateLimitTokens();
EVM2EVMOffRamp.RateLimitToken[] memory removes = new EVM2EVMOffRamp.RateLimitToken[](sourceTokens.length);
for (uint256 x = 0; x < removes.length; x++) {
removes[x] = EVM2EVMOffRamp.RateLimitToken({sourceToken: sourceTokens[x], destToken: destTokens[x]});
}
s_offRamp.updateRateLimitTokens(removes, new EVM2EVMOffRamp.RateLimitToken[](0));

// Sanity check that the rateLimitTokens were successfully cleared
(sourceTokens, destTokens) = s_offRamp.getAllRateLimitTokens();
assertEq(sourceTokens.length, 0, "sourceTokenLength should be zero");

EVM2EVMOffRamp.RateLimitToken[] memory adds = new EVM2EVMOffRamp.RateLimitToken[](numTokens);

for (uint256 x = 0; x < numTokens; x++) {
address tokenAddr = vm.addr(x + 1);

// Create an array of several fake tokens to add which are deployed on the same address on both chains for simplicity
adds[x] = EVM2EVMOffRamp.RateLimitToken({sourceToken: tokenAddr, destToken: tokenAddr});
}

// Attempt to add the tokens to the RateLimitToken Array
s_offRamp.updateRateLimitTokens(new EVM2EVMOffRamp.RateLimitToken[](0), adds);

// Retrieve them from storage and make sure that they all match the expected adds
(sourceTokens, destTokens) = s_offRamp.getAllRateLimitTokens();

for (uint256 x = 0; x < sourceTokens.length; x++) {
// Check that the tokens match the ones we generated earlier
assertEq(sourceTokens[x], adds[x].sourceToken, "Source token doesn't match add");
assertEq(destTokens[x], adds[x].sourceToken, "dest Token doesn't match add");
}

// Attempt to remove half of the numTokens by removing the second half of the list and copying it to a removes array
removes = new EVM2EVMOffRamp.RateLimitToken[](adds.length / 2);

for (uint256 x = 0; x < adds.length / 2; x++) {
removes[x] = adds[x + (adds.length / 2)];
}

// Attempt to update again, this time adding nothing and removing the second half of the tokens
s_offRamp.updateRateLimitTokens(removes, new EVM2EVMOffRamp.RateLimitToken[](0));

(sourceTokens, destTokens) = s_offRamp.getAllRateLimitTokens();
assertEq(sourceTokens.length, adds.length / 2, "Current Rate limit token length is not half of the original adds");
for (uint256 x = 0; x < sourceTokens.length; x++) {
// Check that the tokens match the ones we generated earlier and didn't remove in the previous step
assertEq(sourceTokens[x], adds[x].sourceToken, "Source token doesn't match add after removes");
assertEq(destTokens[x], adds[x].destToken, "dest Token doesn't match add after removes");
}
}

// Reverts

function test_updateRateLimitTokens_NonOwner_Revert() public {
Expand Down

0 comments on commit 3f3db71

Please sign in to comment.