Skip to content

Commit

Permalink
test: dynamically fetch dest gas amt
Browse files Browse the repository at this point in the history
  • Loading branch information
DhairyaSethi committed Oct 30, 2024
1 parent 758cbc3 commit 6044944
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
pragma solidity ^0.8.0;

import {ITypeAndVersion} from "../../../../shared/interfaces/ITypeAndVersion.sol";
import {IAny2EVMOffRamp} from "../../../interfaces/IAny2EVMOffRamp.sol";
import {Internal} from "../../../libraries/Internal.sol";

interface IEVM2EVMOffRamp_1_2 is IAny2EVMOffRamp, ITypeAndVersion {
function executeSingleMessage(Internal.EVM2EVMMessage memory message, bytes[] memory offchainTokenData) external;
}

interface IEVM2EVMOffRamp_1_5 is IAny2EVMOffRamp, ITypeAndVersion {
function executeSingleMessage(
Internal.EVM2EVMMessage calldata message,
bytes[] calldata offchainTokenData,
uint32[] memory tokenGasOverrides
) external;
}
46 changes: 46 additions & 0 deletions contracts/src/v0.8/ccip/test/helpers/interfaces/IEVM2EVMOnRamp.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
pragma solidity ^0.8.0;

import {ITypeAndVersion} from "../../../../shared/interfaces/ITypeAndVersion.sol";
import {IEVM2AnyOnRamp} from "../../../interfaces/IEVM2AnyOnRamp.sol";

interface IEVM2EVMOnRamp_1_2 is IEVM2AnyOnRamp, ITypeAndVersion {}

