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

CCIP-4269 - Make registered TokenPools swappable #15293

Merged
merged 21 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from 20 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
5 changes: 5 additions & 0 deletions .changeset/bright-keys-whisper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

allow different decimals on different chains for token pools
13 changes: 0 additions & 13 deletions .github/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1096,19 +1096,6 @@ runner-test-matrix:
test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPForBidirectionalLane$ -timeout 30m -count=1 -test.parallel=1 -json
test_env_vars:
E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2

- id: ccip-smoke-1.4-pools
path: integration-tests/ccip-tests/smoke/ccip_test.go
test_env_type: docker
runs_on: ubuntu-latest
triggers:
- PR E2E CCIP Tests
- Merge Queue E2E CCIP Tests
- Nightly E2E Tests
test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPForBidirectionalLane$ -timeout 30m -count=1 -test.parallel=1 -json
test_env_vars:
E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2
test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/contract-version1.4.toml

- id: ccip-smoke-usdc
path: integration-tests/ccip-tests/smoke/ccip_test.go
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/solidity-foundry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
{ "name": "functions", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": true, "run-forge-fmt": false }},
{ "name": "keystone", "setup": { "run-coverage": true, "min-coverage": 72.8, "run-gas-snapshot": false, "run-forge-fmt": false }},
{ "name": "l2ep", "setup": { "run-coverage": true, "min-coverage": 61.0, "run-gas-snapshot": true, "run-forge-fmt": false }},
{ "name": "liquiditymanager", "setup": { "run-coverage": true, "min-coverage": 46.3, "run-gas-snapshot": true, "run-forge-fmt": false }},
{ "name": "liquiditymanager", "setup": { "run-coverage": true, "min-coverage": 44, "run-gas-snapshot": true, "run-forge-fmt": false }},
{ "name": "llo-feeds", "setup": { "run-coverage": true, "min-coverage": 49.3, "run-gas-snapshot": true, "run-forge-fmt": false }},
{ "name": "operatorforwarder", "setup": { "run-coverage": true, "min-coverage": 55.7, "run-gas-snapshot": true, "run-forge-fmt": false }},
{ "name": "shared", "setup": { "run-coverage": true, "extra-coverage-params": "--no-match-path='*CallWithExactGas*' --ir-minimum", "min-coverage": 32.6, "run-gas-snapshot": true, "run-forge-fmt": false }},
Expand Down
10 changes: 10 additions & 0 deletions contracts/.changeset/modern-mayflies-give.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@chainlink/contracts': patch
---

allow multiple remote pools per chain selector


PR issue: CCIP-4269

Solidity Review issue: CCIP-3966
401 changes: 204 additions & 197 deletions contracts/gas-snapshots/ccip.gas-snapshot

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions contracts/gas-snapshots/liquiditymanager.gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ LiquidityManager_addLiquidity:test_addLiquiditySuccess() (gas: 279198)
LiquidityManager_rebalanceLiquidity:test_InsufficientLiquidityReverts() (gas: 206764)
LiquidityManager_rebalanceLiquidity:test_InvalidRemoteChainReverts() (gas: 192374)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess() (gas: 9141798)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 8942122)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 8937262)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 8865000)
LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382946)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 9246772)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 9241912)
LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 9169653)
LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382928)
LiquidityManager_receive:test_receive_success() (gas: 21182)
LiquidityManager_removeLiquidity:test_InsufficientLiquidityReverts() (gas: 184959)
LiquidityManager_removeLiquidity:test_OnlyFinanceRoleReverts() (gas: 10872)
LiquidityManager_removeLiquidity:test_removeLiquiditySuccess() (gas: 236379)
LiquidityManager_removeLiquidity:test_removeLiquiditySuccess() (gas: 236361)
LiquidityManager_setCrossChainRebalancer:test_OnlyOwnerReverts() (gas: 17005)
LiquidityManager_setCrossChainRebalancer:test_ZeroAddressReverts() (gas: 21669)
LiquidityManager_setCrossChainRebalancer:test_ZeroChainSelectorReverts() (gas: 13099)
Expand All @@ -19,7 +19,7 @@ LiquidityManager_setFinanceRole:test_OnlyOwnerReverts() (gas: 10987)
LiquidityManager_setFinanceRole:test_setFinanceRoleSuccess() (gas: 21836)
LiquidityManager_setLocalLiquidityContainer:test_OnlyOwnerReverts() (gas: 11030)
LiquidityManager_setLocalLiquidityContainer:test_ReverstWhen_CalledWithTheZeroAddress() (gas: 10621)
LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3479905)
LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3784709)
LiquidityManager_setMinimumLiquidity:test_OnlyOwnerReverts() (gas: 10925)
LiquidityManager_setMinimumLiquidity:test_setMinimumLiquiditySuccess() (gas: 36389)
LiquidityManager_withdrawERC20:test_withdrawERC20Reverts() (gas: 180396)
Expand Down
5 changes: 3 additions & 2 deletions contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/tok
contract BurnFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion {
using SafeERC20 for IBurnMintERC20;

string public constant override typeAndVersion = "BurnFromMintTokenPool 1.5.0";
string public constant override typeAndVersion = "BurnFromMintTokenPool 1.5.1";

constructor(
IBurnMintERC20 token,
uint8 localTokenDecimals,
address[] memory allowlist,
address rmnProxy,
address router
) TokenPool(token, allowlist, rmnProxy, router) {
) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {
// Some tokens allow burning from the sender without approval, but not all do.
// To be safe, we approve the pool to burn from the pool.
token.safeIncreaseAllowance(address(this), type(uint256).max);
Expand Down
5 changes: 3 additions & 2 deletions contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import {TokenPool} from "./TokenPool.sol";
/// If that is expected, please make sure the token's burner/minter roles are adjustable.
/// @dev This contract is a variant of BurnMintTokenPool that uses `burn(amount)`.
contract BurnMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion {
string public constant override typeAndVersion = "BurnMintTokenPool 1.5.0";
string public constant override typeAndVersion = "BurnMintTokenPool 1.5.1";

constructor(
IBurnMintERC20 token,
uint8 localTokenDecimals,
address[] memory allowlist,
address rmnProxy,
address router
) TokenPool(token, allowlist, rmnProxy, router) {}
) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {}

/// @inheritdoc BurnMintTokenPoolAbstract
function _burn(
Expand Down
15 changes: 11 additions & 4 deletions contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ abstract contract BurnMintTokenPoolAbstract is TokenPool {

emit Burned(msg.sender, lockOrBurnIn.amount);

return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""});
return Pool.LockOrBurnOutV1({
destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector),
destPoolData: _encodeLocalDecimals()
});
}

