Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
116 changes: 45 additions & 71 deletions ccv/chains/evm/gobindings/generated/latest/fee_quoter/fee_quoter.go

Large diffs are not rendered by default.

Large diffs are not rendered by default.

198 changes: 99 additions & 99 deletions chains/evm/.gas-snapshot

Large diffs are not rendered by default.

599 changes: 293 additions & 306 deletions chains/evm/contracts/FeeQuoter.sol

Large diffs are not rendered by default.

140 changes: 41 additions & 99 deletions chains/evm/contracts/interfaces/IFeeQuoter.sol
Original file line number Diff line number Diff line change
@@ -1,74 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import {Client} from "../libraries/Client.sol";
import {Internal} from "../libraries/Internal.sol";

interface IFeeQuoter {
/// @notice Quotes the total gas and gas cost in USD cents.
/// @param destChainSelector The destination chain selector.
/// @param nonCalldataGas The non-calldata gas to be used for the message.
/// @param calldataSize The size of the calldata in bytes.
/// @return totalGas The total gas needed for the message.
/// @return gasCostInUsdCents The gas cost in USD cents, taking into account the calldata cost as well.
function quoteGasForExec(
uint64 destChainSelector,
uint32 nonCalldataGas,
uint32 calldataSize
) external view returns (uint32 totalGas, uint256 gasCostInUsdCents);

/// @notice Validates the ccip message & returns the fee.
/// @param destChainSelector The destination chain selector.
/// @param message The message to get quote for.
/// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token.
function getValidatedFee(
uint64 destChainSelector,
Client.EVM2AnyMessage calldata message
) external view returns (uint256 feeTokenAmount);

/// @notice Converts the extraArgs to the latest version and returns the converted message fee in juels.
/// @notice Validates pool return data.
/// @param destChainSelector destination chain selector to process, must be a configured valid chain.
/// @param feeToken token address used to pay for message fees, must be a configured valid fee token.
/// @param feeTokenAmount Fee token amount.
/// @param extraArgs Message extra args that were passed in by the client.
/// @param messageReceiver Message receiver address in bytes from EVM2AnyMessage.receiver
/// @return msgFeeJuels message fee in juels.
/// @return isOutOfOrderExecution true if the message should be executed out of order.
/// @return convertedExtraArgs extra args converted to the latest family-specific args version.
/// @return tokenReceiver token receiver address in bytes on destination chain
function processMessageArgs(
uint64 destChainSelector,
address feeToken,
uint256 feeTokenAmount,
bytes calldata extraArgs,
bytes calldata messageReceiver
)
external
view
returns (
uint256 msgFeeJuels,
bool isOutOfOrderExecution,
bytes memory convertedExtraArgs,
bytes memory tokenReceiver
);

/// @notice Validates pool return data.
/// @param destChainSelector Destination chain selector to which the token amounts are sent to.
/// @param onRampTokenTransfers Token amounts with populated pool return data.
/// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message.
/// @return destExecDataPerToken Destination chain execution data.
function processPoolReturnData(
uint64 destChainSelector,
Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers,
Client.EVMTokenAmount[] calldata sourceTokenAmounts
) external view returns (bytes[] memory destExecDataPerToken);

/// @notice Update the price for given tokens and gas prices for given chains.
/// @param priceUpdates The price updates to apply.
function updatePrices(
Internal.PriceUpdates memory priceUpdates
) external;
/// @notice Get the list of fee tokens.
/// @return feeTokens The tokens set as fee tokens.
function getFeeTokens() external view returns (address[] memory);

/// @notice Get the `tokenPrice` for a given token.
/// @param token The token to get the price for.
Expand All @@ -91,6 +29,12 @@ interface IFeeQuoter {
address[] calldata tokens
) external view returns (Internal.TimestampedPackedUint224[] memory);

/// @notice Update the price for given tokens and gas prices for given chains.
/// @param priceUpdates The price updates to apply.
function updatePrices(
Internal.PriceUpdates memory priceUpdates
) external;

/// @notice Get an encoded `gasPrice` for a given destination chain ID.
/// The 224-bit result encodes necessary gas price components.
/// On L1 chains like Ethereum or Avax, the only component is the gas price.
Expand All @@ -102,30 +46,40 @@ interface IFeeQuoter {
uint64 destChainSelector
) external view returns (Internal.TimestampedPackedUint224 memory);

/// @notice Gets the fee token price and the gas price, both denominated in dollars.
/// @param token The source token to get the price for.
/// @param destChainSelector The destination chain to get the gas price for.
/// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit.
/// @return gasPrice The price of gas in 1e18 dollars per base unit.
function getTokenAndGasPrices(
address token,
uint64 destChainSelector
) external view returns (uint224 tokenPrice, uint224 gasPrice);
// ================================================================
// │ Not needed for new 1.7 chains │
// ================================================================

/// @notice Convert a given token amount to target token amount.
/// @param fromToken The given token address.
/// @param fromTokenAmount The given token amount.
/// @param toToken The target token address.
/// @return toTokenAmount The target token amount.
function convertTokenAmount(
address fromToken,
uint256 fromTokenAmount,
address toToken
) external view returns (uint256 toTokenAmount);
/// @notice Gets the resolved token transfer fee components for a token transfer.
/// @dev This function will check token-specific config first, then fall back to destination chain defaults.
/// @param destChainSelector The destination chain selector.
/// @param token The token address.
/// @return feeUSDCents The fee in USD cents (multiples of 0.01 USD).
/// @return destGasOverhead The gas charged to execute the token transfer on the destination chain.
/// @return destBytesOverhead The bytes overhead for the token transfer on the destination chain.
function getTokenTransferFee(
uint64 destChainSelector,
address token
) external view returns (uint32 feeUSDCents, uint32 destGasOverhead, uint32 destBytesOverhead);

/// @notice Get the list of fee tokens.
/// @return feeTokens The tokens set as fee tokens.
function getFeeTokens() external view returns (address[] memory);
/// @notice Quotes the total gas and gas cost in USD cents.
/// @param destChainSelector The destination chain selector.
/// @param nonCalldataGas The non-calldata gas to be used for the message.
/// @param calldataSize The size of the calldata in bytes.
/// @param feeToken The fee token address.
/// @return totalGas The total gas needed for the message.
/// @return gasCostInUsdCents The gas cost in USD cents, taking into account the calldata cost as well.
/// @return feeTokenPrice The price of the fee token in 1e18 USD.
/// @return premiumBasisPointsMultiplier The premium in basis points.
function quoteGasForExec(
uint64 destChainSelector,
uint32 nonCalldataGas,
uint32 calldataSize,
address feeToken
)
external
view
returns (uint32 totalGas, uint256 gasCostInUsdCents, uint256 feeTokenPrice, uint256 premiumBasisPointsMultiplier);

/// @notice Resolves legacy extra args for backward compatibility. Only has to support EVM, SVM, Aptos and SUI chain
/// families as all future families have to use the new extraArgs format.
Expand All @@ -138,16 +92,4 @@ interface IFeeQuoter {
uint64 destChainSelector,
bytes calldata extraArgs
) external view returns (bytes memory tokenReceiver, uint32 gasLimit, bytes memory executorArgs);

/// @notice Gets the resolved token transfer fee components for a token transfer.
/// @dev This function will check token-specific config first, then fall back to destination chain defaults.
/// @param destChainSelector The destination chain selector.
/// @param token The token address.
/// @return feeUSDCents The fee in USD cents (multiples of 0.01 USD).
/// @return destGasOverhead The gas charged to execute the token transfer on the destination chain.
/// @return destBytesOverhead The bytes overhead for the token transfer on the destination chain.
function getTokenTransferFee(
uint64 destChainSelector,
address token
) external view returns (uint32 feeUSDCents, uint32 destGasOverhead, uint32 destBytesOverhead);
}
78 changes: 78 additions & 0 deletions chains/evm/contracts/interfaces/ILegacyFeeQuoter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import {Client} from "../libraries/Client.sol";
import {Internal} from "../libraries/Internal.sol";