interface IEVM2EVMOnRamp_1_5 is IEVM2AnyOnRamp, ITypeAndVersion {
struct TokenTransferFeeConfig {
uint32 minFeeUSDCents; // ──────────╮ Minimum fee to charge per token transfer, multiples of 0.01 USD
uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD
uint16 deciBps; // │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5
uint32 destGasOverhead; // │ Gas charged to execute the token transfer on the destination chain
// │ Extra data availability bytes that are returned from the source pool and sent
uint32 destBytesOverhead; // │ to the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES
bool aggregateRateLimitEnabled; // │ Whether this transfer token is to be included in Aggregate Rate Limiting
bool isEnabled; // ─────────────────╯ Whether this token has custom transfer fees
}

struct DynamicConfig {
address router; // ──────────────────────────╮ Router address
uint16 maxNumberOfTokensPerMsg; // │ Maximum number of distinct ERC20 token transferred per message
uint32 destGasOverhead; // │ Gas charged on top of the gasLimit to cover destination chain costs
uint16 destGasPerPayloadByte; // │ Destination chain gas charged for passing each byte of `data` payload to receiver
uint32 destDataAvailabilityOverheadGas; // ──╯ Extra data availability gas charged on top of the message, e.g. for OCR
uint16 destGasPerDataAvailabilityByte; // ───╮ Amount of gas to charge per byte of message data that needs availability
uint16 destDataAvailabilityMultiplierBps; // │ Multiplier for data availability gas, multiples of bps, or 0.0001
address priceRegistry; // │ Price registry address
uint32 maxDataBytes; // │ Maximum payload data size in bytes
uint32 maxPerMsgGasLimit; // ────────────────╯ Maximum gas limit for messages targeting EVMs
// │
// The following three properties are defaults, they can be overridden by setting the TokenTransferFeeConfig for a token
uint16 defaultTokenFeeUSDCents; // ──────────╮ Default token fee charged per token transfer
uint32 defaultTokenDestGasOverhead; // │ Default gas charged to execute the token transfer on the destination chain
bool enforceOutOfOrder; // ──────────────────╯ Whether to enforce the allowOutOfOrderExecution extraArg value to be true.
}

/// @notice Gets the transfer fee config for a given token.
function getTokenTransferFeeConfig(
address token
) external view returns (TokenTransferFeeConfig memory tokenTransferFeeConfig);

/// @notice Returns the dynamic onRamp config.
/// @return dynamicConfig the configuration.
function getDynamicConfig() external view returns (DynamicConfig memory dynamicConfig);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {IAny2EVMOffRamp} from "../../../../../interfaces/IAny2EVMOffRamp.sol";
import {IRouter as IRouterBase} from "../../../../../interfaces/IRouter.sol";
import {Client} from "../../../../../libraries/Client.sol";
import {Internal} from "../../../../../libraries/Internal.sol";
import {IEVM2EVMOffRamp_1_2, IEVM2EVMOffRamp_1_5} from "../../../../helpers/interfaces/IEVM2EVMOffRamp.sol";
import {IEVM2EVMOnRamp_1_2, IEVM2EVMOnRamp_1_5} from "../../../../helpers/interfaces/IEVM2EVMOnRamp.sol";
import {UpgradeableLockReleaseTokenPool_Sepolia} from "./LegacyTestnetTokenPools/UpgradeableLockReleaseTokenPool_Sepolia.sol";
import {UpgradeableBurnMintTokenPool_ArbSepolia} from "./LegacyTestnetTokenPools/UpgradeableBurnMintTokenPool_ArbSepolia.sol";

Expand All @@ -23,18 +25,6 @@ interface IRouter is IRouterClient, IRouterBase {
function getOffRamps() external view returns (OffRamp[] memory);
}

interface IEVM2EVMOffRamp_1_2 is IAny2EVMOffRamp, ITypeAndVersion {
function executeSingleMessage(Internal.EVM2EVMMessage memory message, bytes[] memory offchainTokenData) external;
}

interface IEVM2EVMOffRamp_1_5 is IAny2EVMOffRamp, ITypeAndVersion {
function executeSingleMessage(
Internal.EVM2EVMMessage calldata message,
bytes[] calldata offchainTokenData,
uint32[] memory tokenGasOverrides
) external;
}

struct SourceTokenData {
bytes sourcePoolAddress;
bytes destTokenAddress;
Expand All @@ -55,8 +45,8 @@ contract ForkBase is Test {
UpgradeableLockReleaseTokenPool_Sepolia tokenPool;
IRouter router;
IERC20 token;
IEVM2AnyOnRamp EVM2EVMOnRamp1_2;
IEVM2AnyOnRamp EVM2EVMOnRamp1_5;
IEVM2EVMOnRamp_1_2 EVM2EVMOnRamp1_2;
IEVM2EVMOnRamp_1_5 EVM2EVMOnRamp1_5;
IEVM2EVMOffRamp_1_2 EVM2EVMOffRamp1_2;
IEVM2EVMOffRamp_1_5 EVM2EVMOffRamp1_5;
address proxyPool;
Expand All @@ -68,8 +58,8 @@ contract ForkBase is Test {
UpgradeableBurnMintTokenPool_ArbSepolia tokenPool;
IRouter router;
IERC20 token;
IEVM2AnyOnRamp EVM2EVMOnRamp1_2;
IEVM2AnyOnRamp EVM2EVMOnRamp1_5;
IEVM2EVMOnRamp_1_2 EVM2EVMOnRamp1_2;
IEVM2EVMOnRamp_1_5 EVM2EVMOnRamp1_5;
IEVM2EVMOffRamp_1_2 EVM2EVMOffRamp1_2;
IEVM2EVMOffRamp_1_5 EVM2EVMOffRamp1_5;
address proxyPool;
Expand All @@ -96,8 +86,8 @@ contract ForkBase is Test {
l1.router = IRouter(l1.tokenPool.getRouter());
l2.chainSelector = l1.tokenPool.getSupportedChains()[0];
l1.token = l1.tokenPool.getToken();
l1.EVM2EVMOnRamp1_2 = IEVM2AnyOnRamp(0xe4Dd3B16E09c016402585a8aDFdB4A18f772a07e); // legacy on ramp
l1.EVM2EVMOnRamp1_5 = IEVM2AnyOnRamp(l1.router.getOnRamp(l2.chainSelector));
l1.EVM2EVMOnRamp1_2 = IEVM2EVMOnRamp_1_2(0xe4Dd3B16E09c016402585a8aDFdB4A18f772a07e); // legacy on ramp
l1.EVM2EVMOnRamp1_5 = IEVM2EVMOnRamp_1_5(l1.router.getOnRamp(l2.chainSelector));
l1.EVM2EVMOffRamp1_2 = IEVM2EVMOffRamp_1_2(0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1);
l1.EVM2EVMOffRamp1_5 = IEVM2EVMOffRamp_1_5(0xD2f5edfD4561d6E7599F6c6888Bd353cAFd0c55E);
vm.prank(alice);
Expand All @@ -111,8 +101,8 @@ contract ForkBase is Test {
l2.router = IRouter(l2.tokenPool.getRouter());
l1.chainSelector = l2.tokenPool.getSupportedChains()[0];
l2.token = l2.tokenPool.getToken();
l2.EVM2EVMOnRamp1_2 = IEVM2AnyOnRamp(0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9); // legacy on ramp
l2.EVM2EVMOnRamp1_5 = IEVM2AnyOnRamp(l2.router.getOnRamp(l1.chainSelector));
l2.EVM2EVMOnRamp1_2 = IEVM2EVMOnRamp_1_2(0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9); // legacy on ramp
l2.EVM2EVMOnRamp1_5 = IEVM2EVMOnRamp_1_5(l2.router.getOnRamp(l1.chainSelector));
l2.EVM2EVMOffRamp1_2 = IEVM2EVMOffRamp_1_2(0x1c71f141b4630EBE52d6aF4894812960abE207eB);
l2.EVM2EVMOffRamp1_5 = IEVM2EVMOffRamp_1_5(0xBed6e9131916d724418C8a6FE810F727302a5c00);
vm.prank(alice);
Expand All @@ -129,8 +119,8 @@ contract ForkBase is Test {
assertEq(l1.token.balanceOf(alice), 1000e18);
assertEq(ITypeAndVersion(address(l1.router)).typeAndVersion(), "Router 1.2.0");
assertEq(ITypeAndVersion(l1.proxyPool).typeAndVersion(), "LockReleaseTokenPoolAndProxy 1.5.0");
assertEq(ITypeAndVersion(address(l1.EVM2EVMOnRamp1_2)).typeAndVersion(), "EVM2EVMOnRamp 1.2.0");
assertEq(ITypeAndVersion(address(l1.EVM2EVMOnRamp1_5)).typeAndVersion(), "EVM2EVMOnRamp 1.5.0");
assertEq(l1.EVM2EVMOnRamp1_2.typeAndVersion(), "EVM2EVMOnRamp 1.2.0");
assertEq(l1.EVM2EVMOnRamp1_5.typeAndVersion(), "EVM2EVMOnRamp 1.5.0");
assertEq(l1.EVM2EVMOffRamp1_2.typeAndVersion(), "EVM2EVMOffRamp 1.2.0");
assertEq(l1.EVM2EVMOffRamp1_5.typeAndVersion(), "EVM2EVMOffRamp 1.5.0");
assertTrue(l1.router.isOffRamp(l2.chainSelector, address(l1.EVM2EVMOffRamp1_2)));
Expand All @@ -142,8 +132,8 @@ contract ForkBase is Test {
assertEq(l2.token.balanceOf(alice), 1000e18);
assertEq(ITypeAndVersion(address(l2.router)).typeAndVersion(), "Router 1.2.0");
assertEq(ITypeAndVersion(l2.proxyPool).typeAndVersion(), "BurnMintTokenPoolAndProxy 1.5.0");
assertEq(ITypeAndVersion(address(l2.EVM2EVMOnRamp1_2)).typeAndVersion(), "EVM2EVMOnRamp 1.2.0");
assertEq(ITypeAndVersion(address(l2.EVM2EVMOnRamp1_5)).typeAndVersion(), "EVM2EVMOnRamp 1.5.0");
assertEq(l2.EVM2EVMOnRamp1_2.typeAndVersion(), "EVM2EVMOnRamp 1.2.0");
assertEq(l2.EVM2EVMOnRamp1_5.typeAndVersion(), "EVM2EVMOnRamp 1.5.0");
assertEq(l2.EVM2EVMOffRamp1_2.typeAndVersion(), "EVM2EVMOffRamp 1.2.0");
assertEq(l2.EVM2EVMOffRamp1_5.typeAndVersion(), "EVM2EVMOffRamp 1.5.0");
assertTrue(l2.router.isOffRamp(l1.chainSelector, address(l2.EVM2EVMOffRamp1_2)));
Expand All @@ -168,7 +158,7 @@ contract ForkBase is Test {

function _messageToEvent(
Client.EVM2AnyMessage memory message,
IEVM2AnyOnRamp onRamp,
address onRamp,
uint256 feeTokenAmount,
address originalSender,
bool isL1
Expand All @@ -180,10 +170,10 @@ contract ForkBase is Test {
}
Client.EVMExtraArgsV1 memory extraArgs = abi.decode(args, (Client.EVMExtraArgsV1));
Internal.EVM2EVMMessage memory messageEvent = Internal.EVM2EVMMessage({
sequenceNumber: onRamp.getExpectedNextSequenceNumber(),
sequenceNumber: IEVM2AnyOnRamp(onRamp).getExpectedNextSequenceNumber(),
feeTokenAmount: feeTokenAmount,
sender: originalSender,
nonce: onRamp.getSenderNonce(originalSender) + 1,
nonce: IEVM2AnyOnRamp(onRamp).getSenderNonce(originalSender) + 1,
gasLimit: extraArgs.gasLimit,
strict: false,
sourceChainSelector: isL1 ? l1.chainSelector : l2.chainSelector,
Expand All @@ -202,7 +192,7 @@ contract ForkBase is Test {
sourcePoolAddress: abi.encode(isL1 ? l1.proxyPool : l2.proxyPool),
destTokenAddress: abi.encode(address(isL1 ? l2.token : l1.token)),
extraData: "",
destGasAmount: 90000
destGasAmount: _getDestGasAmount(onRamp, message.tokenAmounts[i].token)
})
);
}
Expand All @@ -211,6 +201,16 @@ contract ForkBase is Test {
return messageEvent;
}

function _getDestGasAmount(address onRamp, address token) internal view returns (uint32) {
IEVM2EVMOnRamp_1_5.TokenTransferFeeConfig memory config = IEVM2EVMOnRamp_1_5(onRamp).getTokenTransferFeeConfig(
token
);
return
config.isEnabled
? config.destGasOverhead
: IEVM2EVMOnRamp_1_5(onRamp).getDynamicConfig().defaultTokenDestGasOverhead;
}

function _generateMetadataHash(uint64 sourceChainSelector, IEVM2AnyOnRamp onRamp) internal view returns (bytes32) {
uint64 destChainSelector = sourceChainSelector == l1.chainSelector ? l2.chainSelector : l1.chainSelector;
return
Expand Down Expand Up @@ -286,7 +286,7 @@ contract ForkPoolBeforeMigration is ForkBase {
l1.router = IRouter(l1.tokenPool.getRouter());
l2.chainSelector = l1.tokenPool.getSupportedChains()[0];
l1.token = l1.tokenPool.getToken();
l1.EVM2EVMOnRamp1_2 = IEVM2AnyOnRamp(l1.router.getOnRamp(l2.chainSelector));
l1.EVM2EVMOnRamp1_2 = IEVM2EVMOnRamp_1_2(l1.router.getOnRamp(l2.chainSelector));
l1.EVM2EVMOffRamp1_2 = IEVM2EVMOffRamp_1_2(0xdb92e73d1D630B5B7aC96840c4df0c591c7Ad23E);
vm.prank(alice);
l1.token.approve(address(l1.router), type(uint256).max);
Expand All @@ -298,7 +298,7 @@ contract ForkPoolBeforeMigration is ForkBase {
l2.router = IRouter(l2.tokenPool.getRouter());
l1.chainSelector = l2.tokenPool.getSupportedChains()[0];
l2.token = l2.tokenPool.getToken();
l2.EVM2EVMOnRamp1_2 = IEVM2AnyOnRamp(l2.router.getOnRamp(l1.chainSelector));
l2.EVM2EVMOnRamp1_2 = IEVM2EVMOnRamp_1_2(l2.router.getOnRamp(l1.chainSelector));
l2.EVM2EVMOffRamp1_2 = IEVM2EVMOffRamp_1_2(0xFf5e1c597c5DFfC896Ab8c7b9d876D513518c4b7);
vm.prank(alice);
l2.token.approve(address(l2.router), type(uint256).max);
Expand Down Expand Up @@ -396,7 +396,7 @@ contract ForkPoolBeforeMigration is ForkBase {
uint256 feeTokenAmount = l2.router.getFee(l1.chainSelector, message);
Internal.EVM2EVMMessage memory eventArg = _messageToEvent(
message,
l2.EVM2EVMOnRamp1_2,
address(l2.EVM2EVMOnRamp1_2),
feeTokenAmount,
alice,
false
Expand All @@ -423,7 +423,7 @@ contract ForkPoolBeforeMigration is ForkBase {
uint256 feeTokenAmount = l1.router.getFee(l2.chainSelector, message);
Internal.EVM2EVMMessage memory eventArg = _messageToEvent(
message,
l1.EVM2EVMOnRamp1_2,
address(l1.EVM2EVMOnRamp1_2),
feeTokenAmount,
alice,
true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ contract ForkPoolUpgradeAfterMigration is ForkBase {
// router uses 1_5 onRamp
assertEq(l1.router.getOnRamp(l2.chainSelector), address(l1.EVM2EVMOnRamp1_5));
vm.expectEmit();
emit CCIPSendRequested(_messageToEvent(message, l1.EVM2EVMOnRamp1_5, feeTokenAmount, alice, true));
emit CCIPSendRequested(_messageToEvent(message, address(l1.EVM2EVMOnRamp1_5), feeTokenAmount, alice, true));
vm.prank(alice);
l1.router.ccipSend{value: feeTokenAmount}(l2.chainSelector, message);
}
Expand All @@ -57,7 +57,7 @@ contract ForkPoolUpgradeAfterMigration is ForkBase {
// router uses 1_5 onRamp
assertEq(l2.router.getOnRamp(l1.chainSelector), address(l2.EVM2EVMOnRamp1_5));
vm.expectEmit();
emit CCIPSendRequested(_messageToEvent(message, l2.EVM2EVMOnRamp1_5, feeTokenAmount, alice, false));
emit CCIPSendRequested(_messageToEvent(message, address(l2.EVM2EVMOnRamp1_5), feeTokenAmount, alice, false));
vm.prank(alice);
l2.router.ccipSend{value: feeTokenAmount}(l1.chainSelector, message);
}
Expand Down Expand Up @@ -91,7 +91,7 @@ contract ForkPoolUpgradeAfterMigration is ForkBase {
uint256 feeTokenAmount = l2.router.getFee(l1.chainSelector, message);
Internal.EVM2EVMMessage memory eventArg = _messageToEvent(
message,
l2.EVM2EVMOnRamp1_5,
address(l2.EVM2EVMOnRamp1_5),
feeTokenAmount,
alice,
false
Expand All @@ -118,7 +118,7 @@ contract ForkPoolUpgradeAfterMigration is ForkBase {
uint256 feeTokenAmount = l1.router.getFee(l2.chainSelector, message);
Internal.EVM2EVMMessage memory eventArg = _messageToEvent(
message,
l1.EVM2EVMOnRamp1_5,
address(l1.EVM2EVMOnRamp1_5),
feeTokenAmount,
alice,
true
Expand Down Expand Up @@ -150,7 +150,7 @@ contract ForkPoolUpgradeAfterMigration is ForkBase {
uint256 feeTokenAmount = l2.router.getFee(l1.chainSelector, message);
Internal.EVM2EVMMessage memory eventArg = _messageToEvent(
message,
l2.EVM2EVMOnRamp1_5,
address(l2.EVM2EVMOnRamp1_5),
feeTokenAmount,
alice,
false
Expand Down Expand Up @@ -179,7 +179,7 @@ contract ForkPoolUpgradeAfterMigration is ForkBase {
uint256 feeTokenAmount = l1.router.getFee(l2.chainSelector, message);
Internal.EVM2EVMMessage memory eventArg = _messageToEvent(
message,
l1.EVM2EVMOnRamp1_5,
address(l1.EVM2EVMOnRamp1_5),
feeTokenAmount,
alice,
true
Expand Down

0 comments on commit 6044944

Please sign in to comment.