-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'ccip-develop' into fix/onramp-allowlist-race-condition
- Loading branch information
Showing
10 changed files
with
2,995 additions
and
6 deletions.
There are no files selected for viewing
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
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
49 changes: 49 additions & 0 deletions
49
contracts/src/v0.8/ccip/pools/BurnWithFromMintRebasingTokenPool.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,49 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.24; | ||
|
||
import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; | ||
|
||
import {Pool} from "../libraries/Pool.sol"; | ||
import {BurnWithFromMintTokenPool} from "./BurnWithFromMintTokenPool.sol"; | ||
|
||
/// @notice This pool mints and burns a 3rd-party token. | ||
/// @dev This contract is a variant of BurnMintTokenPool that uses `burn(from, amount)`. | ||
/// @dev This contract supports minting tokens that do not mint the exact amount they are asked to mint. This can be | ||
/// used for rebasing tokens. NOTE: for true rebasing support, the lockOrBurn method must also be updated to support | ||
/// relaying the correct amount. | ||
contract BurnWithFromMintRebasingTokenPool is BurnWithFromMintTokenPool { | ||
error NegativeMintAmount(uint256 amountBurned); | ||
|
||
string public constant override typeAndVersion = "BurnWithFromMintRebasingTokenPool 1.5.0"; | ||
|
||
constructor( | ||
IBurnMintERC20 token, | ||
address[] memory allowlist, | ||
address rmnProxy, | ||
address router | ||
) BurnWithFromMintTokenPool(token, allowlist, rmnProxy, router) {} | ||
|
||
/// @notice Mint tokens from the pool to the recipient | ||
/// @dev The _validateReleaseOrMint check is an essential security check | ||
function releaseOrMint( | ||
Pool.ReleaseOrMintInV1 calldata releaseOrMintIn | ||
) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { | ||
_validateReleaseOrMint(releaseOrMintIn); | ||
|
||
uint256 balancePre = IBurnMintERC20(address(i_token)).balanceOf(releaseOrMintIn.receiver); | ||
|
||
// Mint to the receiver | ||
IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, releaseOrMintIn.amount); | ||
|
||
uint256 balancePost = IBurnMintERC20(address(i_token)).balanceOf(releaseOrMintIn.receiver); | ||
|
||
// Mint should not reduce the number of tokens in the receiver, if it does it will revert the call. | ||
if (balancePost < balancePre) { | ||
revert NegativeMintAmount(balancePre - balancePost); | ||
} | ||
|
||
emit Minted(msg.sender, releaseOrMintIn.receiver, balancePost - balancePre); | ||
|
||
return Pool.ReleaseOrMintOutV1({destinationAmount: balancePost - balancePre}); | ||
} | ||
} |
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
27 changes: 27 additions & 0 deletions
27
contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.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,27 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.24; | ||
|
||
import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; | ||
|
||
contract ERC20RebasingHelper is ERC20 { | ||
uint16 public s_multiplierPercentage = 100; | ||
bool public s_mintShouldBurn = false; | ||
|
||
constructor() ERC20("Rebasing", "REB") {} | ||
|
||
function mint(address to, uint256 amount) external { | ||
if (!s_mintShouldBurn) { | ||
_mint(to, amount * s_multiplierPercentage / 100); | ||
return; | ||
} | ||
_burn(to, amount * s_multiplierPercentage / 100); | ||
} | ||
|
||
function setMultiplierPercentage(uint16 multiplierPercentage) external { | ||
s_multiplierPercentage = multiplierPercentage; | ||
} | ||
|
||
function setMintShouldBurn(bool mintShouldBurn) external { | ||
s_mintShouldBurn = mintShouldBurn; | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
contracts/src/v0.8/ccip/test/pools/BurnWithFromMintRebasingTokenPool.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,87 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.24; | ||
|
||
import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; | ||
|
||
import {Pool} from "../../libraries/Pool.sol"; | ||
import {BurnWithFromMintRebasingTokenPool} from "../../pools/BurnWithFromMintRebasingTokenPool.sol"; | ||
import {BurnMintSetup} from "./BurnMintSetup.t.sol"; | ||
|
||
import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; | ||
import {ERC20RebasingHelper} from "../helpers/ERC20RebasingHelper.sol"; | ||
|
||
contract BurnWithFromMintRebasingTokenPoolSetup is BurnMintSetup { | ||
BurnWithFromMintRebasingTokenPool internal s_pool; | ||
ERC20RebasingHelper internal s_rebasingToken; | ||
|
||
function setUp() public virtual override { | ||
BurnMintSetup.setUp(); | ||
|
||
s_rebasingToken = new ERC20RebasingHelper(); | ||
|
||
s_pool = new BurnWithFromMintRebasingTokenPool( | ||
IBurnMintERC20(address(s_rebasingToken)), new address[](0), address(s_mockRMN), address(s_sourceRouter) | ||
); | ||
|
||
_applyChainUpdates(address(s_pool)); | ||
|
||
deal(address(s_rebasingToken), OWNER, 1e18); | ||
|
||
vm.startPrank(s_burnMintOffRamp); | ||
} | ||
} | ||
|
||
contract BurnWithFromMintTokenPool_releaseOrMint is BurnWithFromMintRebasingTokenPoolSetup { | ||
function test_Setup_Success() public view { | ||
assertEq(address(s_rebasingToken), address(s_pool.getToken())); | ||
assertEq(address(s_mockRMN), s_pool.getRmnProxy()); | ||
assertEq(false, s_pool.getAllowListEnabled()); | ||
assertEq(type(uint256).max, s_rebasingToken.allowance(address(s_pool), address(s_pool))); | ||
assertEq("BurnWithFromMintRebasingTokenPool 1.5.0", s_pool.typeAndVersion()); | ||
} | ||
|
||
function test_releaseOrMint_Success() public { | ||
uint256 amount = 1000; | ||
uint256 balancePre = s_rebasingToken.balanceOf(address(OWNER)); | ||
|
||
Pool.ReleaseOrMintOutV1 memory releaseOrMintOut = s_pool.releaseOrMint(_getReleaseOrMintIn(amount)); | ||
|
||
assertEq(amount, releaseOrMintOut.destinationAmount); | ||
assertEq(balancePre + amount, s_rebasingToken.balanceOf(address(OWNER))); | ||
} | ||
|
||
function testFuzz_releaseOrMint_rebasing_success(uint16 multiplierPercentage) public { | ||
uint256 amount = 1000; | ||
uint256 expectedAmount = amount * multiplierPercentage / 100; | ||
s_rebasingToken.setMultiplierPercentage(multiplierPercentage); | ||
|
||
uint256 balancePre = s_rebasingToken.balanceOf(address(OWNER)); | ||
|
||
Pool.ReleaseOrMintOutV1 memory releaseOrMintOut = s_pool.releaseOrMint(_getReleaseOrMintIn(amount)); | ||
|
||
assertEq(expectedAmount, releaseOrMintOut.destinationAmount); | ||
assertEq(balancePre + expectedAmount, s_rebasingToken.balanceOf(address(OWNER))); | ||
} | ||
|
||
function test_releaseOrMint_NegativeMintAmount_reverts() public { | ||
uint256 amount = 1000; | ||
s_rebasingToken.setMintShouldBurn(true); | ||
|
||
vm.expectRevert(abi.encodeWithSelector(BurnWithFromMintRebasingTokenPool.NegativeMintAmount.selector, amount)); | ||
|
||
s_pool.releaseOrMint(_getReleaseOrMintIn(amount)); | ||
} | ||
|
||
function _getReleaseOrMintIn(uint256 amount) internal view returns (Pool.ReleaseOrMintInV1 memory) { | ||
return Pool.ReleaseOrMintInV1({ | ||
originalSender: bytes(""), | ||
receiver: OWNER, | ||
amount: amount, | ||
localToken: address(s_rebasingToken), | ||
remoteChainSelector: DEST_CHAIN_SELECTOR, | ||
sourcePoolAddress: abi.encode(s_remoteBurnMintPool), | ||
sourcePoolData: "", | ||
offchainTokenData: "" | ||
}); | ||
} | ||
} |
2,818 changes: 2,818 additions & 0 deletions
2,818
...erated/burn_with_from_mint_rebasing_token_pool/burn_with_from_mint_rebasing_token_pool.go
Large diffs are not rendered by default.
Oops, something went wrong.
4 changes: 2 additions & 2 deletions
4
...hwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go
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
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