Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manual-execute-gas-overrides #1256

Merged
merged 66 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
da2b0b9
feat: CCIP-2910 manual overrides for destGasAmount in manualExecution
Aug 5, 2024
09719c0
Merge da2b0b98fd52a8454381e191a0eecba7bd98fa83 into acb585270e15a6cc2…
defistar Aug 5, 2024
db6de00
Update gethwrappers
app-token-issuer-infra-releng[bot] Aug 5, 2024
449a3b3
feat: CCIP-2910 EVM2EVMOffRamp contract test refactoring and fixes
Aug 5, 2024
fef0df1
fix: CCIP-2910 minor fix for EVM2EVMOffRamp contract with prettier ch…
Aug 5, 2024
641d29e
fix: CCIP-2910 forge formatting fixes for EVM2EVMOffRamp contracts
Aug 5, 2024
5c8b538
fix: CCIP-2910 fix EVM2EVMOffRamp tests
Aug 5, 2024
e8763c5
Merge 5c8b5386126a5b5d35168b942f5a30c26ad8ceb8 into acb585270e15a6cc2…
defistar Aug 5, 2024
7ffcd20
Update gethwrappers
app-token-issuer-infra-releng[bot] Aug 5, 2024
dbccb54
fix: CCIP-2910 solidity forge formatting updates
Aug 5, 2024
ddb384a
fix: CCIP-2910 gas-snapshot updated for EVM2EVMOffRamp
Aug 5, 2024
34efe99
fix: CCIP-2910 gas-snapshot updated for EVM2EVMOffRamp
Aug 5, 2024
fea911a
fix: CCIP-2910 ccip_contracts fix for gasLimitOverrides struct update…
Aug 5, 2024
dad0478
Merge branch 'ccip-develop' into feature/CCIP-2910-manual-execute-gas…
defistar Aug 5, 2024
339ab36
feat: CCIP-2910 offchain service markers for manuallyExecute script c…
Aug 5, 2024
12db93e
feat: CCIP-2910 manualExecution signature changes in offchain script …
Aug 5, 2024
09d0248
fix: CCIP-2950 fix ManuallyExecute testHelper
Aug 5, 2024
b2bbe11
Merge branch 'ccip-develop' into feature/CCIP-2910-manual-execute-gas…
defistar Aug 5, 2024
7356a8e
chore: mockery interface fix, run make generate
0xsuryansh Aug 5, 2024
fb7d2b3
Merge branch 'ccip-develop' into feature/CCIP-2910-manual-execute-gas…
0xsuryansh Aug 5, 2024
ad0aba6
fix: trial fix for smoke tests
0xsuryansh Aug 5, 2024
d21ec9e
Merge branch 'ccip-develop' into feature/CCIP-2910-manual-execute-gas…
defistar Aug 6, 2024
c4d19cc
fix: CCIP-2950 manuallyExecute Args will override the default destGas…
Aug 6, 2024
cd3c1a2
Gas golf for manual exec (#1262)
RensR Aug 6, 2024
84402a9
Merge branch 'ccip-develop' into feature/CCIP-2910-manual-execute-gas…
defistar Aug 6, 2024
931d5c9
Merge 84402a93f20411f97993f20124f0921eca76c7ef into dc33de84cbc4f9741…
defistar Aug 6, 2024
30b37ec
Update gethwrappers
app-token-issuer-infra-releng[bot] Aug 6, 2024
5160115
fix: CCIP-2950 code review feedback changes for EVM2EVMOfframp contra…
Aug 7, 2024
7028235
fix: CCIP-2950 formatting error fixes for EVM2EVMOfframpSetup
Aug 7, 2024
3891da0
Merge branch 'ccip-develop' into feature/CCIP-2910-manual-execute-gas…
defistar Aug 7, 2024
d187fe5
fix: CCIP-2950 gasLimitOverride fixes for tests
Aug 7, 2024
48d3566
Merge d187fe5daa3db27688c889d32245b83f61ae6021 into 2707bd001a0424ece…
defistar Aug 7, 2024
64cb4cb
Update gethwrappers
app-token-issuer-infra-releng[bot] Aug 7, 2024
099a789
fix: CCIP-2950 ManuallyExecute gasLimit-override failure test cases
Aug 7, 2024
3a31c8d
Merge 099a7895080b4c966074f747a16cf8d961226a07 into 2707bd001a0424ece…
defistar Aug 7, 2024
6177ab9
Update gethwrappers
app-token-issuer-infra-releng[bot] Aug 7, 2024
55d2894
fix: CCIP-2950 gassnapshots fixes after EVM2EVMOffRamp contract enhan…
Aug 7, 2024
0364e3a
fix: CCIP-2950 gassnapshots fixes after EVM2EVMOffRamp contract enhan…
Aug 7, 2024
9da075a
fix: CCIP-2950 gassnapshots fixes after EVM2EVMOffRamp contract enhan…
Aug 7, 2024
c827fd4
fix: CCIP-2950 rename EVM2EVMOffRamp Override struct - destGasAmount …
Aug 7, 2024
21e70e1
fix: CCIP-2950 solidity forge formatting fixes
Aug 7, 2024
411c66b
Merge 21e70e175187c09228b91f0a33410bee66b5f54e into 2707bd001a0424ece…
defistar Aug 7, 2024
6849697
Update gethwrappers
app-token-issuer-infra-releng[bot] Aug 7, 2024
74ab3e8
fix: CCIP-2950 gassnapshot fixes for EVM2EVMOfframp
Aug 7, 2024
1deda6d
chore: update mocks and gas snapshot
0xsuryansh Aug 7, 2024
f26d0fc
fix: CCIP-2950 rename offchain gas-override properties for EVM2EVMoff…
Aug 8, 2024
086778c
Merge branch 'ccip-develop' into feature/CCIP-2910-manual-execute-gas…
defistar Aug 8, 2024
e5c96c4
fix: CCIP-2950 gassnapshot fixes and formatting error fixes
Aug 8, 2024
42a4adc
fix: CCIP-2950 optimise EVM2EVMOfframp contract and gassnapshot corre…
Aug 8, 2024
5bc5f42
Merge 42a4adc46658cc3e3dcc2df627d24c7625f8f696 into 5f1b30e0d37cac094…
defistar Aug 8, 2024
803235f
Update gethwrappers
app-token-issuer-infra-releng[bot] Aug 8, 2024
a48f15f
fix: CCIP-2950 update gasOverride dataType to uint32 and related test…
Aug 8, 2024
d9793ed
fix: CCIP-2950 wrappers regenerated after datatype of tokenGasOverrid…
Aug 8, 2024
c18a87f
fix: CCIP-2950 offchain datatype fixes for ccip_contracts
Aug 8, 2024
1a10b1d
fix: CCIP-2950 gassnapshot and contract formatting fixes
Aug 8, 2024
4b76aad
Merge branch 'ccip-develop' into feature/CCIP-2910-manual-execute-gas…
defistar Aug 8, 2024
c1258c5
chore: update gas snapshot and mock
0xsuryansh Aug 8, 2024
2a10db1
fix: CCIP-2950 ccip_contracts linting error fixes
Aug 8, 2024
9542dca
Merge branch 'ccip-develop' into feature/CCIP-2910-manual-execute-gas…
defistar Aug 8, 2024
20dcec5
index on feature/CCIP-2910-manual-execute-gas-overrides: 55d2894595 f…
Aug 7, 2024
2d56bad
fix: CCIP-2950 gas-snapshot fixes after merge resolution
Aug 8, 2024
666f38e
rm compile all comment
RensR Aug 9, 2024
09a960c
add msg id to revert reason
RensR Aug 9, 2024
40200c6
Merge branch 'ccip-develop' into feature/CCIP-2910-manual-execute-gas…
RensR Aug 9, 2024
bae670c
add comments
RensR Aug 9, 2024
18bafa2
fix comments, rename, minor gas improvement
RensR Aug 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 96 additions & 90 deletions contracts/gas-snapshots/ccip.gas-snapshot

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contracts/scripts/native_solc_compile_all_ccip
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ echo " └───────────────────────

SOLC_VERSION="0.8.24"
OPTIMIZE_RUNS=26000
OPTIMIZE_RUNS_OFFRAMP=22000
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed due to space issues

OPTIMIZE_RUNS_OFFRAMP=18000
OPTIMIZE_RUNS_ONRAMP=4100
OPTIMIZE_RUNS_MULTI_OFFRAMP=2000

Expand Down
95 changes: 77 additions & 18 deletions contracts/src/v0.8/ccip/offRamp/EVM2EVMOffRamp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersio
error UnsupportedNumberOfTokens(uint64 sequenceNumber);
error ManualExecutionNotYetEnabled();
error ManualExecutionGasLimitMismatch();
error InvalidManualExecutionGasLimit(uint256 index, uint256 newLimit);
error DestinationGasAmountCountMismatch(bytes32 messageId, uint64 sequenceNumber);
error InvalidManualExecutionGasLimit(bytes32 messageId, uint256 oldLimit, uint256 newLimit);
error InvalidTokenGasOverride(bytes32 messageId, uint256 tokenIndex, uint256 oldLimit, uint256 tokenGasOverride);
error RootNotCommitted();
error CanOnlySelfCall();
error ReceiverError(bytes err);
Expand Down Expand Up @@ -100,6 +102,15 @@ contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersio
address destToken;
}

