-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
55 changed files
with
4,282 additions
and
306 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.24; | ||
|
||
import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; | ||
|
||
import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; | ||
import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; | ||
|
||
contract USDCTokenPoolHelper is USDCTokenPool { | ||
constructor( | ||
ITokenMessenger tokenMessenger, | ||
IBurnMintERC20 token, | ||
address[] memory allowlist, | ||
address rmnProxy, | ||
address router | ||
) USDCTokenPool(tokenMessenger, token, allowlist, rmnProxy, router) {} | ||
|
||
function validateMessage(bytes memory usdcMessage, SourceTokenDataPayload memory sourceTokenData) external view { | ||
return _validateMessage(usdcMessage, sourceTokenData); | ||
} | ||
} |
89 changes: 89 additions & 0 deletions
89
...cts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.24; | ||
|
||
import {Pool} from "../../../libraries/Pool.sol"; | ||
import {RateLimiter} from "../../../libraries/RateLimiter.sol"; | ||
import {TokenPool} from "../../../pools/TokenPool.sol"; | ||
import {BurnFromMintTokenPoolSetup} from "./BurnFromMintTokenPoolSetup.t.sol"; | ||
|
||
import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; | ||
|
||
contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { | ||
function test_setup_Success() public view { | ||
assertEq(address(s_burnMintERC20), address(s_pool.getToken())); | ||
assertEq(address(s_mockRMN), s_pool.getRmnProxy()); | ||
assertEq(false, s_pool.getAllowListEnabled()); | ||
assertEq(type(uint256).max, s_burnMintERC20.allowance(address(s_pool), address(s_pool))); | ||
assertEq("BurnFromMintTokenPool 1.5.1", s_pool.typeAndVersion()); | ||
} | ||
|
||
function test_PoolBurn_Success() public { | ||
uint256 burnAmount = 20_000e18; | ||
|
||
deal(address(s_burnMintERC20), address(s_pool), burnAmount); | ||
assertEq(s_burnMintERC20.balanceOf(address(s_pool)), burnAmount); | ||
|
||
vm.startPrank(s_burnMintOnRamp); | ||
|
||
vm.expectEmit(); | ||
emit RateLimiter.TokensConsumed(burnAmount); | ||
|
||
vm.expectEmit(); | ||
emit IERC20.Transfer(address(s_pool), address(0), burnAmount); | ||
|
||
vm.expectEmit(); | ||
emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); | ||
|
||
bytes4 expectedSignature = bytes4(keccak256("burnFrom(address,uint256)")); | ||
vm.expectCall(address(s_burnMintERC20), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); | ||
|
||
s_pool.lockOrBurn( | ||
Pool.LockOrBurnInV1({ | ||
originalSender: OWNER, | ||
receiver: bytes(""), | ||
amount: burnAmount, | ||
remoteChainSelector: DEST_CHAIN_SELECTOR, | ||
localToken: address(s_burnMintERC20) | ||
}) | ||
); | ||
|
||
assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0); | ||
} | ||
|
||
// Should not burn tokens if cursed. | ||
function test_PoolBurnRevertNotHealthy_Revert() public { | ||
s_mockRMN.setGlobalCursed(true); | ||
uint256 before = s_burnMintERC20.balanceOf(address(s_pool)); | ||
vm.startPrank(s_burnMintOnRamp); | ||
|
||
vm.expectRevert(TokenPool.CursedByRMN.selector); | ||
s_pool.lockOrBurn( | ||
Pool.LockOrBurnInV1({ | ||
originalSender: OWNER, | ||
receiver: bytes(""), | ||
amount: 1e5, | ||
remoteChainSelector: DEST_CHAIN_SELECTOR, | ||
localToken: address(s_burnMintERC20) | ||
}) | ||
); | ||
|
||
assertEq(s_burnMintERC20.balanceOf(address(s_pool)), before); | ||
} | ||
|
||
function test_ChainNotAllowed_Revert() public { | ||
uint64 wrongChainSelector = 8838833; | ||
vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); | ||
s_pool.releaseOrMint( | ||
Pool.ReleaseOrMintInV1({ | ||
originalSender: bytes(""), | ||
receiver: OWNER, | ||
amount: 1, | ||
localToken: address(s_burnMintERC20), | ||
remoteChainSelector: wrongChainSelector, | ||
sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, | ||
sourcePoolData: _generateSourceTokenData().extraData, | ||
offchainTokenData: "" | ||
}) | ||
); | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.24; | ||
|
||
import {BurnFromMintTokenPool} from "../../../pools/BurnFromMintTokenPool.sol"; | ||
import {BurnMintSetup} from "../BurnMintTokenPool/BurnMintSetup.t.sol"; | ||
|
||
contract BurnFromMintTokenPoolSetup is BurnMintSetup { | ||
BurnFromMintTokenPool internal s_pool; | ||
|
||
function setUp() public virtual override { | ||
BurnMintSetup.setUp(); | ||
|
||
s_pool = new BurnFromMintTokenPool( | ||
s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) | ||
); | ||
s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); | ||
|
||
_applyChainUpdates(address(s_pool)); | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.24; | ||
|
||
import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; | ||
import {Router} from "../../../Router.sol"; | ||
import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; | ||
import {TokenPool} from "../../../pools/TokenPool.sol"; | ||
import {RouterSetup} from "../../router/RouterSetup.t.sol"; | ||
|
||
contract BurnMintSetup is RouterSetup { | ||
BurnMintERC20 internal s_burnMintERC20; | ||
address internal s_burnMintOffRamp = makeAddr("burn_mint_offRamp"); | ||
address internal s_burnMintOnRamp = makeAddr("burn_mint_onRamp"); | ||
|
||
address internal s_remoteBurnMintPool = makeAddr("remote_burn_mint_pool"); | ||
address internal s_remoteToken = makeAddr("remote_token"); | ||
|
||
function setUp() public virtual override { | ||
RouterSetup.setUp(); | ||
|
||
s_burnMintERC20 = new BurnMintERC20("Chainlink Token", "LINK", 18, 0, 0); | ||
} | ||
|
||
function _applyChainUpdates( | ||
address pool | ||
) internal { | ||
bytes[] memory remotePoolAddresses = new bytes[](1); | ||
remotePoolAddresses[0] = abi.encode(s_remoteBurnMintPool); | ||
|
||
TokenPool.ChainUpdate[] memory chainsToAdd = new TokenPool.ChainUpdate[](1); | ||
chainsToAdd[0] = TokenPool.ChainUpdate({ | ||
remoteChainSelector: DEST_CHAIN_SELECTOR, | ||
remotePoolAddresses: remotePoolAddresses, | ||
remoteTokenAddress: abi.encode(s_remoteToken), | ||
outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), | ||
inboundRateLimiterConfig: _getInboundRateLimiterConfig() | ||
}); | ||
|
||
BurnMintTokenPool(pool).applyChainUpdates(new uint64[](0), chainsToAdd); | ||
|
||
Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); | ||
onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_burnMintOnRamp}); | ||
Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); | ||
offRampUpdates[0] = Router.OffRamp({sourceChainSelector: DEST_CHAIN_SELECTOR, offRamp: s_burnMintOffRamp}); | ||
s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); | ||
} | ||
} |
102 changes: 102 additions & 0 deletions
102
contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.24; | ||
|
||
import {Pool} from "../../../libraries/Pool.sol"; | ||
import {RateLimiter} from "../../../libraries/RateLimiter.sol"; | ||
import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; | ||
import {TokenPool} from "../../../pools/TokenPool.sol"; | ||
import {BurnMintSetup} from "./BurnMintSetup.t.sol"; | ||
|
||
import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; | ||
|
||
contract BurnMintTokenPoolSetup is BurnMintSetup { | ||
BurnMintTokenPool internal s_pool; | ||
|
||
function setUp() public virtual override { | ||
BurnMintSetup.setUp(); | ||
|
||
s_pool = new BurnMintTokenPool( | ||
s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) | ||
); | ||
s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); | ||
|
||
_applyChainUpdates(address(s_pool)); | ||
} | ||
} | ||
|
||
contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { | ||
function test_Setup_Success() public view { | ||
assertEq(address(s_burnMintERC20), address(s_pool.getToken())); | ||
assertEq(address(s_mockRMN), s_pool.getRmnProxy()); | ||
assertEq(false, s_pool.getAllowListEnabled()); | ||
assertEq("BurnMintTokenPool 1.5.1", s_pool.typeAndVersion()); | ||
} | ||
|
||
function test_PoolBurn_Success() public { | ||
uint256 burnAmount = 20_000e18; | ||
|
||
deal(address(s_burnMintERC20), address(s_pool), burnAmount); | ||
assertEq(s_burnMintERC20.balanceOf(address(s_pool)), burnAmount); | ||
|
||
vm.startPrank(s_burnMintOnRamp); | ||
|
||
vm.expectEmit(); | ||
emit RateLimiter.TokensConsumed(burnAmount); | ||
|
||
vm.expectEmit(); | ||
emit IERC20.Transfer(address(s_pool), address(0), burnAmount); | ||
|
||
vm.expectEmit(); | ||
emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); | ||
|
||
bytes4 expectedSignature = bytes4(keccak256("burn(uint256)")); | ||
vm.expectCall(address(s_burnMintERC20), abi.encodeWithSelector(expectedSignature, burnAmount)); | ||
|
||
s_pool.lockOrBurn( | ||
Pool.LockOrBurnInV1({ | ||
originalSender: OWNER, | ||
receiver: bytes(""), | ||
amount: burnAmount, | ||
remoteChainSelector: DEST_CHAIN_SELECTOR, | ||
localToken: address(s_burnMintERC20) | ||
}) | ||
); | ||
|
||
assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0); | ||
} | ||
|
||
// Should not burn tokens if cursed. | ||
function test_PoolBurnRevertNotHealthy_Revert() public { | ||
s_mockRMN.setGlobalCursed(true); | ||
uint256 before = s_burnMintERC20.balanceOf(address(s_pool)); | ||
vm.startPrank(s_burnMintOnRamp); | ||
|
||
vm.expectRevert(TokenPool.CursedByRMN.selector); | ||
s_pool.lockOrBurn( | ||
Pool.LockOrBurnInV1({ | ||
originalSender: OWNER, | ||
receiver: bytes(""), | ||
amount: 1e5, | ||
remoteChainSelector: DEST_CHAIN_SELECTOR, | ||
localToken: address(s_burnMintERC20) | ||
}) | ||
); | ||
|
||
assertEq(s_burnMintERC20.balanceOf(address(s_pool)), before); | ||
} | ||
|
||
function test_ChainNotAllowed_Revert() public { | ||
uint64 wrongChainSelector = 8838833; | ||
|
||
vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); | ||
s_pool.lockOrBurn( | ||
Pool.LockOrBurnInV1({ | ||
originalSender: OWNER, | ||
receiver: bytes(""), | ||
amount: 1, | ||
remoteChainSelector: wrongChainSelector, | ||
localToken: address(s_burnMintERC20) | ||
}) | ||
); | ||
} | ||
} |
Oops, something went wrong.