/// @notice Mint tokens from the pool to the recipient
Expand All @@ -35,11 +38,15 @@ abstract contract BurnMintTokenPoolAbstract is TokenPool {
) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) {
_validateReleaseOrMint(releaseOrMintIn);

// Calculate the local amount
uint256 localAmount =
_calculateLocalAmount(releaseOrMintIn.amount, _parseRemoteDecimals(releaseOrMintIn.sourcePoolData));

// Mint to the receiver
IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, releaseOrMintIn.amount);
IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, localAmount);

emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount);
emit Minted(msg.sender, releaseOrMintIn.receiver, localAmount);

return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount});
return Pool.ReleaseOrMintOutV1({destinationAmount: localAmount});
}
}
5 changes: 3 additions & 2 deletions contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ contract BurnWithFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion

constructor(
IBurnMintERC20 token,
uint8 localTokenDecimals,
address[] memory allowlist,
address rmnProxy,
address router
) TokenPool(token, allowlist, rmnProxy, router) {
) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {
// Some tokens allow burning from the sender without approval, but not all do.
// To be safe, we approve the pool to burn from the pool.
token.safeIncreaseAllowance(address(this), type(uint256).max);
Expand All @@ -37,6 +38,6 @@ contract BurnWithFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion
}

function typeAndVersion() external pure virtual override returns (string memory) {
return "BurnWithFromMintTokenPool 1.5.0";
return "BurnWithFromMintTokenPool 1.5.1";
}
}
20 changes: 14 additions & 6 deletions contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion

event LiquidityTransferred(address indexed from, uint256 amount);

string public constant override typeAndVersion = "LockReleaseTokenPool 1.5.0";
string public constant override typeAndVersion = "LockReleaseTokenPool 1.5.1";

/// @dev Whether or not the pool accepts liquidity.
/// External liquidity is not required when there is one canonical token deployed to a chain,
Expand All @@ -35,11 +35,12 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion

constructor(
IERC20 token,
uint8 localTokenDecimals,
address[] memory allowlist,
address rmnProxy,
bool acceptLiquidity,
address router
) TokenPool(token, allowlist, rmnProxy, router) {
) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {
i_acceptLiquidity = acceptLiquidity;
}

Expand All @@ -52,7 +53,10 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion

emit Locked(msg.sender, lockOrBurnIn.amount);

return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""});
return Pool.LockOrBurnOutV1({
destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector),
destPoolData: _encodeLocalDecimals()
});
}

/// @notice Release tokens from the pool to the recipient
Expand All @@ -62,12 +66,16 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion
) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) {
_validateReleaseOrMint(releaseOrMintIn);

// Calculate the local amount
uint256 localAmount =
_calculateLocalAmount(releaseOrMintIn.amount, _parseRemoteDecimals(releaseOrMintIn.sourcePoolData));

// Release to the recipient
getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount);
getToken().safeTransfer(releaseOrMintIn.receiver, localAmount);

emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount);
emit Released(msg.sender, releaseOrMintIn.receiver, localAmount);

return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount});
return Pool.ReleaseOrMintOutV1({destinationAmount: localAmount});
}

/// @inheritdoc IERC165
Expand Down
Loading
Loading