/// @notice Gas overrides for manual exec, the number of token overrides must match the number of tokens in the msg.
struct GasLimitOverride {
/// @notice Overrides EVM2EVMMessage.gasLimit. A value of zero indicates no override and is valid.
uint256 receiverExecutionGasLimit;
/// @notice Overrides EVM2EVMMessage.sourceTokenData.destGasAmount. Must be same length as tokenAmounts. A value
/// of zero indicates no override and is valid.
uint32[] tokenGasOverrides;
}
RayXpub marked this conversation as resolved.
Show resolved Hide resolved

// STATIC CONFIG
string public constant override typeAndVersion = "EVM2EVMOffRamp 1.5.0-dev";

Expand Down Expand Up @@ -218,18 +229,44 @@ contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersio
/// @param gasLimitOverrides New gasLimit for each message in the report.
/// @dev We permit gas limit overrides so that users may manually execute messages which failed due to
/// insufficient gas provided.
function manuallyExecute(Internal.ExecutionReport memory report, uint256[] memory gasLimitOverrides) external {
function manuallyExecute(
Internal.ExecutionReport memory report,
GasLimitOverride[] memory gasLimitOverrides
) external {
// We do this here because the other _execute path is already covered OCR2BaseXXX.
_checkChainForked();

uint256 numMsgs = report.messages.length;
if (numMsgs != gasLimitOverrides.length) revert ManualExecutionGasLimitMismatch();
for (uint256 i = 0; i < numMsgs; ++i) {
uint256 newLimit = gasLimitOverrides[i];
Internal.EVM2EVMMessage memory message = report.messages[i];
GasLimitOverride memory gasLimitOverride = gasLimitOverrides[i];

uint256 newLimit = gasLimitOverride.receiverExecutionGasLimit;
// Checks to ensure message cannot be executed with less gas than specified.
if (newLimit != 0) {
if (newLimit < report.messages[i].gasLimit) {
revert InvalidManualExecutionGasLimit(i, newLimit);
if (newLimit < message.gasLimit) {
revert InvalidManualExecutionGasLimit(message.messageId, message.gasLimit, newLimit);
}
}

if (message.tokenAmounts.length != gasLimitOverride.tokenGasOverrides.length) {
revert DestinationGasAmountCountMismatch(message.messageId, message.sequenceNumber);
}

bytes[] memory encodedSourceTokenData = message.sourceTokenData;

for (uint256 j = 0; j < message.tokenAmounts.length; ++j) {
Internal.SourceTokenData memory sourceTokenData =
abi.decode(encodedSourceTokenData[i], (Internal.SourceTokenData));
uint256 tokenGasOverride = gasLimitOverride.tokenGasOverrides[j];

// The gas limit can not be lowered as that could cause the message to fail. If manual execution is done
// from an UNTOUCHED state and we would allow lower gas limit, anyone could grief by executing the message with
// lower gas limit than the DON would have used. This results in the message being marked FAILURE and the DON
// would not attempt it with the correct gas limit.
if (tokenGasOverride != 0 && tokenGasOverride < sourceTokenData.destGasAmount) {
revert InvalidTokenGasOverride(message.messageId, j, sourceTokenData.destGasAmount, tokenGasOverride);
}
}
}
Expand All @@ -239,16 +276,17 @@ contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersio

/// @notice Entrypoint for execution, called by the OCR network
/// @dev Expects an encoded ExecutionReport
/// @dev Supplies no GasLimitOverrides as the DON will only execute with the original gas limits.
function _report(bytes calldata report) internal override {
_execute(abi.decode(report, (Internal.ExecutionReport)), new uint256[](0));
_execute(abi.decode(report, (Internal.ExecutionReport)), new GasLimitOverride[](0));
}

/// @notice Executes a report, executing each message in order.
/// @param report The execution report containing the messages and proofs.
/// @param manualExecGasLimits An array of gas limits to use for manual execution.
/// @param manualExecGasOverrides An array of gas limits to use for manual execution.
/// @dev If called from the DON, this array is always empty.
/// @dev If called from manual execution, this array is always same length as messages.
function _execute(Internal.ExecutionReport memory report, uint256[] memory manualExecGasLimits) internal {
function _execute(Internal.ExecutionReport memory report, GasLimitOverride[] memory manualExecGasOverrides) internal {
if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(i_sourceChainSelector)))) revert CursedByRMN();

uint256 numMsgs = report.messages.length;
Expand All @@ -267,13 +305,13 @@ contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersio
// a message with an unexpected hash.
if (hashedLeaves[i] != message.messageId) revert InvalidMessageId();
}
bool manualExecution = manualExecGasOverrides.length != 0;

// SECURITY CRITICAL CHECK
uint256 timestampCommitted = ICommitStore(i_commitStore).verify(hashedLeaves, report.proofs, report.proofFlagBits);
if (timestampCommitted == 0) revert RootNotCommitted();

// Execute messages
bool manualExecution = manualExecGasLimits.length != 0;
for (uint256 i = 0; i < numMsgs; ++i) {
Internal.EVM2EVMMessage memory message = report.messages[i];
Internal.MessageExecutionState originalState = getExecutionState(message.sequenceNumber);
Expand All @@ -292,8 +330,10 @@ contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersio
emit SkippedAlreadyExecutedMessage(message.sequenceNumber);
continue;
}
uint32[] memory tokenGasOverrides;

if (manualExecution) {
tokenGasOverrides = manualExecGasOverrides[i].tokenGasOverrides;
bool isOldCommitReport =
(block.timestamp - timestampCommitted) > s_dynamicConfig.permissionLessExecutionThresholdSeconds;
// Manually execution is fine if we previously failed or if the commit report is just too old
Expand All @@ -303,8 +343,8 @@ contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersio
}

// Manual execution gas limit can override gas limit specified in the message. Value of 0 indicates no override.
if (manualExecGasLimits[i] != 0) {
message.gasLimit = manualExecGasLimits[i];
if (manualExecGasOverrides[i].receiverExecutionGasLimit != 0) {
message.gasLimit = manualExecGasOverrides[i].receiverExecutionGasLimit;
}
} else {
// DON can only execute a message once
Expand Down Expand Up @@ -361,7 +401,8 @@ contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersio
);

_setExecutionState(message.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS);
(Internal.MessageExecutionState newState, bytes memory returnData) = _trialExecute(message, offchainTokenData);
(Internal.MessageExecutionState newState, bytes memory returnData) =
_trialExecute(message, offchainTokenData, tokenGasOverrides);
_setExecutionState(message.sequenceNumber, newState);

// Since it's hard to estimate whether manual execution will succeed, we
Expand Down Expand Up @@ -432,9 +473,10 @@ contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersio
/// @return revert data in bytes if CCIP receiver reverted during execution.
function _trialExecute(
Internal.EVM2EVMMessage memory message,
bytes[] memory offchainTokenData
bytes[] memory offchainTokenData,
uint32[] memory tokenGasOverrides
) internal returns (Internal.MessageExecutionState, bytes memory) {
try this.executeSingleMessage(message, offchainTokenData) {}
try this.executeSingleMessage(message, offchainTokenData, tokenGasOverrides) {}
catch (bytes memory err) {
// return the message execution state as FAILURE and the revert data
// Max length of revert data is Router.MAX_RET_BYTES, max length of err is 4 + Router.MAX_RET_BYTES
Expand All @@ -451,12 +493,21 @@ contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersio
/// its execution and enforce atomicity among successful message processing and token transfer.
/// @dev We use ERC-165 to check for the ccipReceive interface to permit sending tokens to contracts
/// (for example smart contract wallets) without an associated message.
function executeSingleMessage(Internal.EVM2EVMMessage calldata message, bytes[] calldata offchainTokenData) external {
function executeSingleMessage(
Internal.EVM2EVMMessage calldata message,
bytes[] calldata offchainTokenData,
uint32[] memory tokenGasOverrides
) external {
if (msg.sender != address(this)) revert CanOnlySelfCall();
Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](0);
if (message.tokenAmounts.length > 0) {
destTokenAmounts = _releaseOrMintTokens(
message.tokenAmounts, abi.encode(message.sender), message.receiver, message.sourceTokenData, offchainTokenData
message.tokenAmounts,
abi.encode(message.sender),
message.receiver,
message.sourceTokenData,
offchainTokenData,
tokenGasOverrides
);
}
// There are three cases in which we skip calling the receiver:
Expand Down Expand Up @@ -701,19 +752,27 @@ contract EVM2EVMOffRamp is IAny2EVMOffRamp, AggregateRateLimiter, ITypeAndVersio
bytes memory originalSender,
address receiver,
bytes[] calldata encodedSourceTokenData,
bytes[] calldata offchainTokenData
bytes[] calldata offchainTokenData,
uint32[] memory tokenGasOverrides
) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) {
// Creating a copy is more gas efficient than initializing a new array.
destTokenAmounts = sourceTokenAmounts;
uint256 value = 0;
for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) {
Internal.SourceTokenData memory sourceTokenData =
abi.decode(encodedSourceTokenData[i], (Internal.SourceTokenData));
if (tokenGasOverrides.length != 0) {
if (tokenGasOverrides[i] != 0) {
sourceTokenData.destGasAmount = tokenGasOverrides[i];
}
}
destTokenAmounts[i] = _releaseOrMintToken(
sourceTokenAmounts[i].amount,
originalSender,
receiver,
// This should never revert as the onRamp encodes the sourceTokenData struct. Only the inner components from
// this struct come from untrusted sources.
abi.decode(encodedSourceTokenData[i], (Internal.SourceTokenData)),
sourceTokenData,
offchainTokenData[i]
);

Expand Down
24 changes: 18 additions & 6 deletions contracts/src/v0.8/ccip/test/NonceManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,9 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup {
_generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1);
uint64 startNonceChain3 =
s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(messages[0].sender));
s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0));
s_prevOffRamp.execute(
_generateSingleLaneRampReportFromMessages(messages), new EVM2EVMOffRampHelper.GasLimitOverride[](0)
);