interface ILegacyFeeQuoter {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Extracted to clearly show what can be removed in future versions and what doesn't have to be written for net-new non-evms

/// @notice Converts the extraArgs to the latest version and returns the converted message fee in juels.
/// @notice Validates pool return data.
/// @param destChainSelector destination chain selector to process, must be a configured valid chain.
/// @param feeToken token address used to pay for message fees, must be a configured valid fee token.
/// @param feeTokenAmount Fee token amount.
/// @param extraArgs Message extra args that were passed in by the client.
/// @param messageReceiver Message receiver address in bytes from EVM2AnyMessage.receiver
/// @return msgFeeJuels message fee in juels.
/// @return isOutOfOrderExecution true if the message should be executed out of order.
/// @return convertedExtraArgs extra args converted to the latest family-specific args version.
/// @return tokenReceiver token receiver address in bytes on destination chain
function processMessageArgs(
uint64 destChainSelector,
address feeToken,
uint256 feeTokenAmount,
bytes calldata extraArgs,
bytes calldata messageReceiver
)
external
view
returns (
uint256 msgFeeJuels,
bool isOutOfOrderExecution,
bytes memory convertedExtraArgs,
bytes memory tokenReceiver
);

/// @notice Validates the ccip message & returns the fee.
/// @param destChainSelector The destination chain selector.
/// @param message The message to get quote for.
/// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token.
function getValidatedFee(
uint64 destChainSelector,
Client.EVM2AnyMessage calldata message
) external view returns (uint256 feeTokenAmount);

/// @notice Convert a given token amount to target token amount.
/// @dev this function assumes that no more than 1e59 dollars are sent as payment.
/// If more is sent, the multiplication of feeTokenAmount and feeTokenValue will overflow.
/// Since there isn't even close to 1e59 dollars in the world economy this is safe.
/// @param fromToken The given token address.
/// @param fromTokenAmount The given token amount.
/// @param toToken The target token address.
/// @return toTokenAmount The target token amount.
function convertTokenAmount(
address fromToken,
uint256 fromTokenAmount,
address toToken
) external view returns (uint256 toTokenAmount);

/// @notice Gets the fee token price and the gas price, both denominated in dollars.
/// @param token The source token to get the price for.
/// @param destChainSelector The destination chain to get the gas price for.
/// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit.
/// @return gasPrice The price of gas in 1e18 dollars per base unit.
function getTokenAndGasPrices(
address token,
uint64 destChainSelector
) external view returns (uint224 tokenPrice, uint224 gasPrice);

/// @notice Validates pool return data.
/// @param destChainSelector Destination chain selector to which the token amounts are sent to.
/// @param onRampTokenTransfers Token amounts with populated pool return data.
/// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message.
/// @return destExecDataPerToken Destination chain execution data.
function processPoolReturnData(
uint64 destChainSelector,
Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers,
Client.EVMTokenAmount[] calldata sourceTokenAmounts
) external view returns (bytes[] memory destExecDataPerToken);
}
16 changes: 8 additions & 8 deletions chains/evm/contracts/onRamp/OnRamp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -835,26 +835,26 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, Ownable2StepMsgSender
gasLimitSum += receipts[executorIndex].destGasLimit;
bytesOverheadSum += receipts[executorIndex].destBytesOverhead;

