Skip to content

Commit

Permalink
Merge branch 'ccip-2824' of github.com:smartcontractkit/ccip into cci…
Browse files Browse the repository at this point in the history
…p-2824
  • Loading branch information
b-gopalswami committed Aug 9, 2024
2 parents e267ec3 + ee89ee5 commit 308f078
Show file tree
Hide file tree
Showing 73 changed files with 1,593 additions and 1,136 deletions.
464 changes: 239 additions & 225 deletions contracts/gas-snapshots/ccip.gas-snapshot

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions contracts/gas-snapshots/liquiditymanager.gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ LiquidityManager_addLiquidity:test_addLiquiditySuccess() (gas: 279154)
LiquidityManager_rebalanceLiquidity:test_InsufficientLiquidityReverts() (gas: 206745)
LiquidityManager_rebalanceLiquidity:test_InvalidRemoteChainReverts() (gas: 192319)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess() (gas: 9141768)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 8981838)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 8977044)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 8904842)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 8960797)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 8956003)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 8883801)
LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382897)
LiquidityManager_receive:test_receive_success() (gas: 21182)
LiquidityManager_removeLiquidity:test_InsufficientLiquidityReverts() (gas: 184869)
Expand All @@ -19,7 +19,7 @@ LiquidityManager_setFinanceRole:test_OnlyOwnerReverts() (gas: 10987)
LiquidityManager_setFinanceRole:test_setFinanceRoleSuccess() (gas: 21836)
LiquidityManager_setLocalLiquidityContainer:test_OnlyOwnerReverts() (gas: 11052)
LiquidityManager_setLocalLiquidityContainer:test_ReverstWhen_CalledWithTheZeroAddress() (gas: 10643)
LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3519863)
LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3498806)
LiquidityManager_setMinimumLiquidity:test_OnlyOwnerReverts() (gas: 10925)
LiquidityManager_setMinimumLiquidity:test_setMinimumLiquiditySuccess() (gas: 36389)
LiquidityManager_withdrawERC20:test_withdrawERC20Reverts() (gas: 180359)
Expand Down
2 changes: 1 addition & 1 deletion contracts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@chainlink/contracts-ccip",
"version": "1.4.0",
"version": "1.5.0",
"description": "Chainlink CCIP smart contracts",
"author": "Chainlink devs",
"license": "BUSL-1.1",
Expand Down
2 changes: 1 addition & 1 deletion contracts/src/v0.8/ccip/CommitStore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ contract CommitStore is ICommitStore, ITypeAndVersion, OCR2Base {
}

