diff --git a/contracts/src/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPoolOld.sol b/contracts/src/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPoolOld.sol new file mode 100644 index 0000000000..16ab280431 --- /dev/null +++ b/contracts/src/v0.8/ccip/pools/GHO/UpgradeableBurnMintTokenPoolOld.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {Initializable} from "solidity-utils/contracts/transparent-proxy/Initializable.sol"; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {UpgradeableTokenPool} from "./UpgradeableTokenPool.sol"; +import {UpgradeableBurnMintTokenPoolAbstract} from "./UpgradeableBurnMintTokenPoolAbstract.sol"; + +import {IRouter} from "../../interfaces/IRouter.sol"; + +/// @title UpgradeableBurnMintTokenPoolOld +/// @author Aave Labs +/// @notice Upgradeable version of Chainlink's CCIP BurnMintTokenPool +/// @dev Contract adaptations: +/// - Implementation of Initializable to allow upgrades +/// - Move of allowlist and router definition to initialization stage +contract UpgradeableBurnMintTokenPoolOld is Initializable, UpgradeableBurnMintTokenPoolAbstract, ITypeAndVersion { + string public constant override typeAndVersion = "BurnMintTokenPool 1.4.0"; + + /// @dev Constructor + /// @param token The bridgeable token that is managed by this pool. + /// @param armProxy The address of the arm proxy + /// @param allowlistEnabled True if pool is set to access-controlled mode, false otherwise + constructor( + address token, + address armProxy, + bool allowlistEnabled + ) UpgradeableTokenPool(IBurnMintERC20(token), armProxy, allowlistEnabled) {} + + /// @dev Initializer + /// @dev The address passed as `owner` must accept ownership after initialization. + /// @dev The `allowlist` is only effective if pool is set to access-controlled mode + /// @param owner The address of the owner + /// @param allowlist A set of addresses allowed to trigger lockOrBurn as original senders + /// @param router The address of the router + function initialize(address owner, address[] memory allowlist, address router) public virtual initializer { + if (owner == address(0)) revert ZeroAddressNotAllowed(); + if (router == address(0)) revert ZeroAddressNotAllowed(); + _transferOwnership(owner); + + s_router = IRouter(router); + + // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. + if (i_allowlistEnabled) { + _applyAllowListUpdates(new address[](0), allowlist); + } + } + + /// @inheritdoc UpgradeableBurnMintTokenPoolAbstract + function _burn(uint256 amount) internal virtual override { + IBurnMintERC20(address(i_token)).burn(amount); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/GHO/GhoBaseTest.t.sol b/contracts/src/v0.8/ccip/test/pools/GHO/GhoBaseTest.t.sol index 66d6fc63b5..921680f9c8 100644 --- a/contracts/src/v0.8/ccip/test/pools/GHO/GhoBaseTest.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/GHO/GhoBaseTest.t.sol @@ -8,6 +8,7 @@ import {IBurnMintERC20} from "../../../../shared/token/ERC20/IBurnMintERC20.sol" import {IPool} from "../../../interfaces/pools/IPool.sol"; import {UpgradeableLockReleaseTokenPool} from "../../../pools/GHO/UpgradeableLockReleaseTokenPool.sol"; import {UpgradeableBurnMintTokenPool} from "../../../pools/GHO/UpgradeableBurnMintTokenPool.sol"; +import {UpgradeableBurnMintTokenPoolOld} from "../../../pools/GHO/UpgradeableBurnMintTokenPoolOld.sol"; import {UpgradeableTokenPool} from "../../../pools/GHO/UpgradeableTokenPool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; import {BaseTest} from "../../BaseTest.t.sol"; @@ -65,6 +66,50 @@ abstract contract GhoBaseTest is BaseTest { return address(tokenPoolProxy); } + function _deployUpgradeableBurnMintTokenPoolOld( + address ghoToken, + address arm, + address router, + address owner, + address proxyAdmin + ) internal returns (address) { + // Deploy BurnMintTokenPool for GHO token on source chain + UpgradeableBurnMintTokenPoolOld tokenPoolImpl = new UpgradeableBurnMintTokenPoolOld(ghoToken, arm, false); + // proxy deploy and init + address[] memory emptyArray = new address[](0); + bytes memory tokenPoolInitParams = abi.encodeWithSignature( + "initialize(address,address[],address)", + owner, + emptyArray, + router + ); + TransparentUpgradeableProxy tokenPoolProxy = new TransparentUpgradeableProxy( + address(tokenPoolImpl), + proxyAdmin, + tokenPoolInitParams + ); + // Manage ownership + vm.stopPrank(); + vm.prank(owner); + UpgradeableBurnMintTokenPoolOld(address(tokenPoolProxy)).acceptOwnership(); + vm.startPrank(OWNER); + + return address(tokenPoolProxy); + } + + function _upgradeUpgradeableBurnMintTokenPool( + address payable tokenPoolProxy, + address ghoToken, + address arm, + address proxyAdmin + ) internal { + // Deploy BurnMintTokenPool for GHO token on source chain + UpgradeableBurnMintTokenPool tokenPoolImpl = new UpgradeableBurnMintTokenPool(ghoToken, arm, false); + // proxy upgrade + vm.startPrank(proxyAdmin); + TransparentUpgradeableProxy(tokenPoolProxy).upgradeTo(address(tokenPoolImpl)); + } + function _deployUpgradeableLockReleaseTokenPool( address ghoToken, address arm, diff --git a/contracts/src/v0.8/ccip/test/pools/GHO/GhoTokenPoolRemoteOld.t.sol b/contracts/src/v0.8/ccip/test/pools/GHO/GhoTokenPoolRemoteOld.t.sol new file mode 100644 index 0000000000..6bea004e3f --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/GHO/GhoTokenPoolRemoteOld.t.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {GhoToken} from "@aave/gho-core/gho/GhoToken.sol"; +import {TransparentUpgradeableProxy} from "solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol"; + +import {stdError} from "forge-std/Test.sol"; +import {MockUpgradeable} from "../../mocks/MockUpgradeable.sol"; +import {UpgradeableTokenPool} from "../../../pools/GHO/UpgradeableTokenPool.sol"; +import {EVM2EVMOnRamp} from "../../../onRamp/EVM2EVMOnRamp.sol"; +import {EVM2EVMOffRamp} from "../../../offRamp/EVM2EVMOffRamp.sol"; +import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; +import {UpgradeableBurnMintTokenPool} from "../../../pools/GHO/UpgradeableBurnMintTokenPool.sol"; +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; +import {GhoTokenPoolRemoteSetupOld} from "./GhoTokenPoolRemoteSetupOld.t.sol"; + +contract GhoTokenPoolRemoteOld_setRateLimitAdmin is GhoTokenPoolRemoteSetupOld { + /*function testSetRateLimitAdminSuccess() public { + assertEq(address(0), s_pool.getRateLimitAdmin()); + changePrank(AAVE_DAO); + s_pool.setRateLimitAdmin(OWNER); + assertEq(OWNER, s_pool.getRateLimitAdmin()); + }*/ + + // Reverts + + // Should fail because old implementation does not have rate limiter + function testSetRateLimitRevert() public { + changePrank(AAVE_DAO); + vm.expectRevert(); + s_pool.setRateLimitAdmin(OWNER); + } + + function testSetRateLimitAfterUpgrade() public { + _upgradeUpgradeableBurnMintTokenPool(payable(address(s_pool)), address(s_burnMintERC677), ARM_PROXY, PROXY_ADMIN); + changePrank(AAVE_DAO); + s_pool.setRateLimitAdmin(OWNER); + assertEq(OWNER, s_pool.getRateLimitAdmin()); + } + + /* + function testSetRateLimitAdminReverts() public { + vm.startPrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + s_pool.setRateLimitAdmin(STRANGER); + } + */ +} diff --git a/contracts/src/v0.8/ccip/test/pools/GHO/GhoTokenPoolRemoteSetupOld.t.sol b/contracts/src/v0.8/ccip/test/pools/GHO/GhoTokenPoolRemoteSetupOld.t.sol new file mode 100644 index 0000000000..784481b362 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/GHO/GhoTokenPoolRemoteSetupOld.t.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {GhoToken} from "@aave/gho-core/gho/GhoToken.sol"; +import {TransparentUpgradeableProxy} from "solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol"; + +import {stdError} from "forge-std/Test.sol"; +import {UpgradeableTokenPool} from "../../../pools/GHO/UpgradeableTokenPool.sol"; +import {Router} from "../../../Router.sol"; +import {BurnMintERC677} from "../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {UpgradeableBurnMintTokenPoolOld} from "../../../pools/GHO/UpgradeableBurnMintTokenPoolOld.sol"; +import {UpgradeableBurnMintTokenPool} from "../../../pools/GHO/UpgradeableBurnMintTokenPool.sol"; +import {RouterSetup} from "../../router/RouterSetup.t.sol"; +import {BaseTest} from "../../BaseTest.t.sol"; +import {GhoBaseTest} from "./GhoBaseTest.t.sol"; + +contract GhoTokenPoolRemoteSetupOld is RouterSetup, GhoBaseTest { + event Transfer(address indexed from, address indexed to, uint256 value); + event TokensConsumed(uint256 tokens); + event Burned(address indexed sender, uint256 amount); + + BurnMintERC677 internal s_burnMintERC677; + address internal s_burnMintOffRamp = makeAddr("burn_mint_offRamp"); + address internal s_burnMintOnRamp = makeAddr("burn_mint_onRamp"); + + UpgradeableBurnMintTokenPool internal s_pool; + + function setUp() public virtual override(RouterSetup, BaseTest) { + RouterSetup.setUp(); + + // GHO deployment + GhoToken ghoToken = new GhoToken(AAVE_DAO); + s_burnMintERC677 = BurnMintERC677(address(ghoToken)); + + s_pool = UpgradeableBurnMintTokenPool( + _deployUpgradeableBurnMintTokenPoolOld( + address(s_burnMintERC677), + address(s_mockARM), + address(s_sourceRouter), + AAVE_DAO, + PROXY_ADMIN + ) + ); + + // Give mint and burn privileges to source UpgradeableTokenPool (GHO-specific related) + vm.stopPrank(); + vm.startPrank(AAVE_DAO); + GhoToken(address(s_burnMintERC677)).grantRole( + GhoToken(address(s_burnMintERC677)).FACILITATOR_MANAGER_ROLE(), + AAVE_DAO + ); + GhoToken(address(s_burnMintERC677)).addFacilitator(address(s_pool), "UpgradeableTokenPool", type(uint128).max); + vm.stopPrank(); + + _applyChainUpdates(address(s_pool)); + } + + function _applyChainUpdates(address pool) internal { + UpgradeableTokenPool.ChainUpdate[] memory chains = new UpgradeableTokenPool.ChainUpdate[](1); + chains[0] = UpgradeableTokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + allowed: true, + outboundRateLimiterConfig: getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: getInboundRateLimiterConfig() + }); + + vm.startPrank(AAVE_DAO); + UpgradeableBurnMintTokenPool(pool).applyChainUpdates(chains); + vm.stopPrank(); + vm.startPrank(OWNER); + + 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); + } +}