uint256 execCostInUSDCents;
(gasLimitSum, execCostInUSDCents) =
IFeeQuoter(s_dynamicConfig.feeQuoter).quoteGasForExec(destChainSelector, gasLimitSum, bytesOverheadSum);
(uint32 updatedGasLimitSum, uint256 execCostInUSDCents, uint256 feeTokenPrice, uint256 bpsMultiplier) = IFeeQuoter(
s_dynamicConfig.feeQuoter
).quoteGasForExec(destChainSelector, gasLimitSum, bytesOverheadSum, message.feeToken);

gasLimitSum = updatedGasLimitSum;

// Update the fee of the executor to include execution costs.
if (extraArgs.executor != Client.NO_EXECUTION_ADDRESS) {
receipts[executorIndex].feeTokenAmount += execCostInUSDCents;
}

// The price, in USD with 18 decimals, per 1e18 of the smallest token denomination.
uint256 feeTokenPrice = IFeeQuoter(s_dynamicConfig.feeQuoter).getValidatedTokenPrice(message.feeToken);

// Transform the USD based fees into fee token amounts & sum them.
for (uint256 i = 0; i < receipts.length; ++i) {
// Example:
// feeTokenPrice = $15 = 15e18
// usdFeeCents = $1.50 = 150
// feeTokenAmount = 150 * 1e34 / 15e18 = 1e17 (0.1 tokens of the fee token)
// Normally we'd multiple by 1e36, but since usdFeeCents has 2 decimals, we use 1e34 here.
receipts[i].feeTokenAmount = receipts[i].feeTokenAmount * 1e34 / feeTokenPrice;
// Normally we'd multiple by 1e36, but since usdFeeCents has 2 decimals and bpsMultiplier has 4 decimals, we use
// 1e30 here.
receipts[i].feeTokenAmount = receipts[i].feeTokenAmount * bpsMultiplier * 1e30 / feeTokenPrice;
feeTokenAmount += receipts[i].feeTokenAmount;
}

Expand Down
6 changes: 2 additions & 4 deletions chains/evm/contracts/test/Router/Router.ccipSend.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {IEVM2AnyOnRampClient} from "../../interfaces/IEVM2AnyOnRampClient.sol";
import {IRouterClient} from "../../interfaces/IRouterClient.sol";
import {IWrappedNative} from "../../interfaces/IWrappedNative.sol";

import {FeeQuoter} from "../../FeeQuoter.sol";
import {Router} from "../../Router.sol";
import {Client} from "../../libraries/Client.sol";
import {TokenPool} from "../../pools/TokenPool.sol";
Expand Down Expand Up @@ -135,9 +134,8 @@ contract Router_ccipSend is RouterSetup {
}

function test_NonLinkFeeToken() public {
FeeQuoter.FeeTokenArgs[] memory feeTokens = new FeeQuoter.FeeTokenArgs[](1);
feeTokens[0].token = s_sourceTokens[1];
feeTokens[0].premiumMultiplierWeiPerEth = 1e18;
address[] memory feeTokens = new address[](1);
feeTokens[0] = s_sourceTokens[1];

s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens);

Expand Down
Loading
Loading