// Nonce unchanged for chain 3
assertEq(
Expand Down Expand Up @@ -446,7 +448,9 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup {
uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender));

for (uint64 i = 1; i < 4; ++i) {
s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0));
s_prevOffRamp.execute(
_generateSingleLaneRampReportFromMessages(messages), new EVM2EVMOffRampHelper.GasLimitOverride[](0)
);

// messages contains a single message - update for the next execution
messages[0].nonce++;
Expand All @@ -465,7 +469,9 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup {
uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_2, abi.encode(messages[0].sender));

for (uint64 i = 1; i < 4; ++i) {
s_nestedPrevOffRamps[0].execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0));
s_nestedPrevOffRamps[0].execute(
_generateSingleLaneRampReportFromMessages(messages), new EVM2EVMOffRampHelper.GasLimitOverride[](0)
);

// messages contains a single message - update for the next execution
messages[0].nonce++;
Expand All @@ -484,7 +490,9 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup {
_generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1);

uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender));
s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0));
s_prevOffRamp.execute(
_generateSingleLaneRampReportFromMessages(messages), new EVM2EVMOffRampHelper.GasLimitOverride[](0)
);

assertEq(
startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messages[0].sender))
Expand Down Expand Up @@ -537,7 +545,9 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup {
Internal.EVM2EVMMessage[] memory messages =
_generateSingleLaneSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, SINGLE_LANE_ON_RAMP_ADDRESS_1);