// STATIC CONFIG
string public constant override typeAndVersion = "CommitStore 1.5.0-dev";
string public constant override typeAndVersion = "CommitStore 1.5.0";
// Chain ID of this chain
uint64 internal immutable i_chainSelector;
// Chain ID of the source chain
Expand Down
2 changes: 2 additions & 0 deletions contracts/src/v0.8/ccip/interfaces/IPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ interface IPoolV1 is IERC165 {
/// @param releaseOrMintIn All data required to release or mint tokens.
/// @return releaseOrMintOut The amount of tokens released or minted on the local chain, denominated
/// in the local token's decimals.
/// @dev The offramp asserts that the balanceOf of the receiver has been incremented by exactly the number
/// of tokens that is returned in ReleaseOrMintOutV1.destinationAmount. If the amounts do not match, the tx reverts.
function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn)
external
returns (Pool.ReleaseOrMintOutV1 memory);
Expand Down
2 changes: 2 additions & 0 deletions contracts/src/v0.8/ccip/libraries/Internal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ library Internal {
// malicious contracts from returning large amounts of data and causing
// repeated out-of-gas scenarios.
uint16 internal constant MAX_RET_BYTES = 4 + 4 * 32;
/// @dev The expected number of bytes returned by the balanceOf function.
uint256 internal constant MAX_BALANCE_OF_RET_BYTES = 32;

/// @notice A collection of token price and gas price updates.
/// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
Expand Down
3 changes: 1 addition & 2 deletions contracts/src/v0.8/ccip/libraries/Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ library Pool {
struct ReleaseOrMintInV1 {
bytes originalSender; // The original sender of the tx on the source chain
uint64 remoteChainSelector; // ─╮ The chain ID of the source chain
address receiver; // ───────────╯ The recipient of the tokens on the destination chain. This is *NOT* the address to
// send the tokens to, but the address that will receive the tokens via the offRamp.
address receiver; // ───────────╯ The recipient of the tokens on the destination chain.
uint256 amount; // The amount of tokens to release or mint, denominated in the source token's decimals
address localToken; // The address on this chain of the token to release or mint
/// @dev WARNING: sourcePoolAddress should be checked prior to any processing of funds. Make sure it matches the
Expand Down
64 changes: 46 additions & 18 deletions contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
using ERC165Checker for address;
using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap;

error AlreadyExecuted(uint64 sourceChainSelector, uint64 sequenceNumber);
error ZeroChainSelectorNotAllowed();
error ExecutionError(bytes32 messageId, bytes err);
error SourceChainNotEnabled(uint64 sourceChainSelector);
Expand All @@ -48,6 +47,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
error CanOnlySelfCall();
error ReceiverError(bytes err);
error TokenHandlingError(bytes err);
error ReleaseOrMintBalanceMismatch(uint256 amountReleased, uint256 balancePre, uint256 balancePost);
error EmptyReport();
error CursedByRMN(uint64 sourceChainSelector);
error NotACompatiblePool(address notPool);
Expand Down Expand Up @@ -497,7 +497,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
/// @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.Any2EVMRampMessage calldata message,
Internal.Any2EVMRampMessage memory message,
bytes[] calldata offchainTokenData
) external {
if (msg.sender != address(this)) revert CanOnlySelfCall();
Expand Down Expand Up @@ -807,11 +807,11 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
/// @param offchainTokenData Data fetched offchain by the DON.
/// @return destTokenAmount local token address with amount
function _releaseOrMintSingleToken(
Internal.RampTokenAmount calldata sourceTokenAmount,
bytes calldata originalSender,
Internal.RampTokenAmount memory sourceTokenAmount,
bytes memory originalSender,
address receiver,
uint64 sourceChainSelector,
bytes calldata offchainTokenData
bytes memory offchainTokenData
) internal returns (Client.EVMTokenAmount memory destTokenAmount) {
// We need to safely decode the token address from the sourceTokenData, as it could be wrong,
// in which case it doesn't have to be a valid EVM address.
Expand All @@ -826,12 +826,17 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
revert NotACompatiblePool(localPoolAddress);
}

// We retrieve the local token balance of the receiver before the pool call.
(uint256 balancePre, uint256 gasLeft) =
_getBalanceOfReceiver(receiver, localToken, s_dynamicConfig.maxPoolReleaseOrMintGas);

// We determined that the pool address is a valid EVM address, but that does not mean the code at this
// address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location
// contains a contract. If it doesn't it reverts with a known error, which we catch gracefully.
// We call the pool with exact gas to increase resistance against malicious tokens or token pools.
// We protects against return data bombs by capping the return data size at MAX_RET_BYTES.
(bool success, bytes memory returnData,) = CallWithExactGas._callWithExactGasSafeReturnData(
(bool success, bytes memory returnData, uint256 gasUsedReleaseOrMint) = CallWithExactGas
._callWithExactGasSafeReturnData(
abi.encodeCall(
IPoolV1.releaseOrMint,
Pool.ReleaseOrMintInV1({
Expand All @@ -846,7 +851,7 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
})
),
localPoolAddress,
s_dynamicConfig.maxPoolReleaseOrMintGas,
gasLeft,
Internal.GAS_FOR_CALL_EXACT_CHECK,
Internal.MAX_RET_BYTES
);
Expand All @@ -858,21 +863,44 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
if (returnData.length != Pool.CCIP_POOL_V1_RET_BYTES) {
revert InvalidDataLength(Pool.CCIP_POOL_V1_RET_BYTES, returnData.length);
}

uint256 localAmount = abi.decode(returnData, (uint256));
// Since token pools send the tokens to the msg.sender, which is this offRamp, we need to
// transfer them to the final receiver. We use the _callWithExactGasSafeReturnData function because
// the token contracts are not considered trusted.
(success, returnData,) = CallWithExactGas._callWithExactGasSafeReturnData(
abi.encodeCall(IERC20.transferFrom, (localPoolAddress, receiver, localAmount)),
localToken,
s_dynamicConfig.maxTokenTransferGas,
// We don't need to do balance checks if the pool is the receiver, as they would always fail in the case
// of a lockRelease pool.
if (receiver != localPoolAddress) {
(uint256 balancePost,) = _getBalanceOfReceiver(receiver, localToken, gasLeft - gasUsedReleaseOrMint);

// First we check if the subtraction would result in an underflow to ensure we revert with a clear error
if (balancePost < balancePre || balancePost - balancePre != localAmount) {
revert ReleaseOrMintBalanceMismatch(localAmount, balancePre, balancePost);
}
}

return Client.EVMTokenAmount({token: localToken, amount: localAmount});
}

function _getBalanceOfReceiver(
address receiver,
address token,
uint256 gasLimit
) internal returns (uint256 balance, uint256 gasLeft) {
(bool success, bytes memory returnData, uint256 gasUsed) = CallWithExactGas._callWithExactGasSafeReturnData(
abi.encodeCall(IERC20.balanceOf, (receiver)),
token,
gasLimit,
Internal.GAS_FOR_CALL_EXACT_CHECK,
Internal.MAX_RET_BYTES
);

if (!success) revert TokenHandlingError(returnData);

return Client.EVMTokenAmount({token: localToken, amount: localAmount});
// If the call was successful, the returnData should contain only the balance.
if (returnData.length != Internal.MAX_BALANCE_OF_RET_BYTES) {
revert InvalidDataLength(Internal.MAX_BALANCE_OF_RET_BYTES, returnData.length);
}

// Return the decoded balance, which cannot fail as we checked the length, and the gas that is left
// after this call.
return (abi.decode(returnData, (uint256)), gasLimit - gasUsed);
}

/// @notice Uses pools to release or mint a number of different tokens to a receiver address.
Expand All @@ -886,8 +914,8 @@ contract EVM2EVMMultiOffRamp is ITypeAndVersion, MultiOCR3Base {
/// any non-rate limiting errors that may occur. If we encounter a rate limiting related error
/// we bubble it up. If we encounter a non-rate limiting error we wrap it in a TokenHandlingError.
function _releaseOrMintTokens(
Internal.RampTokenAmount[] calldata sourceTokenAmounts,
bytes calldata originalSender,
Internal.RampTokenAmount[] memory sourceTokenAmounts,
bytes memory originalSender,
address receiver,
uint64 sourceChainSelector,
bytes[] calldata offchainTokenData
Expand Down
Loading

0 comments on commit 308f078

Please sign in to comment.