s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messages), new uint256[](0));
s_prevOffRamp.execute(
_generateSingleLaneRampReportFromMessages(messages), new EVM2EVMOffRampHelper.GasLimitOverride[](0)
);

Internal.Any2EVMRampMessage[] memory messagesMultiRamp =
_generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1);
Expand Down Expand Up @@ -589,7 +599,9 @@ contract NonceManager_OffRampUpgrade is EVM2EVMMultiOffRampSetup {
messagesSingleLane[0].messageId = Internal._hash(messagesSingleLane[0], s_prevOffRamp.metadataHash());

// previous offramp executes msg and increases nonce
s_prevOffRamp.execute(_generateSingleLaneRampReportFromMessages(messagesSingleLane), new uint256[](0));
s_prevOffRamp.execute(
_generateSingleLaneRampReportFromMessages(messagesSingleLane), new EVM2EVMOffRampHelper.GasLimitOverride[](0)
);
assertEq(
startNonce + 1,
s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(messagesSingleLane[0].sender))
Expand Down
2 changes: 1 addition & 1 deletion contracts/src/v0.8/ccip/test/e2e/End2End.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ contract E2E is EVM2EVMOnRampSetup, CommitStoreSetup, EVM2EVMOffRampSetup {

Internal.ExecutionReport memory execReport = _generateReportFromMessages(messages);
vm.resumeGasMetering();
s_offRamp.execute(execReport, new uint256[](0));
s_offRamp.execute(execReport, new EVM2EVMOffRamp.GasLimitOverride[](0));
}

function sendRequest(uint64 expectedSeqNum) public returns (Internal.EVM2EVMMessage memory) {
Expand Down
16 changes: 10 additions & 6 deletions contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,28 @@ contract EVM2EVMOffRampHelper is EVM2EVMOffRamp, IgnoreContractSize {
bytes calldata originalSender,
address receiver,
bytes[] calldata sourceTokenData,
bytes[] calldata offchainTokenData
bytes[] calldata offchainTokenData,
uint32[] memory tokenGasOverrides
) external returns (Client.EVMTokenAmount[] memory) {
return _releaseOrMintTokens(sourceTokenAmounts, originalSender, receiver, sourceTokenData, offchainTokenData);
return _releaseOrMintTokens(
sourceTokenAmounts, originalSender, receiver, sourceTokenData, offchainTokenData, tokenGasOverrides
);
}

function trialExecute(
Internal.EVM2EVMMessage memory message,
bytes[] memory offchainTokenData
bytes[] memory offchainTokenData,
uint32[] memory tokenGasOverrides
) external returns (Internal.MessageExecutionState, bytes memory) {
return _trialExecute(message, offchainTokenData);
return _trialExecute(message, offchainTokenData, tokenGasOverrides);
}

function report(bytes calldata executableMessages) external {
_report(executableMessages);
}

function execute(Internal.ExecutionReport memory rep, uint256[] memory manualExecGasLimits) external {
_execute(rep, manualExecGasLimits);
function execute(Internal.ExecutionReport memory rep, GasLimitOverride[] memory gasLimitOverrides) external {
_execute(rep, gasLimitOverrides);
}

function metadataHash() external view returns (bytes32) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {EVM2EVMOffRamp} from "../../../offRamp/EVM2EVMOffRamp.sol";
contract ReentrancyAbuser is CCIPReceiver {
event ReentrancySucceeded();

uint32 internal constant DEFAULT_TOKEN_DEST_GAS_OVERHEAD = 144_000;

bool internal s_ReentrancyDone = false;
Internal.ExecutionReport internal s_payload;
EVM2EVMOffRamp internal s_offRamp;
Expand All @@ -23,11 +25,7 @@ contract ReentrancyAbuser is CCIPReceiver {

function _ccipReceive(Client.Any2EVMMessage memory) internal override {
// Use original message gas limits in manual execution
uint256 numMsgs = s_payload.messages.length;
uint256[] memory gasOverrides = new uint256[](numMsgs);
for (uint256 i = 0; i < numMsgs; ++i) {
gasOverrides[i] = 0;
}
EVM2EVMOffRamp.GasLimitOverride[] memory gasOverrides = _getGasLimitsFromMessages(s_payload.messages);

if (!s_ReentrancyDone) {
// Could do more rounds but a PoC one is enough
Expand All @@ -37,4 +35,22 @@ contract ReentrancyAbuser is CCIPReceiver {
emit ReentrancySucceeded();
}
}

function _getGasLimitsFromMessages(Internal.EVM2EVMMessage[] memory messages)
internal
view
returns (EVM2EVMOffRamp.GasLimitOverride[] memory)
{
EVM2EVMOffRamp.GasLimitOverride[] memory gasLimitOverrides = new EVM2EVMOffRamp.GasLimitOverride[](messages.length);
for (uint256 i = 0; i < messages.length; ++i) {
gasLimitOverrides[i].receiverExecutionGasLimit = messages[i].gasLimit;
gasLimitOverrides[i].tokenGasOverrides = new uint32[](messages[i].tokenAmounts.length);

for (uint256 j = 0; j < messages[i].tokenAmounts.length; ++j) {
gasLimitOverrides[i].tokenGasOverrides[j] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD + 1;
}
}

return gasLimitOverrides;
}
}
Loading
Loading