From 9ee018ca43c707a69670f519960fba00f1182351 Mon Sep 17 00:00:00 2001 From: Le Yu Date: Thu, 21 Mar 2024 17:17:36 -0400 Subject: [PATCH 01/14] Add deployAdminAndProxyContracts(). Update CollateralVault and Native to use deployAdminAndProxyContracts --- .../token/HypERC20CollateralVaultDeposit.sol | 8 ++ solidity/contracts/token/HypNative.sol | 8 ++ .../HypERC20CollateralVaultDeposit.t.sol | 20 +++- typescript/sdk/src/token/deploy.ts | 102 +++++++++++++++--- 4 files changed, 123 insertions(+), 15 deletions(-) diff --git a/solidity/contracts/token/HypERC20CollateralVaultDeposit.sol b/solidity/contracts/token/HypERC20CollateralVaultDeposit.sol index b4085a9b2c..ac94d4749d 100644 --- a/solidity/contracts/token/HypERC20CollateralVaultDeposit.sol +++ b/solidity/contracts/token/HypERC20CollateralVaultDeposit.sol @@ -21,7 +21,15 @@ contract HypERC20CollateralVaultDeposit is HypERC20Collateral { address _mailbox ) HypERC20Collateral(_vault.asset(), _mailbox) { vault = _vault; + } + + function initialize( + address _hook, + address _interchainSecurityModule, + address _owner + ) public initializer { wrappedToken.approve(address(vault), type(uint256).max); + _MailboxClient_initialize(_hook, _interchainSecurityModule, _owner); } /** diff --git a/solidity/contracts/token/HypNative.sol b/solidity/contracts/token/HypNative.sol index 7dd9bbbd0a..115df1a2dd 100644 --- a/solidity/contracts/token/HypNative.sol +++ b/solidity/contracts/token/HypNative.sol @@ -20,6 +20,14 @@ contract HypNative is TokenRouter { constructor(address _mailbox) TokenRouter(_mailbox) {} + function initialize( + address _hook, + address _interchainSecurityModule, + address _owner + ) public initializer { + _MailboxClient_initialize(_hook, _interchainSecurityModule, _owner); + } + /** * @inheritdoc TokenRouter * @dev uses (`msg.value` - `_amount`) as interchain gas payment and `msg.sender` as refund address. diff --git a/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol b/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol index bf01665366..a46ecf7de4 100644 --- a/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol +++ b/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol @@ -14,6 +14,8 @@ pragma solidity ^0.8.13; @@@@@@@@@ @@@@@@@@*/ import "forge-std/Test.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + import {ERC4626Test} from "../../contracts/test/ERC4626/ERC4626Test.sol"; import {TypeCasts} from "../../contracts/libs/TypeCasts.sol"; import {HypTokenTest} from "./HypERC20.t.sol"; @@ -24,6 +26,7 @@ import "../../contracts/test/ERC4626/ERC4626Test.sol"; contract HypERC20CollateralVaultDepositTest is HypTokenTest { using TypeCasts for address; uint256 constant DUST_AMOUNT = 1e11; + address internal constant PROXY_ADMIN = address(0x37); HypERC20CollateralVaultDeposit internal erc20CollateralVaultDeposit; ERC4626Test vault; @@ -31,10 +34,21 @@ contract HypERC20CollateralVaultDepositTest is HypTokenTest { super.setUp(); vault = new ERC4626Test(address(primaryToken), "Regular Vault", "RV"); - localToken = new HypERC20CollateralVaultDeposit( - vault, - address(localMailbox) + HypERC20CollateralVaultDeposit implementation = new HypERC20CollateralVaultDeposit( + vault, + address(localMailbox) + ); + TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( + address(implementation), + PROXY_ADMIN, + abi.encodeWithSelector( + HypERC20CollateralVaultDeposit.initialize.selector, + address(address(noopHook)), + address(igp), + address(this) + ) ); + localToken = HypERC20CollateralVaultDeposit(address(proxy)); erc20CollateralVaultDeposit = HypERC20CollateralVaultDeposit( address(localToken) ); diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index b6a7d25aee..f4aa78a769 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import debug from 'debug'; -import { providers } from 'ethers'; +import { constants, ethers, providers } from 'ethers'; import { ERC20__factory, @@ -10,15 +10,18 @@ import { HypERC721, HypERC721Collateral, HypNative, + ProxyAdmin__factory, + TimelockController, + TimelockController__factory, } from '@hyperlane-xyz/core'; -import { objKeys, objMap } from '@hyperlane-xyz/utils'; +import { eqAddress, objKeys, objMap } from '@hyperlane-xyz/utils'; import { HyperlaneContracts } from '../contracts/types'; import { ContractVerifier } from '../deploy/verify/ContractVerifier'; import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory'; import { MultiProvider } from '../providers/MultiProvider'; import { GasRouterDeployer } from '../router/GasRouterDeployer'; -import { GasConfig, RouterConfig } from '../router/types'; +import { GasConfig, ProxiedRouterConfig, RouterConfig } from '../router/types'; import { ChainMap, ChainName } from '../types'; import { @@ -139,6 +142,12 @@ export class HypERC20Deployer extends GasRouterDeployer< | TokenType.fastCollateral | TokenType.collateral | TokenType.collateralVault; + const constructorArgs = [config.token, config.mailbox]; + const initializeArgs = [ + ethers.constants.AddressZero, + ethers.constants.AddressZero, + config.owner, + ]; switch (config.type) { case TokenType.fastSynthetic || TokenType.fastCollateral: contractName = TokenType.fastCollateral; @@ -152,23 +161,92 @@ export class HypERC20Deployer extends GasRouterDeployer< default: throw new Error(`Unknown collateral type ${config.type}`); } - return this.deployContract(chain, contractName, [ - config.token, - config.mailbox, - ]); + + return this.deployAdminAndProxyContracts( + chain, + config, + contractName, + constructorArgs, + initializeArgs, + ); + } + + // @dev this is a copy of ProxiedRouterDeployer.deployContracts(). + // Here because ProxiedRouterDeployer assumes a single contract, but here is deploying multiple contracts + // Please remove once ProxiedRouterDeployer is refactored! + async deployAdminAndProxyContracts( + chain: ChainName, + config: ERC20RouterConfig & ProxiedRouterConfig, + contractName: K, + constructorArgs: any, + initializeArgs?: any, + ): Promise { + const proxyAdmin = await this.deployContractFromFactory( + chain, + new ProxyAdmin__factory(), + 'proxyAdmin', + [], + ); + + let timelockController: TimelockController; + let adminOwner: string; + if (config.timelock) { + timelockController = await this.deployTimelock(chain, config.timelock); + adminOwner = timelockController.address; + } else { + timelockController = TimelockController__factory.connect( + constants.AddressZero, + this.multiProvider.getProvider(chain), + ); + adminOwner = config.owner; + } + + await super.runIfOwner(chain, proxyAdmin, async () => { + this.logger(`Checking ownership of proxy admin to ${adminOwner}`); + + if (!eqAddress(await proxyAdmin.owner(), adminOwner)) { + this.logger(`Transferring ownership of proxy admin to ${adminOwner}`); + return this.multiProvider.handleTx( + chain, + proxyAdmin.transferOwnership(adminOwner), + ); + } + return; + }); + return this.deployProxiedContract( + chain, + contractName, + proxyAdmin.address, + constructorArgs, + initializeArgs, + ); } protected async deployNative( chain: ChainName, config: HypNativeConfig, ): Promise { + const initializeArgs = [ + ethers.constants.AddressZero, + ethers.constants.AddressZero, + config.owner, + ]; if (config.scale) { - return this.deployContract(chain, TokenType.nativeScaled, [ - config.scale, - config.mailbox, - ]); + return this.deployAdminAndProxyContracts( + chain, + config, + TokenType.nativeScaled, + [config.scale, config.mailbox], + initializeArgs, + ); } else { - return this.deployContract(chain, TokenType.native, [config.mailbox]); + return this.deployAdminAndProxyContracts( + chain, + config, + TokenType.native, + [config.mailbox], + initializeArgs, + ); } } From 4bd2d7db6d426ac8e4b487c2a7e53107e46311a2 Mon Sep 17 00:00:00 2001 From: Le Yu Date: Mon, 25 Mar 2024 14:33:16 -0400 Subject: [PATCH 02/14] Add routerContractNameConstant for backwards compatibility, refactor routerContractName to be an abstract getter function. Implement constructorArgs and initializeArgs in token/deploy. Clean up --- solidity/contracts/token/HypERC20.sol | 6 +- .../contracts/token/HypERC20Collateral.sol | 8 + .../token/HypERC20CollateralVaultDeposit.sol | 2 +- solidity/test/token/HypERC20.t.sol | 51 +++- .../HypERC20CollateralVaultDeposit.t.sol | 1 - solidity/test/token/HypNativeScaled.t.sol | 1 + .../account/InterchainAccountDeployer.ts | 8 +- .../LiquidityLayerRouterDeployer.ts | 8 +- .../query/InterchainQueryDeployer.ts | 8 +- .../sdk/src/router/GasRouterDeployer.ts | 15 +- .../sdk/src/router/ProxiedRouterDeployer.ts | 10 +- typescript/sdk/src/token/contracts.ts | 4 + typescript/sdk/src/token/deploy.ts | 260 +++++++----------- 13 files changed, 193 insertions(+), 189 deletions(-) diff --git a/solidity/contracts/token/HypERC20.sol b/solidity/contracts/token/HypERC20.sol index b3f815d948..80e7bb6cd9 100644 --- a/solidity/contracts/token/HypERC20.sol +++ b/solidity/contracts/token/HypERC20.sol @@ -26,11 +26,15 @@ contract HypERC20 is ERC20Upgradeable, TokenRouter { function initialize( uint256 _totalSupply, string memory _name, - string memory _symbol + string memory _symbol, + address _hook, + address _interchainSecurityModule, + address _owner ) external initializer { // Initialize ERC20 metadata __ERC20_init(_name, _symbol); _mint(msg.sender, _totalSupply); + _MailboxClient_initialize(_hook, _interchainSecurityModule, _owner); } function decimals() public view override returns (uint8) { diff --git a/solidity/contracts/token/HypERC20Collateral.sol b/solidity/contracts/token/HypERC20Collateral.sol index 00f0acd9a5..858a3140b9 100644 --- a/solidity/contracts/token/HypERC20Collateral.sol +++ b/solidity/contracts/token/HypERC20Collateral.sol @@ -25,6 +25,14 @@ contract HypERC20Collateral is TokenRouter { wrappedToken = IERC20(erc20); } + function initialize( + address _hook, + address _interchainSecurityModule, + address _owner + ) public virtual initializer { + _MailboxClient_initialize(_hook, _interchainSecurityModule, _owner); + } + function balanceOf( address _account ) external view override returns (uint256) { diff --git a/solidity/contracts/token/HypERC20CollateralVaultDeposit.sol b/solidity/contracts/token/HypERC20CollateralVaultDeposit.sol index ac94d4749d..11b530d6ac 100644 --- a/solidity/contracts/token/HypERC20CollateralVaultDeposit.sol +++ b/solidity/contracts/token/HypERC20CollateralVaultDeposit.sol @@ -27,7 +27,7 @@ contract HypERC20CollateralVaultDeposit is HypERC20Collateral { address _hook, address _interchainSecurityModule, address _owner - ) public initializer { + ) public override initializer { wrappedToken.approve(address(vault), type(uint256).max); _MailboxClient_initialize(_hook, _interchainSecurityModule, _owner); } diff --git a/solidity/test/token/HypERC20.t.sol b/solidity/test/token/HypERC20.t.sol index 0b196f3c66..86195a05dd 100644 --- a/solidity/test/token/HypERC20.t.sol +++ b/solidity/test/token/HypERC20.t.sol @@ -14,6 +14,7 @@ pragma solidity ^0.8.13; @@@@@@@@@ @@@@@@@@*/ import "forge-std/Test.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {TypeCasts} from "../../contracts/libs/TypeCasts.sol"; import {TestMailbox} from "../../contracts/test/TestMailbox.sol"; @@ -40,6 +41,7 @@ abstract contract HypTokenTest is Test { string internal constant SYMBOL = "HYP"; address internal constant ALICE = address(0x1); address internal constant BOB = address(0x2); + address internal constant PROXY_ADMIN = address(0x37); ERC20Test internal primaryToken; TokenRouter internal localToken; @@ -73,8 +75,24 @@ abstract contract HypTokenTest is Test { REQUIRED_VALUE = noopHook.quoteDispatch("", ""); - remoteToken = new HypERC20(DECIMALS, address(remoteMailbox)); - remoteToken.initialize(TOTAL_SUPPLY, NAME, SYMBOL); + HypERC20 implementation = new HypERC20( + DECIMALS, + address(remoteMailbox) + ); + TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( + address(implementation), + PROXY_ADMIN, + abi.encodeWithSelector( + HypERC20.initialize.selector, + TOTAL_SUPPLY, + NAME, + SYMBOL, + address(address(noopHook)), + address(igp), + address(this) + ) + ); + remoteToken = HypERC20(address(proxy)); remoteToken.enrollRemoteRouter( ORIGIN, address(localToken).addressToBytes32() @@ -188,10 +206,24 @@ contract HypERC20Test is HypTokenTest { function setUp() public override { super.setUp(); - localToken = new HypERC20(DECIMALS, address(localMailbox)); - erc20Token = HypERC20(address(localToken)); + HypERC20 implementation = new HypERC20(DECIMALS, address(localMailbox)); + TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( + address(implementation), + PROXY_ADMIN, + abi.encodeWithSelector( + HypERC20.initialize.selector, + TOTAL_SUPPLY, + NAME, + SYMBOL, + address(address(noopHook)), + address(igp), + address(this) + ) + ); + // localToken = new HypERC20(DECIMALS, address(localMailbox)); + erc20Token = HypERC20(address(proxy)); - erc20Token.initialize(TOTAL_SUPPLY, NAME, SYMBOL); + // erc20Token.initialize(TOTAL_SUPPLY, NAME, SYMBOL); erc20Token.enrollRemoteRouter( DESTINATION, @@ -204,7 +236,14 @@ contract HypERC20Test is HypTokenTest { function testInitialize_revert_ifAlreadyInitialized() public { vm.expectRevert("Initializable: contract is already initialized"); - erc20Token.initialize(TOTAL_SUPPLY, NAME, SYMBOL); + erc20Token.initialize( + TOTAL_SUPPLY, + NAME, + SYMBOL, + address(address(noopHook)), + address(igp), + BOB + ); } function testTotalSupply() public { diff --git a/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol b/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol index a46ecf7de4..3dc4e75323 100644 --- a/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol +++ b/solidity/test/token/HypERC20CollateralVaultDeposit.t.sol @@ -26,7 +26,6 @@ import "../../contracts/test/ERC4626/ERC4626Test.sol"; contract HypERC20CollateralVaultDepositTest is HypTokenTest { using TypeCasts for address; uint256 constant DUST_AMOUNT = 1e11; - address internal constant PROXY_ADMIN = address(0x37); HypERC20CollateralVaultDeposit internal erc20CollateralVaultDeposit; ERC4626Test vault; diff --git a/solidity/test/token/HypNativeScaled.t.sol b/solidity/test/token/HypNativeScaled.t.sol index 09865606af..a9499d056f 100644 --- a/solidity/test/token/HypNativeScaled.t.sol +++ b/solidity/test/token/HypNativeScaled.t.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0; import "forge-std/Test.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {HypNativeScaled} from "../../contracts/token/extensions/HypNativeScaled.sol"; import {HypERC20} from "../../contracts/token/HypERC20.sol"; diff --git a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts index 329539150f..44170d5b12 100644 --- a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts +++ b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts @@ -19,7 +19,7 @@ export class InterchainAccountDeployer extends ProxiedRouterDeployer< InterchainAccountFactories, 'interchainAccountRouter' > { - readonly routerContractName = 'interchainAccountRouter'; + readonly routerContractNameConstant = 'interchainAccountRouter'; constructor( multiProvider: MultiProvider, @@ -30,6 +30,12 @@ export class InterchainAccountDeployer extends ProxiedRouterDeployer< }); } + routerContractName( + _: RouterConfig, + ): K { + return 'interchainAccountRouter' as K; + } + async constructorArgs(_: string, config: RouterConfig): Promise<[string]> { return [config.mailbox]; } diff --git a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts index 1662fc4403..3296b74f00 100644 --- a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts +++ b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts @@ -56,7 +56,7 @@ export class LiquidityLayerDeployer extends ProxiedRouterDeployer< LiquidityLayerFactories, 'liquidityLayerRouter' > { - readonly routerContractName = 'liquidityLayerRouter'; + readonly routerContractNameConstant = 'liquidityLayerRouter'; constructor( multiProvider: MultiProvider, @@ -67,6 +67,12 @@ export class LiquidityLayerDeployer extends ProxiedRouterDeployer< }); } + routerContractName( + _: RouterConfig, + ): K { + return 'liquidityLayerRouter' as K; + } + async constructorArgs( _: string, config: LiquidityLayerConfig, diff --git a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts index 51af12bb9e..a45a08e062 100644 --- a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts +++ b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts @@ -17,7 +17,7 @@ export class InterchainQueryDeployer extends ProxiedRouterDeployer< InterchainQueryFactories, 'interchainQueryRouter' > { - readonly routerContractName = 'interchainQueryRouter'; + readonly routerContractNameConstant = 'interchainQueryRouter'; constructor( multiProvider: MultiProvider, @@ -28,6 +28,12 @@ export class InterchainQueryDeployer extends ProxiedRouterDeployer< }); } + routerContractName( + _: RouterConfig, + ): K { + return 'interchainQueryRouter' as K; + } + async constructorArgs(_: string, config: RouterConfig): Promise<[string]> { return [config.mailbox]; } diff --git a/typescript/sdk/src/router/GasRouterDeployer.ts b/typescript/sdk/src/router/GasRouterDeployer.ts index a219c36e72..c9358565d0 100644 --- a/typescript/sdk/src/router/GasRouterDeployer.ts +++ b/typescript/sdk/src/router/GasRouterDeployer.ts @@ -1,20 +1,17 @@ import { GasRouter } from '@hyperlane-xyz/core'; import { Address } from '@hyperlane-xyz/utils'; -import { - HyperlaneContracts, - HyperlaneContractsMap, - HyperlaneFactories, -} from '../contracts/types'; +import { HyperlaneContracts, HyperlaneContractsMap } from '../contracts/types'; import { ChainMap } from '../types'; -import { HyperlaneRouterDeployer } from './HyperlaneRouterDeployer'; -import { GasRouterConfig } from './types'; +import { ProxiedRouterDeployer } from './ProxiedRouterDeployer'; +import { GasRouterConfig, ProxiedFactories } from './types'; export abstract class GasRouterDeployer< Config extends GasRouterConfig, - Factories extends HyperlaneFactories, -> extends HyperlaneRouterDeployer { + Factories extends ProxiedFactories, + RouterKey extends keyof Factories, +> extends ProxiedRouterDeployer { abstract router(contracts: HyperlaneContracts): GasRouter; async enrollRemoteRouters( diff --git a/typescript/sdk/src/router/ProxiedRouterDeployer.ts b/typescript/sdk/src/router/ProxiedRouterDeployer.ts index 8a61f7a773..8e51d59ece 100644 --- a/typescript/sdk/src/router/ProxiedRouterDeployer.ts +++ b/typescript/sdk/src/router/ProxiedRouterDeployer.ts @@ -18,10 +18,10 @@ export abstract class ProxiedRouterDeployer< Factories extends ProxiedFactories, RouterKey extends keyof Factories, > extends HyperlaneRouterDeployer { - abstract routerContractName: RouterKey; + abstract routerContractNameConstant: RouterKey; // @dev this is for backwards compatibility, should refactor later router(contracts: HyperlaneContracts): Router { - return contracts[this.routerContractName] as Router; + return contracts[this.routerContractNameConstant] as Router; } abstract constructorArgs( @@ -38,6 +38,8 @@ export abstract class ProxiedRouterDeployer< > >; + abstract routerContractName(config: Config): RouterKey; + async deployContracts( chain: ChainName, config: Config, @@ -77,14 +79,14 @@ export abstract class ProxiedRouterDeployer< const proxiedRouter = await this.deployProxiedContract( chain, - this.routerContractName, + this.routerContractName(config), proxyAdmin.address, await this.constructorArgs(chain, config), await this.initializeArgs(chain, config), ); return { - [this.routerContractName]: proxiedRouter, + [this.routerContractName(config)]: proxiedRouter, proxyAdmin, timelockController, } as HyperlaneContracts; diff --git a/typescript/sdk/src/token/contracts.ts b/typescript/sdk/src/token/contracts.ts index 542a04dc41..00b615f0b8 100644 --- a/typescript/sdk/src/token/contracts.ts +++ b/typescript/sdk/src/token/contracts.ts @@ -12,6 +12,8 @@ import { HypNative__factory, } from '@hyperlane-xyz/core'; +import { proxiedFactories } from '../router/types'; + import { TokenType } from './config'; export const hypERC20factories = { @@ -22,6 +24,7 @@ export const hypERC20factories = { [TokenType.collateralVault]: new HypERC20CollateralVaultDeposit__factory(), [TokenType.native]: new HypNative__factory(), [TokenType.nativeScaled]: new HypNativeScaled__factory(), + ...proxiedFactories, }; export type HypERC20Factories = typeof hypERC20factories; @@ -30,6 +33,7 @@ export const hypERC721factories = { [TokenType.collateral]: new HypERC721Collateral__factory(), [TokenType.syntheticUri]: new HypERC721URIStorage__factory(), [TokenType.synthetic]: new HypERC721__factory(), + ...proxiedFactories, }; export type HypERC721Factories = typeof hypERC721factories; diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index f4aa78a769..f858d4ee8a 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -1,27 +1,22 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import debug from 'debug'; -import { constants, ethers, providers } from 'ethers'; +import { ethers, providers } from 'ethers'; import { ERC20__factory, ERC721EnumerableUpgradeable__factory, - HypERC20, - HypERC20Collateral, + GasRouter, HypERC721, HypERC721Collateral, - HypNative, - ProxyAdmin__factory, - TimelockController, - TimelockController__factory, } from '@hyperlane-xyz/core'; -import { eqAddress, objKeys, objMap } from '@hyperlane-xyz/utils'; +import { objKeys, objMap } from '@hyperlane-xyz/utils'; import { HyperlaneContracts } from '../contracts/types'; import { ContractVerifier } from '../deploy/verify/ContractVerifier'; import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory'; import { MultiProvider } from '../providers/MultiProvider'; import { GasRouterDeployer } from '../router/GasRouterDeployer'; -import { GasConfig, ProxiedRouterConfig, RouterConfig } from '../router/types'; +import { GasConfig, RouterConfig } from '../router/types'; import { ChainMap, ChainName } from '../types'; import { @@ -33,7 +28,6 @@ import { HypERC20Config, HypERC721CollateralConfig, HypERC721Config, - HypNativeConfig, TokenConfig, TokenMetadata, TokenType, @@ -54,8 +48,11 @@ import { export class HypERC20Deployer extends GasRouterDeployer< ERC20RouterConfig, - HypERC20Factories + HypERC20Factories, + TokenType.native > { + readonly routerContractNameConstant = TokenType.native; + constructor( multiProvider: MultiProvider, ismFactory?: HyperlaneIsmFactory, @@ -68,6 +65,57 @@ export class HypERC20Deployer extends GasRouterDeployer< }); // factories not used in deploy } + routerContractName( + config: ERC20RouterConfig, + ): K { + if (isCollateralConfig(config)) { + return ( + isFastConfig(config) ? TokenType.fastCollateral : TokenType.collateral + ) as K; + } else if (isSyntheticConfig(config)) { + return ( + isFastConfig(config) ? TokenType.fastSynthetic : TokenType.synthetic + ) as K; + } else { + return config.type as K; + } + } + + async constructorArgs( + chain: ChainName, + config: ERC20RouterConfig, + ): Promise { + if (isCollateralConfig(config)) { + return [config.token, config.mailbox]; + } else if (isNativeConfig(config)) { + return config.scale ? [config.scale, config.mailbox] : [config.mailbox]; + } else if (isSyntheticConfig(config)) { + return [config.decimals, config.mailbox]; + } else { + throw new Error('Unknown collateral type when constructing arguments'); + } + } + + async initializeArgs( + chain: ChainName, + config: ERC20RouterConfig, + ): Promise { + const defaultArgs = [ + config.hook ?? ethers.constants.AddressZero, + config.interchainSecurityModule ?? ethers.constants.AddressZero, + config.owner, + ]; + if (isCollateralConfig(config)) { + return defaultArgs; + } else if (isNativeConfig(config)) { + return defaultArgs; + } else if (isSyntheticConfig(config)) { + return [config.totalSupply, config.name, config.symbol, ...defaultArgs]; + } else { + throw new Error('Unknown collateral type when initializing arguments'); + } + } + static async fetchMetadata( provider: providers.Provider, config: CollateralConfig, @@ -134,166 +182,20 @@ export class HypERC20Deployer extends GasRouterDeployer< } as ERC20Metadata; } - protected async deployCollateral( - chain: ChainName, - config: HypERC20CollateralConfig, - ): Promise { - let contractName: - | TokenType.fastCollateral - | TokenType.collateral - | TokenType.collateralVault; - const constructorArgs = [config.token, config.mailbox]; - const initializeArgs = [ - ethers.constants.AddressZero, - ethers.constants.AddressZero, - config.owner, - ]; - switch (config.type) { - case TokenType.fastSynthetic || TokenType.fastCollateral: - contractName = TokenType.fastCollateral; - break; - case TokenType.collateral: - contractName = TokenType.collateral; - break; - case TokenType.collateralVault: - contractName = TokenType.collateralVault; - break; - default: - throw new Error(`Unknown collateral type ${config.type}`); - } - - return this.deployAdminAndProxyContracts( - chain, - config, - contractName, - constructorArgs, - initializeArgs, - ); - } - - // @dev this is a copy of ProxiedRouterDeployer.deployContracts(). - // Here because ProxiedRouterDeployer assumes a single contract, but here is deploying multiple contracts - // Please remove once ProxiedRouterDeployer is refactored! - async deployAdminAndProxyContracts( - chain: ChainName, - config: ERC20RouterConfig & ProxiedRouterConfig, - contractName: K, - constructorArgs: any, - initializeArgs?: any, - ): Promise { - const proxyAdmin = await this.deployContractFromFactory( - chain, - new ProxyAdmin__factory(), - 'proxyAdmin', - [], - ); - - let timelockController: TimelockController; - let adminOwner: string; - if (config.timelock) { - timelockController = await this.deployTimelock(chain, config.timelock); - adminOwner = timelockController.address; - } else { - timelockController = TimelockController__factory.connect( - constants.AddressZero, - this.multiProvider.getProvider(chain), - ); - adminOwner = config.owner; - } - - await super.runIfOwner(chain, proxyAdmin, async () => { - this.logger(`Checking ownership of proxy admin to ${adminOwner}`); - - if (!eqAddress(await proxyAdmin.owner(), adminOwner)) { - this.logger(`Transferring ownership of proxy admin to ${adminOwner}`); - return this.multiProvider.handleTx( - chain, - proxyAdmin.transferOwnership(adminOwner), - ); - } - return; - }); - return this.deployProxiedContract( - chain, - contractName, - proxyAdmin.address, - constructorArgs, - initializeArgs, - ); - } - - protected async deployNative( - chain: ChainName, - config: HypNativeConfig, - ): Promise { - const initializeArgs = [ - ethers.constants.AddressZero, - ethers.constants.AddressZero, - config.owner, - ]; - if (config.scale) { - return this.deployAdminAndProxyContracts( - chain, - config, - TokenType.nativeScaled, - [config.scale, config.mailbox], - initializeArgs, - ); - } else { - return this.deployAdminAndProxyContracts( - chain, - config, - TokenType.native, - [config.mailbox], - initializeArgs, - ); - } - } - - protected async deploySynthetic( - chain: ChainName, - config: HypERC20Config, - ): Promise { - const router: HypERC20 = await this.deployContract( - chain, - isFastConfig(config) ? TokenType.fastSynthetic : TokenType.synthetic, - [config.decimals, config.mailbox], - ); - try { - await this.multiProvider.handleTx( - chain, - router.initialize(config.totalSupply, config.name, config.symbol), - ); - } catch (e: any) { - if (!e.message.includes('already initialized')) { - throw e; - } - this.logger(`${config.type} already initialized`); - } - return router; - } - router(contracts: HyperlaneContracts) { for (const key of objKeys(hypERC20factories)) { if (contracts[key]) { - return contracts[key]; + return contracts[key] as GasRouter; } } throw new Error('No matching contract found'); } async deployContracts(chain: ChainName, config: HypERC20Config) { - let router: HypERC20 | HypERC20Collateral | HypNative; - if (isCollateralConfig(config)) { - router = await this.deployCollateral(chain, config); - } else if (isNativeConfig(config)) { - router = await this.deployNative(chain, config); - } else if (isSyntheticConfig(config)) { - router = await this.deploySynthetic(chain, config); - } else { - throw new Error('Invalid ERC20 token router config'); - } - await this.configureClient(chain, router, config); + const { [this.routerContractName(config)]: router } = + await super.deployContracts(chain, config); + + await this.configureClient(chain, router as any, config); return { [config.type]: router } as any; } @@ -359,8 +261,11 @@ export class HypERC20Deployer extends GasRouterDeployer< export class HypERC721Deployer extends GasRouterDeployer< ERC721RouterConfig, - HypERC721Factories + HypERC721Factories, + TokenType.collateral > { + readonly routerContractNameConstant = TokenType.collateral; + constructor( multiProvider: MultiProvider, contractVerifier?: ContractVerifier, @@ -370,6 +275,33 @@ export class HypERC721Deployer extends GasRouterDeployer< contractVerifier, }); } + routerContractName( + config: ERC721RouterConfig, + ): K { + return TokenType[config.type] as K; + } + + async constructorArgs( + chain: ChainName, + config: HypERC20CollateralConfig, + ): Promise { + switch (config.type) { + case TokenType.fastSynthetic || TokenType.fastCollateral: + return [config.token, config.mailbox]; + case TokenType.collateral: + return [config.token, config.mailbox]; + case TokenType.collateralVault: + return [config.token, config.mailbox]; + } + } + + //@ts-ignore ignore for now until the contracts get fixed + async initializeArgs( + chain: ChainName, + config: HypERC20CollateralConfig, + ): Promise { + return config.token; + } static async fetchMetadata( provider: providers.Provider, @@ -431,7 +363,7 @@ export class HypERC721Deployer extends GasRouterDeployer< router(contracts: HyperlaneContracts) { for (const key of objKeys(hypERC721factories)) { if (contracts[key]) { - return contracts[key]; + return contracts[key] as GasRouter; } } throw new Error('No matching contract found'); From 69bb6822d506613f6bf96bc25962214a3d65a307 Mon Sep 17 00:00:00 2001 From: Le Yu Date: Mon, 25 Mar 2024 16:28:04 -0400 Subject: [PATCH 03/14] Update tests for NativeScaled and ERC20 --- solidity/test/token/HypERC20.t.sol | 6 ++-- solidity/test/token/HypNativeScaled.t.sol | 38 ++++++++++++++++++----- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/solidity/test/token/HypERC20.t.sol b/solidity/test/token/HypERC20.t.sol index 86195a05dd..94fd83ed2d 100644 --- a/solidity/test/token/HypERC20.t.sol +++ b/solidity/test/token/HypERC20.t.sol @@ -87,7 +87,7 @@ abstract contract HypTokenTest is Test { TOTAL_SUPPLY, NAME, SYMBOL, - address(address(noopHook)), + address(noopHook), address(igp), address(this) ) @@ -220,11 +220,9 @@ contract HypERC20Test is HypTokenTest { address(this) ) ); - // localToken = new HypERC20(DECIMALS, address(localMailbox)); + localToken = HypERC20(address(proxy)); erc20Token = HypERC20(address(proxy)); - // erc20Token.initialize(TOTAL_SUPPLY, NAME, SYMBOL); - erc20Token.enrollRemoteRouter( DESTINATION, address(remoteToken).addressToBytes32() diff --git a/solidity/test/token/HypNativeScaled.t.sol b/solidity/test/token/HypNativeScaled.t.sol index a9499d056f..a9af062aec 100644 --- a/solidity/test/token/HypNativeScaled.t.sol +++ b/solidity/test/token/HypNativeScaled.t.sol @@ -6,6 +6,7 @@ import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transpa import {HypNativeScaled} from "../../contracts/token/extensions/HypNativeScaled.sol"; import {HypERC20} from "../../contracts/token/HypERC20.sol"; +import {HypNative} from "../../contracts/token/HypNative.sol"; import {TypeCasts} from "../../contracts/libs/TypeCasts.sol"; import {MockHyperlaneEnvironment} from "../../contracts/mock/MockHyperlaneEnvironment.sol"; @@ -38,20 +39,41 @@ contract HypNativeScaledTest is Test { function setUp() public { environment = new MockHyperlaneEnvironment(synthDomain, nativeDomain); - synth = new HypERC20( + HypERC20 implementationSynth = new HypERC20( decimals, address(environment.mailboxes(synthDomain)) ); - synth.initialize( - mintAmount * (10 ** decimals), - "Zebec BSC Token", - "ZBC" - ); - - native = new HypNativeScaled( + TransparentUpgradeableProxy proxySynth = new TransparentUpgradeableProxy( + address(implementationSynth), + address(9), + abi.encodeWithSelector( + HypERC20.initialize.selector, + mintAmount * (10 ** decimals), + "Zebec BSC Token", + "ZBC", + address(0), + address(0), + address(this) + ) + ); + synth = HypERC20(address(proxySynth)); + + HypNativeScaled implementationNative = new HypNativeScaled( scale, address(environment.mailboxes(nativeDomain)) ); + TransparentUpgradeableProxy proxyNative = new TransparentUpgradeableProxy( + address(implementationNative), + address(9), + abi.encodeWithSelector( + HypNative.initialize.selector, + address(0), + address(0), + address(this) + ) + ); + + native = HypNativeScaled(payable(address(proxyNative))); native.enrollRemoteRouter( synthDomain, From 1bbf245a8db66ce7cbe07476f717cfc6177503af Mon Sep 17 00:00:00 2001 From: Le Yu Date: Mon, 25 Mar 2024 17:15:24 -0400 Subject: [PATCH 04/14] Saving work to switch over to another task rq --- solidity/contracts/token/HypERC721.sol | 6 +- typescript/sdk/src/token/deploy.ts | 113 ++++++++++++++----------- 2 files changed, 70 insertions(+), 49 deletions(-) diff --git a/solidity/contracts/token/HypERC721.sol b/solidity/contracts/token/HypERC721.sol index 57c9e0e7da..defcf9f238 100644 --- a/solidity/contracts/token/HypERC721.sol +++ b/solidity/contracts/token/HypERC721.sol @@ -23,7 +23,10 @@ contract HypERC721 is ERC721EnumerableUpgradeable, TokenRouter { function initialize( uint256 _mintAmount, string memory _name, - string memory _symbol + string memory _symbol, + address _hook, + address _interchainSecurityModule, + address _owner ) external initializer { address owner = msg.sender; _transferOwnership(owner); @@ -32,6 +35,7 @@ contract HypERC721 is ERC721EnumerableUpgradeable, TokenRouter { for (uint256 i = 0; i < _mintAmount; i++) { _safeMint(owner, i); } + _MailboxClient_initialize(_hook, _interchainSecurityModule, _owner); } function balanceOf( diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index f858d4ee8a..8c133275c4 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -24,9 +24,7 @@ import { ERC20Metadata, ERC20RouterConfig, ERC721RouterConfig, - HypERC20CollateralConfig, HypERC20Config, - HypERC721CollateralConfig, HypERC721Config, TokenConfig, TokenMetadata, @@ -275,32 +273,47 @@ export class HypERC721Deployer extends GasRouterDeployer< contractVerifier, }); } - routerContractName( + routerContractName( config: ERC721RouterConfig, ): K { - return TokenType[config.type] as K; + if (isCollateralConfig(config)) { + return ( + isUriConfig(config) ? TokenType.collateralUri : TokenType.collateral + ) as K; + } else if (isSyntheticConfig(config)) { + return ( + isUriConfig(config) ? TokenType.syntheticUri : TokenType.synthetic + ) as K; + } else { + return config.type as K; + } } async constructorArgs( chain: ChainName, - config: HypERC20CollateralConfig, + config: ERC721RouterConfig, ): Promise { - switch (config.type) { - case TokenType.fastSynthetic || TokenType.fastCollateral: - return [config.token, config.mailbox]; - case TokenType.collateral: - return [config.token, config.mailbox]; - case TokenType.collateralVault: - return [config.token, config.mailbox]; + if (isCollateralConfig(config)) { + return [config.token, config.mailbox]; + } else if (isSyntheticConfig(config)) { + return [config.mailbox]; + } else { + throw new Error('Unknown collateral type when constructing arguments'); } } //@ts-ignore ignore for now until the contracts get fixed async initializeArgs( chain: ChainName, - config: HypERC20CollateralConfig, + config: ERC721RouterConfig, ): Promise { - return config.token; + if (isCollateralConfig(config)) { + return [config.token, config.mailbox]; + } else if (isSyntheticConfig(config)) { + return [config.totalSupply, config.name, config.symbol]; + } else { + throw new Error('Unknown collateral type when initializing arguments'); + } } static async fetchMetadata( @@ -333,32 +346,32 @@ export class HypERC721Deployer extends GasRouterDeployer< } } - protected async deployCollateral( - chain: ChainName, - config: HypERC721CollateralConfig, - ): Promise { - return this.deployContract( - chain, - isUriConfig(config) ? TokenType.collateralUri : TokenType.collateral, - [config.token, config.mailbox], - ); - } - - protected async deploySynthetic( - chain: ChainName, - config: HypERC721Config, - ): Promise { - const router = await this.deployContract( - chain, - isUriConfig(config) ? TokenType.syntheticUri : TokenType.synthetic, - [config.mailbox], - ); - await this.multiProvider.handleTx( - chain, - router.initialize(config.totalSupply, config.name, config.symbol), - ); - return router; - } + // protected async deployCollateral( + // chain: ChainName, + // config: HypERC721CollateralConfig, + // ): Promise { + // return this.deployContract( + // chain, + // isUriConfig(config) ? TokenType.collateralUri : TokenType.collateral, + // [config.token, config.mailbox], + // ); + // } + + // protected async deploySynthetic( + // chain: ChainName, + // config: HypERC721Config, + // ): Promise { + // const router = await this.deployContract( + // chain, + // isUriConfig(config) ? TokenType.syntheticUri : TokenType.synthetic, + // [config.mailbox], + // ); + // await this.multiProvider.handleTx( + // chain, + // router.initialize(config.totalSupply, config.name, config.symbol), + // ); + // return router; + // } router(contracts: HyperlaneContracts) { for (const key of objKeys(hypERC721factories)) { @@ -370,14 +383,18 @@ export class HypERC721Deployer extends GasRouterDeployer< } async deployContracts(chain: ChainName, config: HypERC721Config) { - let router: HypERC721 | HypERC721Collateral; - if (isCollateralConfig(config)) { - router = await this.deployCollateral(chain, config); - } else if (isSyntheticConfig(config)) { - router = await this.deploySynthetic(chain, config); - } else { - throw new Error('Invalid ERC721 token router config'); - } + // let router: HypERC721 | HypERC721Collateral; + // if (isCollateralConfig(config)) { + // router = await this.deployCollateral(chain, config); + // } else if (isSyntheticConfig(config)) { + // router = await this.deploySynthetic(chain, config); + // } else { + // throw new Error('Invalid ERC721 token router config'); + // } + const { [this.routerContractName(config)]: router } = + await super.deployContracts(chain, config); + + await this.configureClient(chain, router as any, config); return { [config.type]: router } as any; } From dd3c1824d6a29f1bd5e26e84491fdc49093b8e6a Mon Sep 17 00:00:00 2001 From: Le Yu Date: Mon, 25 Mar 2024 18:06:03 -0400 Subject: [PATCH 05/14] Add init, update unit tests --- .../contracts/token/HypERC721Collateral.sol | 8 ++ solidity/test/token/HypERC721.t.sol | 105 ++++++++++++++---- 2 files changed, 91 insertions(+), 22 deletions(-) diff --git a/solidity/contracts/token/HypERC721Collateral.sol b/solidity/contracts/token/HypERC721Collateral.sol index b12faf8b34..1319b735b7 100644 --- a/solidity/contracts/token/HypERC721Collateral.sol +++ b/solidity/contracts/token/HypERC721Collateral.sol @@ -21,6 +21,14 @@ contract HypERC721Collateral is TokenRouter { wrappedToken = IERC721(erc721); } + function initialize( + address _hook, + address _interchainSecurityModule, + address _owner + ) public virtual initializer { + _MailboxClient_initialize(_hook, _interchainSecurityModule, _owner); + } + function ownerOf(uint256 _tokenId) external view returns (address) { return IERC721(wrappedToken).ownerOf(_tokenId); } diff --git a/solidity/test/token/HypERC721.t.sol b/solidity/test/token/HypERC721.t.sol index cf55ff4763..f1a7df0a6f 100644 --- a/solidity/test/token/HypERC721.t.sol +++ b/solidity/test/token/HypERC721.t.sol @@ -14,6 +14,9 @@ pragma solidity ^0.8.13; @@@@@@@@@ @@@@@@@@*/ import "forge-std/Test.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import {ERC721URIStorageUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol"; import {TestMailbox} from "../../contracts/test/TestMailbox.sol"; import {TestPostDispatchHook} from "../../contracts/test/TestPostDispatchHook.sol"; @@ -26,9 +29,6 @@ import {HypERC721Collateral} from "../../contracts/token/HypERC721Collateral.sol import {HypERC721URIStorage} from "../../contracts/token/extensions/HypERC721URIStorage.sol"; import {HypERC721URICollateral} from "../../contracts/token/extensions/HypERC721URICollateral.sol"; -import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; -import {ERC721URIStorageUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol"; - abstract contract HypTokenTest is Test, IERC721Receiver { using TypeCasts for address; @@ -38,6 +38,7 @@ abstract contract HypTokenTest is Test, IERC721Receiver { address internal constant ALICE = address(0x1); address internal constant BOB = address(0x2); + address internal constant PROXY_ADMIN = address(0x37); uint32 internal constant ORIGIN = 11; uint32 internal constant DESTINATION = 22; uint256 internal constant TRANSFER_ID = 0; @@ -77,19 +78,42 @@ abstract contract HypTokenTest is Test, IERC721Receiver { function _deployRemoteToken(bool isCollateral) internal { if (isCollateral) { - remoteToken = new HypERC721Collateral( + HypERC721Collateral implementation = new HypERC721Collateral( address(remotePrimaryToken), address(remoteMailbox) ); + TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( + address(implementation), + PROXY_ADMIN, + abi.encodeWithSelector( + HypERC721Collateral.initialize.selector, + address(0), + address(0), + address(this) + ) + ); + remoteToken = HypERC721Collateral(address(proxy)); remotePrimaryToken.transferFrom( address(this), address(remoteToken), 0 ); // need for processing messages } else { - HypERC721 erc721 = new HypERC721(address(remoteMailbox)); - erc721.initialize(0, NAME, SYMBOL); - remoteToken = TokenRouter(address(erc721)); + HypERC721 implementation = new HypERC721(address(remoteMailbox)); + TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( + address(implementation), + PROXY_ADMIN, + abi.encodeWithSelector( + HypERC721.initialize.selector, + 0, + NAME, + SYMBOL, + address(0), + address(0), + address(this) + ) + ); + remoteToken = TokenRouter(address(proxy)); } remoteToken.enrollRemoteRouter( ORIGIN, @@ -151,10 +175,22 @@ contract HypERC721Test is HypTokenTest { function setUp() public virtual override { super.setUp(); - localToken = new HypERC721(address(localMailbox)); - hyp721 = HypERC721(address(localToken)); - - hyp721.initialize(INITIAL_SUPPLY, NAME, SYMBOL); + HypERC721 implementation = new HypERC721(address(localMailbox)); + TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( + address(implementation), + PROXY_ADMIN, + abi.encodeWithSelector( + HypERC721.initialize.selector, + INITIAL_SUPPLY, + NAME, + SYMBOL, + address(0), + address(0), + address(this) + ) + ); + localToken = HypERC721(address(proxy)); + hyp721 = HypERC721(address(proxy)); hyp721.enrollRemoteRouter( DESTINATION, @@ -162,37 +198,44 @@ contract HypERC721Test is HypTokenTest { ); } - function testInitialize_revert_ifAlreadyInitialized() public { + function test_Initialize_revert_ifAlreadyInitialized() public { vm.expectRevert("Initializable: contract is already initialized"); - hyp721.initialize(INITIAL_SUPPLY, NAME, SYMBOL); + hyp721.initialize( + INITIAL_SUPPLY, + NAME, + SYMBOL, + address(0), + address(0), + address(this) + ); } - function testTotalSupply() public { + function test_TotalSupply() public { assertEq(hyp721.balanceOf(address(this)), INITIAL_SUPPLY); } - function testOwnerOf() public { + function test_OwnerOf() public { assertEq(hyp721.ownerOf(0), address(this)); } - function testLocalTransfer() public { + function test_LocalTransfer() public { hyp721.transferFrom(address(this), ALICE, 0); assertEq(hyp721.balanceOf(address(this)), INITIAL_SUPPLY - 1); assertEq(hyp721.balanceOf(ALICE), 1); } - function testLocalYTransfer_revert_invalidTokenId() public { + function test_LocalYTransfer_revert_invalidTokenId() public { vm.expectRevert("ERC721: invalid token ID"); hyp721.transferFrom(address(this), ALICE, INITIAL_SUPPLY); } - function testRemoteTransfer(bool isCollateral) public { + function test_RemoteTransfer(bool isCollateral) public { _deployRemoteToken(isCollateral); _performRemoteTransfer(25000, 0); assertEq(hyp721.balanceOf(address(this)), INITIAL_SUPPLY - 1); } - function testRemoteTransfer_revert_unowned() public { + function test_RemoteTransfer_revert_unowned() public { hyp721.transferFrom(address(this), BOB, 1); _deployRemoteToken(false); @@ -201,7 +244,7 @@ contract HypERC721Test is HypTokenTest { assertEq(hyp721.balanceOf(address(this)), INITIAL_SUPPLY - 1); } - function testRemoteTransfer_revert_invalidTokenId() public { + function test_RemoteTransfer_revert_invalidTokenId() public { _deployRemoteToken(false); vm.expectRevert("ERC721: invalid token ID"); _performRemoteTransfer(25000, INITIAL_SUPPLY); @@ -228,7 +271,14 @@ contract HypERC721URIStorageTest is HypTokenTest { localToken = new MockHypERC721URIStorage(address(localMailbox)); hyp721Storage = MockHypERC721URIStorage(address(localToken)); - hyp721Storage.initialize(INITIAL_SUPPLY, NAME, SYMBOL); + hyp721Storage.initialize( + INITIAL_SUPPLY, + NAME, + SYMBOL, + address(0), + address(0), + address(this) + ); hyp721Storage.setTokenURI(0, URI); hyp721Storage.enrollRemoteRouter( DESTINATION, @@ -254,10 +304,21 @@ contract HypERC721CollateralTest is HypTokenTest { function setUp() public override { super.setUp(); - localToken = new HypERC721Collateral( + HypERC721Collateral implementation = new HypERC721Collateral( address(localPrimaryToken), address(localMailbox) ); + TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy( + address(implementation), + PROXY_ADMIN, + abi.encodeWithSelector( + HypERC721Collateral.initialize.selector, + address(0), + address(0), + address(this) + ) + ); + localToken = HypERC721Collateral(address(proxy)); hyp721Collateral = HypERC721Collateral(address(localToken)); hyp721Collateral.enrollRemoteRouter( From b5b7d8da9761cb95ea955219e496602d79b355ca Mon Sep 17 00:00:00 2001 From: Le Yu Date: Tue, 26 Mar 2024 10:52:43 -0400 Subject: [PATCH 06/14] Clean up code --- solidity/test/token/HypERC721.t.sol | 16 ++--- .../sdk/src/router/ProxiedRouterDeployer.ts | 18 ++++- typescript/sdk/src/token/deploy.ts | 66 +++---------------- 3 files changed, 34 insertions(+), 66 deletions(-) diff --git a/solidity/test/token/HypERC721.t.sol b/solidity/test/token/HypERC721.t.sol index f1a7df0a6f..70a2a229c5 100644 --- a/solidity/test/token/HypERC721.t.sol +++ b/solidity/test/token/HypERC721.t.sol @@ -198,7 +198,7 @@ contract HypERC721Test is HypTokenTest { ); } - function test_Initialize_revert_ifAlreadyInitialized() public { + function testInitialize_revert_ifAlreadyInitialized() public { vm.expectRevert("Initializable: contract is already initialized"); hyp721.initialize( INITIAL_SUPPLY, @@ -210,32 +210,32 @@ contract HypERC721Test is HypTokenTest { ); } - function test_TotalSupply() public { + function testTotalSupply() public { assertEq(hyp721.balanceOf(address(this)), INITIAL_SUPPLY); } - function test_OwnerOf() public { + function testOwnerOf() public { assertEq(hyp721.ownerOf(0), address(this)); } - function test_LocalTransfer() public { + function testLocalTransfer() public { hyp721.transferFrom(address(this), ALICE, 0); assertEq(hyp721.balanceOf(address(this)), INITIAL_SUPPLY - 1); assertEq(hyp721.balanceOf(ALICE), 1); } - function test_LocalYTransfer_revert_invalidTokenId() public { + function testLocalYTransfer_revert_invalidTokenId() public { vm.expectRevert("ERC721: invalid token ID"); hyp721.transferFrom(address(this), ALICE, INITIAL_SUPPLY); } - function test_RemoteTransfer(bool isCollateral) public { + function testRemoteTransfer(bool isCollateral) public { _deployRemoteToken(isCollateral); _performRemoteTransfer(25000, 0); assertEq(hyp721.balanceOf(address(this)), INITIAL_SUPPLY - 1); } - function test_RemoteTransfer_revert_unowned() public { + function testRemoteTransfer_revert_unowned() public { hyp721.transferFrom(address(this), BOB, 1); _deployRemoteToken(false); @@ -244,7 +244,7 @@ contract HypERC721Test is HypTokenTest { assertEq(hyp721.balanceOf(address(this)), INITIAL_SUPPLY - 1); } - function test_RemoteTransfer_revert_invalidTokenId() public { + function testRemoteTransfer_revert_invalidTokenId() public { _deployRemoteToken(false); vm.expectRevert("ERC721: invalid token ID"); _performRemoteTransfer(25000, INITIAL_SUPPLY); diff --git a/typescript/sdk/src/router/ProxiedRouterDeployer.ts b/typescript/sdk/src/router/ProxiedRouterDeployer.ts index 8e51d59ece..e1ba23ce82 100644 --- a/typescript/sdk/src/router/ProxiedRouterDeployer.ts +++ b/typescript/sdk/src/router/ProxiedRouterDeployer.ts @@ -24,11 +24,27 @@ export abstract class ProxiedRouterDeployer< return contracts[this.routerContractNameConstant] as Router; } + /** + * Returns the contract name + * @param config Router config + */ + abstract routerContractName(config: Config): RouterKey; + + /** + * Returns the constructor arguments for the proxy + * @param chain Name of chain + * @param config Router config + */ abstract constructorArgs( chain: ChainName, config: Config, ): Promise>; + /** + * Returns the initialize arguments for the proxy + * @param chain Name of chain + * @param config Router config + */ abstract initializeArgs( chain: ChainName, config: Config, @@ -38,8 +54,6 @@ export abstract class ProxiedRouterDeployer< > >; - abstract routerContractName(config: Config): RouterKey; - async deployContracts( chain: ChainName, config: Config, diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index 8c133275c4..27c274a2a7 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -6,8 +6,7 @@ import { ERC20__factory, ERC721EnumerableUpgradeable__factory, GasRouter, - HypERC721, - HypERC721Collateral, + MailboxClient, } from '@hyperlane-xyz/core'; import { objKeys, objMap } from '@hyperlane-xyz/utils'; @@ -75,14 +74,11 @@ export class HypERC20Deployer extends GasRouterDeployer< isFastConfig(config) ? TokenType.fastSynthetic : TokenType.synthetic ) as K; } else { - return config.type as K; + throw new Error('Unknown collateral type when constructing router name'); } } - async constructorArgs( - chain: ChainName, - config: ERC20RouterConfig, - ): Promise { + async constructorArgs(_: ChainName, config: ERC20RouterConfig): Promise { if (isCollateralConfig(config)) { return [config.token, config.mailbox]; } else if (isNativeConfig(config)) { @@ -94,10 +90,7 @@ export class HypERC20Deployer extends GasRouterDeployer< } } - async initializeArgs( - chain: ChainName, - config: ERC20RouterConfig, - ): Promise { + async initializeArgs(_: ChainName, config: ERC20RouterConfig): Promise { const defaultArgs = [ config.hook ?? ethers.constants.AddressZero, config.interchainSecurityModule ?? ethers.constants.AddressZero, @@ -193,7 +186,7 @@ export class HypERC20Deployer extends GasRouterDeployer< const { [this.routerContractName(config)]: router } = await super.deployContracts(chain, config); - await this.configureClient(chain, router as any, config); + await this.configureClient(chain, router as MailboxClient, config); return { [config.type]: router } as any; } @@ -280,17 +273,16 @@ export class HypERC721Deployer extends GasRouterDeployer< return ( isUriConfig(config) ? TokenType.collateralUri : TokenType.collateral ) as K; - } else if (isSyntheticConfig(config)) { + } else { + // if isSyntheticConfig return ( isUriConfig(config) ? TokenType.syntheticUri : TokenType.synthetic ) as K; - } else { - return config.type as K; } } async constructorArgs( - chain: ChainName, + _: ChainName, config: ERC721RouterConfig, ): Promise { if (isCollateralConfig(config)) { @@ -303,10 +295,7 @@ export class HypERC721Deployer extends GasRouterDeployer< } //@ts-ignore ignore for now until the contracts get fixed - async initializeArgs( - chain: ChainName, - config: ERC721RouterConfig, - ): Promise { + async initializeArgs(_: ChainName, config: ERC721RouterConfig): Promise { if (isCollateralConfig(config)) { return [config.token, config.mailbox]; } else if (isSyntheticConfig(config)) { @@ -346,33 +335,6 @@ export class HypERC721Deployer extends GasRouterDeployer< } } - // protected async deployCollateral( - // chain: ChainName, - // config: HypERC721CollateralConfig, - // ): Promise { - // return this.deployContract( - // chain, - // isUriConfig(config) ? TokenType.collateralUri : TokenType.collateral, - // [config.token, config.mailbox], - // ); - // } - - // protected async deploySynthetic( - // chain: ChainName, - // config: HypERC721Config, - // ): Promise { - // const router = await this.deployContract( - // chain, - // isUriConfig(config) ? TokenType.syntheticUri : TokenType.synthetic, - // [config.mailbox], - // ); - // await this.multiProvider.handleTx( - // chain, - // router.initialize(config.totalSupply, config.name, config.symbol), - // ); - // return router; - // } - router(contracts: HyperlaneContracts) { for (const key of objKeys(hypERC721factories)) { if (contracts[key]) { @@ -383,18 +345,10 @@ export class HypERC721Deployer extends GasRouterDeployer< } async deployContracts(chain: ChainName, config: HypERC721Config) { - // let router: HypERC721 | HypERC721Collateral; - // if (isCollateralConfig(config)) { - // router = await this.deployCollateral(chain, config); - // } else if (isSyntheticConfig(config)) { - // router = await this.deploySynthetic(chain, config); - // } else { - // throw new Error('Invalid ERC721 token router config'); - // } const { [this.routerContractName(config)]: router } = await super.deployContracts(chain, config); - await this.configureClient(chain, router as any, config); + await this.configureClient(chain, router as MailboxClient, config); return { [config.type]: router } as any; } From 74c3549465274d8944b142dcea593744d2bd953d Mon Sep 17 00:00:00 2001 From: Le Yu Date: Tue, 26 Mar 2024 13:43:21 -0400 Subject: [PATCH 07/14] Remove routerContractNameConstant. Add router() logic for dependent classes. Add defaultArgs for 721 deploy --- .../account/InterchainAccountDeployer.ts | 14 +++++++++++-- .../LiquidityLayerRouterDeployer.ts | 20 ++++++++++++++++--- .../query/InterchainQueryDeployer.ts | 15 ++++++++++++-- .../sdk/src/router/ProxiedRouterDeployer.ts | 6 +----- typescript/sdk/src/token/deploy.ts | 13 ++++++------ 5 files changed, 50 insertions(+), 18 deletions(-) diff --git a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts index 44170d5b12..2b8ab225bc 100644 --- a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts +++ b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts @@ -1,5 +1,8 @@ import { ethers } from 'ethers'; +import { Router } from '@hyperlane-xyz/core'; +import { objKeys } from '@hyperlane-xyz/utils'; + import { HyperlaneContracts } from '../../contracts/types'; import { ContractVerifier } from '../../deploy/verify/ContractVerifier'; import { MultiProvider } from '../../providers/MultiProvider'; @@ -19,8 +22,6 @@ export class InterchainAccountDeployer extends ProxiedRouterDeployer< InterchainAccountFactories, 'interchainAccountRouter' > { - readonly routerContractNameConstant = 'interchainAccountRouter'; - constructor( multiProvider: MultiProvider, contractVerifier?: ContractVerifier, @@ -36,6 +37,15 @@ export class InterchainAccountDeployer extends ProxiedRouterDeployer< return 'interchainAccountRouter' as K; } + router(contracts: HyperlaneContracts): Router { + for (const key of objKeys(interchainAccountFactories)) { + if (contracts[key]) { + return contracts[key] as Router; + } + } + throw new Error('No matching contract found'); + } + async constructorArgs(_: string, config: RouterConfig): Promise<[string]> { return [config.mailbox]; } diff --git a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts index 3296b74f00..be8a58ade7 100644 --- a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts +++ b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts @@ -4,8 +4,15 @@ import { CircleBridgeAdapter, LiquidityLayerRouter, PortalAdapter, + Router, } from '@hyperlane-xyz/core'; -import { Address, eqAddress, objFilter, objMap } from '@hyperlane-xyz/utils'; +import { + Address, + eqAddress, + objFilter, + objKeys, + objMap, +} from '@hyperlane-xyz/utils'; import { HyperlaneContracts, @@ -56,8 +63,6 @@ export class LiquidityLayerDeployer extends ProxiedRouterDeployer< LiquidityLayerFactories, 'liquidityLayerRouter' > { - readonly routerContractNameConstant = 'liquidityLayerRouter'; - constructor( multiProvider: MultiProvider, contractVerifier?: ContractVerifier, @@ -73,6 +78,15 @@ export class LiquidityLayerDeployer extends ProxiedRouterDeployer< return 'liquidityLayerRouter' as K; } + router(contracts: HyperlaneContracts): Router { + for (const key of objKeys(liquidityLayerFactories)) { + if (contracts[key]) { + return contracts[key] as Router; + } + } + throw new Error('No matching contract found'); + } + async constructorArgs( _: string, config: LiquidityLayerConfig, diff --git a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts index a45a08e062..a0db2959c2 100644 --- a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts +++ b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts @@ -1,5 +1,9 @@ import { ethers } from 'ethers'; +import { Router } from '@hyperlane-xyz/core'; +import { objKeys } from '@hyperlane-xyz/utils'; + +import { HyperlaneContracts } from '../../contracts/types'; import { ContractVerifier } from '../../deploy/verify/ContractVerifier'; import { MultiProvider } from '../../providers/MultiProvider'; import { ProxiedRouterDeployer } from '../../router/ProxiedRouterDeployer'; @@ -17,8 +21,6 @@ export class InterchainQueryDeployer extends ProxiedRouterDeployer< InterchainQueryFactories, 'interchainQueryRouter' > { - readonly routerContractNameConstant = 'interchainQueryRouter'; - constructor( multiProvider: MultiProvider, contractVerifier?: ContractVerifier, @@ -34,6 +36,15 @@ export class InterchainQueryDeployer extends ProxiedRouterDeployer< return 'interchainQueryRouter' as K; } + router(contracts: HyperlaneContracts): Router { + for (const key of objKeys(interchainQueryFactories)) { + if (contracts[key]) { + return contracts[key] as Router; + } + } + throw new Error('No matching contract found'); + } + async constructorArgs(_: string, config: RouterConfig): Promise<[string]> { return [config.mailbox]; } diff --git a/typescript/sdk/src/router/ProxiedRouterDeployer.ts b/typescript/sdk/src/router/ProxiedRouterDeployer.ts index e1ba23ce82..1125b55284 100644 --- a/typescript/sdk/src/router/ProxiedRouterDeployer.ts +++ b/typescript/sdk/src/router/ProxiedRouterDeployer.ts @@ -18,11 +18,7 @@ export abstract class ProxiedRouterDeployer< Factories extends ProxiedFactories, RouterKey extends keyof Factories, > extends HyperlaneRouterDeployer { - abstract routerContractNameConstant: RouterKey; // @dev this is for backwards compatibility, should refactor later - - router(contracts: HyperlaneContracts): Router { - return contracts[this.routerContractNameConstant] as Router; - } + abstract router(contracts: HyperlaneContracts): Router; /** * Returns the contract name diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index 27c274a2a7..5fdcfe87dc 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -48,8 +48,6 @@ export class HypERC20Deployer extends GasRouterDeployer< HypERC20Factories, TokenType.native > { - readonly routerContractNameConstant = TokenType.native; - constructor( multiProvider: MultiProvider, ismFactory?: HyperlaneIsmFactory, @@ -255,8 +253,6 @@ export class HypERC721Deployer extends GasRouterDeployer< HypERC721Factories, TokenType.collateral > { - readonly routerContractNameConstant = TokenType.collateral; - constructor( multiProvider: MultiProvider, contractVerifier?: ContractVerifier, @@ -296,10 +292,15 @@ export class HypERC721Deployer extends GasRouterDeployer< //@ts-ignore ignore for now until the contracts get fixed async initializeArgs(_: ChainName, config: ERC721RouterConfig): Promise { + const defaultArgs = [ + config.hook ?? ethers.constants.AddressZero, + config.interchainSecurityModule ?? ethers.constants.AddressZero, + config.owner, + ]; if (isCollateralConfig(config)) { - return [config.token, config.mailbox]; + return defaultArgs; } else if (isSyntheticConfig(config)) { - return [config.totalSupply, config.name, config.symbol]; + return [config.totalSupply, config.name, config.symbol, ...defaultArgs]; } else { throw new Error('Unknown collateral type when initializing arguments'); } From 78a92686590b0abf2dfe5fbbb52c0db8affaf458 Mon Sep 17 00:00:00 2001 From: Le Yu Date: Tue, 26 Mar 2024 14:29:30 -0400 Subject: [PATCH 08/14] Remove RouterKey from class input type --- .../middleware/account/InterchainAccountDeployer.ts | 10 +++------- .../liquidity-layer/LiquidityLayerRouterDeployer.ts | 10 +++------- .../src/middleware/query/InterchainQueryDeployer.ts | 10 +++------- typescript/sdk/src/router/GasRouterDeployer.ts | 3 +-- typescript/sdk/src/router/ProxiedRouterDeployer.ts | 9 +++++---- typescript/sdk/src/token/deploy.ts | 7 ++----- 6 files changed, 17 insertions(+), 32 deletions(-) diff --git a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts index 2b8ab225bc..a5bfd354c8 100644 --- a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts +++ b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts @@ -19,8 +19,7 @@ export type InterchainAccountConfig = ProxiedRouterConfig; export class InterchainAccountDeployer extends ProxiedRouterDeployer< InterchainAccountConfig, - InterchainAccountFactories, - 'interchainAccountRouter' + InterchainAccountFactories > { constructor( multiProvider: MultiProvider, @@ -46,14 +45,11 @@ export class InterchainAccountDeployer extends ProxiedRouterDeployer< throw new Error('No matching contract found'); } - async constructorArgs(_: string, config: RouterConfig): Promise<[string]> { + async constructorArgs(_: string, config: RouterConfig): Promise { return [config.mailbox]; } - async initializeArgs( - chain: string, - config: RouterConfig, - ): Promise<[string, string, string]> { + async initializeArgs(chain: string, config: RouterConfig): Promise { const owner = await this.multiProvider.getSignerAddress(chain); return [ config.hook ?? ethers.constants.AddressZero, diff --git a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts index be8a58ade7..61e0396103 100644 --- a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts +++ b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts @@ -60,8 +60,7 @@ export type LiquidityLayerConfig = RouterConfig & BridgeAdapterConfig; export class LiquidityLayerDeployer extends ProxiedRouterDeployer< LiquidityLayerConfig, - LiquidityLayerFactories, - 'liquidityLayerRouter' + LiquidityLayerFactories > { constructor( multiProvider: MultiProvider, @@ -87,17 +86,14 @@ export class LiquidityLayerDeployer extends ProxiedRouterDeployer< throw new Error('No matching contract found'); } - async constructorArgs( - _: string, - config: LiquidityLayerConfig, - ): Promise<[string]> { + async constructorArgs(_: string, config: LiquidityLayerConfig): Promise { return [config.mailbox]; } async initializeArgs( chain: string, config: LiquidityLayerConfig, - ): Promise<[string, string, string]> { + ): Promise { const owner = await this.multiProvider.getSignerAddress(chain); if (typeof config.interchainSecurityModule === 'object') { throw new Error('ISM as object unimplemented'); diff --git a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts index a0db2959c2..374ac16c3a 100644 --- a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts +++ b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts @@ -18,8 +18,7 @@ export type InterchainQueryConfig = RouterConfig; export class InterchainQueryDeployer extends ProxiedRouterDeployer< InterchainQueryConfig, - InterchainQueryFactories, - 'interchainQueryRouter' + InterchainQueryFactories > { constructor( multiProvider: MultiProvider, @@ -45,14 +44,11 @@ export class InterchainQueryDeployer extends ProxiedRouterDeployer< throw new Error('No matching contract found'); } - async constructorArgs(_: string, config: RouterConfig): Promise<[string]> { + async constructorArgs(_: string, config: RouterConfig): Promise { return [config.mailbox]; } - async initializeArgs( - chain: string, - config: RouterConfig, - ): Promise<[string, string, string]> { + async initializeArgs(chain: string, config: RouterConfig): Promise { const owner = await this.multiProvider.getSignerAddress(chain); if (typeof config.interchainSecurityModule === 'object') { throw new Error('ISM as object unimplemented'); diff --git a/typescript/sdk/src/router/GasRouterDeployer.ts b/typescript/sdk/src/router/GasRouterDeployer.ts index c9358565d0..0c43db9b70 100644 --- a/typescript/sdk/src/router/GasRouterDeployer.ts +++ b/typescript/sdk/src/router/GasRouterDeployer.ts @@ -10,8 +10,7 @@ import { GasRouterConfig, ProxiedFactories } from './types'; export abstract class GasRouterDeployer< Config extends GasRouterConfig, Factories extends ProxiedFactories, - RouterKey extends keyof Factories, -> extends ProxiedRouterDeployer { +> extends ProxiedRouterDeployer { abstract router(contracts: HyperlaneContracts): GasRouter; async enrollRemoteRouters( diff --git a/typescript/sdk/src/router/ProxiedRouterDeployer.ts b/typescript/sdk/src/router/ProxiedRouterDeployer.ts index 1125b55284..93ab986ebf 100644 --- a/typescript/sdk/src/router/ProxiedRouterDeployer.ts +++ b/typescript/sdk/src/router/ProxiedRouterDeployer.ts @@ -16,7 +16,6 @@ import { ProxiedFactories, ProxiedRouterConfig } from './types'; export abstract class ProxiedRouterDeployer< Config extends ProxiedRouterConfig, Factories extends ProxiedFactories, - RouterKey extends keyof Factories, > extends HyperlaneRouterDeployer { abstract router(contracts: HyperlaneContracts): Router; @@ -24,14 +23,16 @@ export abstract class ProxiedRouterDeployer< * Returns the contract name * @param config Router config */ - abstract routerContractName(config: Config): RouterKey; + abstract routerContractName( + config: Config, + ): RouterKey; /** * Returns the constructor arguments for the proxy * @param chain Name of chain * @param config Router config */ - abstract constructorArgs( + abstract constructorArgs( chain: ChainName, config: Config, ): Promise>; @@ -41,7 +42,7 @@ export abstract class ProxiedRouterDeployer< * @param chain Name of chain * @param config Router config */ - abstract initializeArgs( + abstract initializeArgs( chain: ChainName, config: Config, ): Promise< diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index 5fdcfe87dc..7d12123d18 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -45,8 +45,7 @@ import { export class HypERC20Deployer extends GasRouterDeployer< ERC20RouterConfig, - HypERC20Factories, - TokenType.native + HypERC20Factories > { constructor( multiProvider: MultiProvider, @@ -250,8 +249,7 @@ export class HypERC20Deployer extends GasRouterDeployer< export class HypERC721Deployer extends GasRouterDeployer< ERC721RouterConfig, - HypERC721Factories, - TokenType.collateral + HypERC721Factories > { constructor( multiProvider: MultiProvider, @@ -290,7 +288,6 @@ export class HypERC721Deployer extends GasRouterDeployer< } } - //@ts-ignore ignore for now until the contracts get fixed async initializeArgs(_: ChainName, config: ERC721RouterConfig): Promise { const defaultArgs = [ config.hook ?? ethers.constants.AddressZero, From 27ad19084aed89c30b9bf879b05edd4834623966 Mon Sep 17 00:00:00 2001 From: Le Yu Date: Wed, 27 Mar 2024 10:48:30 -0400 Subject: [PATCH 09/14] Fix according to PR review --- solidity/contracts/token/HypERC721.sol | 10 +++++----- solidity/contracts/token/HypERC721Collateral.sol | 6 ++++++ solidity/contracts/token/HypNative.sol | 6 ++++++ .../account/InterchainAccountDeployer.ts | 7 +------ .../LiquidityLayerRouterDeployer.ts | 15 ++------------- .../middleware/query/InterchainQueryDeployer.ts | 8 +------- 6 files changed, 21 insertions(+), 31 deletions(-) diff --git a/solidity/contracts/token/HypERC721.sol b/solidity/contracts/token/HypERC721.sol index defcf9f238..ced9020b82 100644 --- a/solidity/contracts/token/HypERC721.sol +++ b/solidity/contracts/token/HypERC721.sol @@ -19,6 +19,9 @@ contract HypERC721 is ERC721EnumerableUpgradeable, TokenRouter { * @param _mintAmount The amount of NFTs to mint to `msg.sender`. * @param _name The name of the token. * @param _symbol The symbol of the token. + * @param _hook The post-dispatch hook contract. + @param _interchainSecurityModule The interchain security module contract. + @param _owner The this contract. */ function initialize( uint256 _mintAmount, @@ -28,14 +31,11 @@ contract HypERC721 is ERC721EnumerableUpgradeable, TokenRouter { address _interchainSecurityModule, address _owner ) external initializer { - address owner = msg.sender; - _transferOwnership(owner); - + _MailboxClient_initialize(_hook, _interchainSecurityModule, _owner); __ERC721_init(_name, _symbol); for (uint256 i = 0; i < _mintAmount; i++) { - _safeMint(owner, i); + _safeMint(msg.sender, i); } - _MailboxClient_initialize(_hook, _interchainSecurityModule, _owner); } function balanceOf( diff --git a/solidity/contracts/token/HypERC721Collateral.sol b/solidity/contracts/token/HypERC721Collateral.sol index 1319b735b7..720eebd974 100644 --- a/solidity/contracts/token/HypERC721Collateral.sol +++ b/solidity/contracts/token/HypERC721Collateral.sol @@ -21,6 +21,12 @@ contract HypERC721Collateral is TokenRouter { wrappedToken = IERC721(erc721); } + /** + * @notice Initializes the Hyperlane router + * @param _hook The post-dispatch hook contract. + @param _interchainSecurityModule The interchain security module contract. + @param _owner The this contract. + */ function initialize( address _hook, address _interchainSecurityModule, diff --git a/solidity/contracts/token/HypNative.sol b/solidity/contracts/token/HypNative.sol index 115df1a2dd..b8c6d68223 100644 --- a/solidity/contracts/token/HypNative.sol +++ b/solidity/contracts/token/HypNative.sol @@ -20,6 +20,12 @@ contract HypNative is TokenRouter { constructor(address _mailbox) TokenRouter(_mailbox) {} + /** + * @notice Initializes the Hyperlane router + * @param _hook The post-dispatch hook contract. + @param _interchainSecurityModule The interchain security module contract. + @param _owner The this contract. + */ function initialize( address _hook, address _interchainSecurityModule, diff --git a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts index a5bfd354c8..291cde0e15 100644 --- a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts +++ b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts @@ -37,12 +37,7 @@ export class InterchainAccountDeployer extends ProxiedRouterDeployer< } router(contracts: HyperlaneContracts): Router { - for (const key of objKeys(interchainAccountFactories)) { - if (contracts[key]) { - return contracts[key] as Router; - } - } - throw new Error('No matching contract found'); + return contracts.interchainAccountRouter; } async constructorArgs(_: string, config: RouterConfig): Promise { diff --git a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts index 61e0396103..ec83a70d7e 100644 --- a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts +++ b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts @@ -6,13 +6,7 @@ import { PortalAdapter, Router, } from '@hyperlane-xyz/core'; -import { - Address, - eqAddress, - objFilter, - objKeys, - objMap, -} from '@hyperlane-xyz/utils'; +import { Address, eqAddress, objFilter, objMap } from '@hyperlane-xyz/utils'; import { HyperlaneContracts, @@ -78,12 +72,7 @@ export class LiquidityLayerDeployer extends ProxiedRouterDeployer< } router(contracts: HyperlaneContracts): Router { - for (const key of objKeys(liquidityLayerFactories)) { - if (contracts[key]) { - return contracts[key] as Router; - } - } - throw new Error('No matching contract found'); + return contracts.liquidityLayerRouter; } async constructorArgs(_: string, config: LiquidityLayerConfig): Promise { diff --git a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts index 374ac16c3a..05746d8d4d 100644 --- a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts +++ b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts @@ -1,7 +1,6 @@ import { ethers } from 'ethers'; import { Router } from '@hyperlane-xyz/core'; -import { objKeys } from '@hyperlane-xyz/utils'; import { HyperlaneContracts } from '../../contracts/types'; import { ContractVerifier } from '../../deploy/verify/ContractVerifier'; @@ -36,12 +35,7 @@ export class InterchainQueryDeployer extends ProxiedRouterDeployer< } router(contracts: HyperlaneContracts): Router { - for (const key of objKeys(interchainQueryFactories)) { - if (contracts[key]) { - return contracts[key] as Router; - } - } - throw new Error('No matching contract found'); + return contracts.interchainQueryRouter; } async constructorArgs(_: string, config: RouterConfig): Promise { From 3d48777373418ae2a3b4513e29d415cfd1e57160 Mon Sep 17 00:00:00 2001 From: Le Yu Date: Thu, 28 Mar 2024 12:01:11 -0400 Subject: [PATCH 10/14] Update to use deployContractWithName() --- typescript/cli/src/deploy/warp.ts | 2 +- .../sdk/src/core/HyperlaneCoreDeployer.ts | 1 + .../sdk/src/deploy/HyperlaneDeployer.ts | 6 ++- .../sdk/src/gas/HyperlaneIgpDeployer.ts | 1 + .../account/InterchainAccountDeployer.ts | 8 ++-- .../LiquidityLayerRouterDeployer.ts | 5 +- .../query/InterchainQueryDeployer.ts | 8 ++-- .../sdk/src/router/ProxiedRouterDeployer.ts | 13 +++-- typescript/sdk/src/token/contracts.ts | 5 ++ typescript/sdk/src/token/deploy.ts | 47 +++++++++++-------- 10 files changed, 62 insertions(+), 34 deletions(-) diff --git a/typescript/cli/src/deploy/warp.ts b/typescript/cli/src/deploy/warp.ts index 515443e44a..677930bb6b 100644 --- a/typescript/cli/src/deploy/warp.ts +++ b/typescript/cli/src/deploy/warp.ts @@ -296,7 +296,7 @@ async function fetchBaseTokenMetadata( (base.type === TokenType.collateral && address) ) { // If it's a collateral type, use a TokenAdapter to query for its metadata - log(`Fetching token metadata for ${address} on ${chainName}}`); + log(`Fetching token metadata for ${address} on ${chainName}`); const adapter = new EvmTokenAdapter( chainName, MultiProtocolProvider.fromMultiProvider(multiProvider), diff --git a/typescript/sdk/src/core/HyperlaneCoreDeployer.ts b/typescript/sdk/src/core/HyperlaneCoreDeployer.ts index 2f1f737bb1..b1a4ed153a 100644 --- a/typescript/sdk/src/core/HyperlaneCoreDeployer.ts +++ b/typescript/sdk/src/core/HyperlaneCoreDeployer.ts @@ -65,6 +65,7 @@ export class HyperlaneCoreDeployer extends HyperlaneDeployer< const mailbox = await this.deployProxiedContract( chain, 'mailbox', + 'mailbox', proxyAdmin, [domain], ); diff --git a/typescript/sdk/src/deploy/HyperlaneDeployer.ts b/typescript/sdk/src/deploy/HyperlaneDeployer.ts index f06fdb5fb8..3fd5ceb7c5 100644 --- a/typescript/sdk/src/deploy/HyperlaneDeployer.ts +++ b/typescript/sdk/src/deploy/HyperlaneDeployer.ts @@ -642,14 +642,16 @@ export abstract class HyperlaneDeployer< */ async deployProxiedContract( chain: ChainName, - contractName: K, + contractKey: K, + contractName: string, proxyAdmin: string, constructorArgs: Parameters, initializeArgs?: Parameters[K]['initialize']>, ): Promise[K]> { // Try to initialize the implementation even though it may not be necessary - const implementation = await this.deployContract( + const implementation = await this.deployContractWithName( chain, + contractKey, contractName, constructorArgs, initializeArgs, diff --git a/typescript/sdk/src/gas/HyperlaneIgpDeployer.ts b/typescript/sdk/src/gas/HyperlaneIgpDeployer.ts index 2966d0a3c7..89a87b918d 100644 --- a/typescript/sdk/src/gas/HyperlaneIgpDeployer.ts +++ b/typescript/sdk/src/gas/HyperlaneIgpDeployer.ts @@ -40,6 +40,7 @@ export class HyperlaneIgpDeployer extends HyperlaneDeployer< const igp = await this.deployProxiedContract( chain, 'interchainGasPaymaster', + 'interchainGasPaymaster', proxyAdmin.address, [], [await this.multiProvider.getSignerAddress(chain), beneficiary], diff --git a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts index 291cde0e15..15ababad52 100644 --- a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts +++ b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts @@ -1,7 +1,6 @@ import { ethers } from 'ethers'; import { Router } from '@hyperlane-xyz/core'; -import { objKeys } from '@hyperlane-xyz/utils'; import { HyperlaneContracts } from '../../contracts/types'; import { ContractVerifier } from '../../deploy/verify/ContractVerifier'; @@ -29,10 +28,11 @@ export class InterchainAccountDeployer extends ProxiedRouterDeployer< contractVerifier, }); } + routerContractName(): string { + return 'InterchainAccountRouter'; + } - routerContractName( - _: RouterConfig, - ): K { + routerContractKey(): K { return 'interchainAccountRouter' as K; } diff --git a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts index 1d0923fb9b..9885e1ae3e 100644 --- a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts +++ b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts @@ -64,8 +64,11 @@ export class LiquidityLayerDeployer extends ProxiedRouterDeployer< contractVerifier, }); } + routerContractName(): string { + return 'LiquidityLayerRouter'; + } - routerContractName( + routerContractKey( _: RouterConfig, ): K { return 'liquidityLayerRouter' as K; diff --git a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts index 05746d8d4d..d36a053ac3 100644 --- a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts +++ b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts @@ -28,9 +28,11 @@ export class InterchainQueryDeployer extends ProxiedRouterDeployer< }); } - routerContractName( - _: RouterConfig, - ): K { + routerContractName(): string { + return 'InterchainQueryRouter'; + } + + routerContractKey(): K { return 'interchainQueryRouter' as K; } diff --git a/typescript/sdk/src/router/ProxiedRouterDeployer.ts b/typescript/sdk/src/router/ProxiedRouterDeployer.ts index 13205e5eb2..e68ba262aa 100644 --- a/typescript/sdk/src/router/ProxiedRouterDeployer.ts +++ b/typescript/sdk/src/router/ProxiedRouterDeployer.ts @@ -23,9 +23,13 @@ export abstract class ProxiedRouterDeployer< * Returns the contract name * @param config Router config */ - abstract routerContractName( - config: Config, - ): RouterKey; + abstract routerContractName(config: Config): string; + + /** + * Returns the contract key + * @param config Router config + */ + abstract routerContractKey(config: Config): keyof Factories; /** * Returns the constructor arguments for the proxy @@ -92,6 +96,7 @@ export abstract class ProxiedRouterDeployer< const proxiedRouter = await this.deployProxiedContract( chain, + this.routerContractKey(config), this.routerContractName(config), proxyAdmin.address, await this.constructorArgs(chain, config), @@ -99,7 +104,7 @@ export abstract class ProxiedRouterDeployer< ); return { - [this.routerContractName(config)]: proxiedRouter, + [this.routerContractKey(config)]: proxiedRouter, proxyAdmin, timelockController, } as HyperlaneContracts; diff --git a/typescript/sdk/src/token/contracts.ts b/typescript/sdk/src/token/contracts.ts index 8898351324..478729f842 100644 --- a/typescript/sdk/src/token/contracts.ts +++ b/typescript/sdk/src/token/contracts.ts @@ -25,6 +25,8 @@ export const hypERC20contracts = { [TokenType.native]: 'HypNative', [TokenType.nativeScaled]: 'HypNativeScaled', }; +export type HypERC20contracts = typeof hypERC20contracts; + export const hypERC20factories = { [TokenType.fastCollateral]: new FastHypERC20Collateral__factory(), [TokenType.fastSynthetic]: new FastHypERC20__factory(), @@ -43,6 +45,9 @@ export const hypERC721contracts = { [TokenType.syntheticUri]: 'HypERC721URIStorage', [TokenType.synthetic]: 'HypERC721', }; + +export type HypERC721contracts = typeof hypERC721contracts; + export const hypERC721factories = { [TokenType.collateralUri]: new HypERC721URICollateral__factory(), [TokenType.collateral]: new HypERC721Collateral__factory(), diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index abd10642e3..7088b7ac6c 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import { providers } from 'ethers'; +import { constants, providers } from 'ethers'; import { ERC20__factory, @@ -38,6 +38,7 @@ import { import { HypERC20Factories, HypERC721Factories, + HypERC721contracts, hypERC20contracts, hypERC20factories, hypERC721contracts, @@ -60,17 +61,21 @@ export class HypERC20Deployer extends GasRouterDeployer< }); // factories not used in deploy } - routerContractName( - config: ERC20RouterConfig, - ): K { + routerContractName(config: ERC20RouterConfig): string { + return hypERC20contracts[this.routerContractKey(config)]; + } + + routerContractKey(config: ERC20RouterConfig) { if (isCollateralConfig(config)) { - return ( - isFastConfig(config) ? TokenType.fastCollateral : TokenType.collateral - ) as K; + return isFastConfig(config) + ? TokenType.fastCollateral + : TokenType.collateral; + } else if (isNativeConfig(config)) { + return config.scale ? TokenType.nativeScaled : TokenType.native; } else if (isSyntheticConfig(config)) { - return ( - isFastConfig(config) ? TokenType.fastSynthetic : TokenType.synthetic - ) as K; + return isFastConfig(config) + ? TokenType.fastSynthetic + : TokenType.synthetic; } else { throw new Error('Unknown collateral type when constructing router name'); } @@ -90,8 +95,8 @@ export class HypERC20Deployer extends GasRouterDeployer< async initializeArgs(_: ChainName, config: ERC20RouterConfig): Promise { const defaultArgs = [ - config.hook ?? ethers.constants.AddressZero, - config.interchainSecurityModule ?? ethers.constants.AddressZero, + config.hook ?? constants.AddressZero, + config.interchainSecurityModule ?? constants.AddressZero, config.owner, ]; if (isCollateralConfig(config)) { @@ -170,7 +175,7 @@ export class HypERC20Deployer extends GasRouterDeployer< ...definedConfigMetadata, } as ERC20Metadata; } - + router(contracts: HyperlaneContracts) { for (const key of objKeys(hypERC20factories)) { if (contracts[key]) { @@ -181,7 +186,7 @@ export class HypERC20Deployer extends GasRouterDeployer< } async deployContracts(chain: ChainName, config: HypERC20Config) { - const { [this.routerContractName(config)]: router } = + const { [this.routerContractKey(config)]: router } = await super.deployContracts(chain, config); await this.configureClient(chain, router as MailboxClient, config); @@ -261,7 +266,11 @@ export class HypERC721Deployer extends GasRouterDeployer< contractVerifier, }); } - routerContractName( + routerContractName(config: ERC721RouterConfig): string { + return hypERC721contracts[this.routerContractKey(config)]; + } + + routerContractKey( config: ERC721RouterConfig, ): K { if (isCollateralConfig(config)) { @@ -291,8 +300,8 @@ export class HypERC721Deployer extends GasRouterDeployer< async initializeArgs(_: ChainName, config: ERC721RouterConfig): Promise { const defaultArgs = [ - config.hook ?? ethers.constants.AddressZero, - config.interchainSecurityModule ?? ethers.constants.AddressZero, + config.hook ?? constants.AddressZero, + config.interchainSecurityModule ?? constants.AddressZero, config.owner, ]; if (isCollateralConfig(config)) { @@ -333,7 +342,7 @@ export class HypERC721Deployer extends GasRouterDeployer< return 80_000; } } - + router(contracts: HyperlaneContracts) { for (const key of objKeys(hypERC721factories)) { if (contracts[key]) { @@ -344,7 +353,7 @@ export class HypERC721Deployer extends GasRouterDeployer< } async deployContracts(chain: ChainName, config: HypERC721Config) { - const { [this.routerContractName(config)]: router } = + const { [this.routerContractKey(config)]: router } = await super.deployContracts(chain, config); await this.configureClient(chain, router as MailboxClient, config); From 901e6c1bc9f9c7af8c9f06e85abfa1267b4ba030 Mon Sep 17 00:00:00 2001 From: Le Yu Date: Thu, 28 Mar 2024 16:52:36 -0400 Subject: [PATCH 11/14] Fix typing --- typescript/sdk/src/token/config.ts | 4 ++++ typescript/sdk/src/token/deploy.ts | 29 +++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/typescript/sdk/src/token/config.ts b/typescript/sdk/src/token/config.ts index 7e2738a740..d8c0cc5610 100644 --- a/typescript/sdk/src/token/config.ts +++ b/typescript/sdk/src/token/config.ts @@ -60,6 +60,10 @@ export const isCollateralConfig = ( config.type === TokenType.fastCollateral || config.type == TokenType.collateralVault; +export const isCollateralVaultConfig = ( + config: TokenConfig, +): config is CollateralConfig => config.type === TokenType.collateralVault; + export const isSyntheticConfig = ( config: TokenConfig, ): config is SyntheticConfig => diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index 7088b7ac6c..32b907f5d5 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -28,6 +28,7 @@ import { TokenMetadata, TokenType, isCollateralConfig, + isCollateralVaultConfig, isErc20Metadata, isFastConfig, isNativeConfig, @@ -67,9 +68,13 @@ export class HypERC20Deployer extends GasRouterDeployer< routerContractKey(config: ERC20RouterConfig) { if (isCollateralConfig(config)) { - return isFastConfig(config) - ? TokenType.fastCollateral - : TokenType.collateral; + if (isFastConfig(config)) { + return TokenType.fastCollateral; + } else if (isCollateralVaultConfig(config)) { + return TokenType.collateralVault; + } else { + return TokenType.collateral; + } } else if (isNativeConfig(config)) { return config.scale ? TokenType.nativeScaled : TokenType.native; } else if (isSyntheticConfig(config)) { @@ -81,19 +86,27 @@ export class HypERC20Deployer extends GasRouterDeployer< } } - async constructorArgs(_: ChainName, config: ERC20RouterConfig): Promise { + async constructorArgs( + _: ChainName, + config: ERC20RouterConfig, + ): Promise> { if (isCollateralConfig(config)) { - return [config.token, config.mailbox]; + return [config.token, config.mailbox] as any; } else if (isNativeConfig(config)) { - return config.scale ? [config.scale, config.mailbox] : [config.mailbox]; + return config.scale + ? [config.scale, config.mailbox] + : ([config.mailbox] as any); } else if (isSyntheticConfig(config)) { - return [config.decimals, config.mailbox]; + return [config.decimals, config.mailbox] as any; } else { throw new Error('Unknown collateral type when constructing arguments'); } } - async initializeArgs(_: ChainName, config: ERC20RouterConfig): Promise { + async initializeArgs(_: ChainName, config: HypERC20Config): Promise { + if (typeof config.interchainSecurityModule !== 'string') { + throw new Error('Token deployer does not support ISM objects currently'); + } const defaultArgs = [ config.hook ?? constants.AddressZero, config.interchainSecurityModule ?? constants.AddressZero, From 2439dbb4596f759e4c43332828f2876ca21a6a13 Mon Sep 17 00:00:00 2001 From: Le Yu Date: Thu, 28 Mar 2024 17:31:50 -0400 Subject: [PATCH 12/14] Fix typing --- .../middleware/account/InterchainAccountDeployer.ts | 7 +++++-- .../liquidity-layer/LiquidityLayerRouterDeployer.ts | 7 +++++-- .../src/middleware/query/InterchainQueryDeployer.ts | 7 +++++-- typescript/sdk/src/router/ProxiedRouterDeployer.ts | 9 +++++---- typescript/sdk/src/token/deploy.ts | 11 ++++++++--- 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts index 15ababad52..ed45510e8a 100644 --- a/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts +++ b/typescript/sdk/src/middleware/account/InterchainAccountDeployer.ts @@ -40,8 +40,11 @@ export class InterchainAccountDeployer extends ProxiedRouterDeployer< return contracts.interchainAccountRouter; } - async constructorArgs(_: string, config: RouterConfig): Promise { - return [config.mailbox]; + async constructorArgs( + _: string, + config: RouterConfig, + ): Promise> { + return [config.mailbox] as any; } async initializeArgs(chain: string, config: RouterConfig): Promise { diff --git a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts index 9885e1ae3e..015920f21e 100644 --- a/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts +++ b/typescript/sdk/src/middleware/liquidity-layer/LiquidityLayerRouterDeployer.ts @@ -78,8 +78,11 @@ export class LiquidityLayerDeployer extends ProxiedRouterDeployer< return contracts.liquidityLayerRouter; } - async constructorArgs(_: string, config: LiquidityLayerConfig): Promise { - return [config.mailbox]; + async constructorArgs( + _: string, + config: LiquidityLayerConfig, + ): Promise> { + return [config.mailbox] as any; } async initializeArgs( diff --git a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts index d36a053ac3..93e5dab3d1 100644 --- a/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts +++ b/typescript/sdk/src/middleware/query/InterchainQueryDeployer.ts @@ -40,8 +40,11 @@ export class InterchainQueryDeployer extends ProxiedRouterDeployer< return contracts.interchainQueryRouter; } - async constructorArgs(_: string, config: RouterConfig): Promise { - return [config.mailbox]; + async constructorArgs( + _: string, + config: RouterConfig, + ): Promise> { + return [config.mailbox] as any; } async initializeArgs(chain: string, config: RouterConfig): Promise { diff --git a/typescript/sdk/src/router/ProxiedRouterDeployer.ts b/typescript/sdk/src/router/ProxiedRouterDeployer.ts index e68ba262aa..4f52b995f3 100644 --- a/typescript/sdk/src/router/ProxiedRouterDeployer.ts +++ b/typescript/sdk/src/router/ProxiedRouterDeployer.ts @@ -46,13 +46,14 @@ export abstract class ProxiedRouterDeployer< * @param chain Name of chain * @param config Router config */ - abstract initializeArgs( + abstract initializeArgs< + Omitted extends Omit, + RouterKey extends keyof Omitted, + >( chain: ChainName, config: Config, ): Promise< - Parameters< - Awaited>['initialize'] - > + Parameters>['initialize']> >; async deployContracts( diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index 32b907f5d5..eab5421693 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -113,11 +113,16 @@ export class HypERC20Deployer extends GasRouterDeployer< config.owner, ]; if (isCollateralConfig(config)) { - return defaultArgs; + return defaultArgs as any; } else if (isNativeConfig(config)) { - return defaultArgs; + return defaultArgs as any; } else if (isSyntheticConfig(config)) { - return [config.totalSupply, config.name, config.symbol, ...defaultArgs]; + return [ + config.totalSupply, + config.name, + config.symbol, + ...defaultArgs, + ] as any; } else { throw new Error('Unknown collateral type when initializing arguments'); } From 073f1ea18b32f0b1a1ab71480523f126c68235b6 Mon Sep 17 00:00:00 2001 From: Le Yu Date: Thu, 28 Mar 2024 17:36:57 -0400 Subject: [PATCH 13/14] Remove unused change --- typescript/sdk/src/router/ProxiedRouterDeployer.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/typescript/sdk/src/router/ProxiedRouterDeployer.ts b/typescript/sdk/src/router/ProxiedRouterDeployer.ts index 4f52b995f3..e68ba262aa 100644 --- a/typescript/sdk/src/router/ProxiedRouterDeployer.ts +++ b/typescript/sdk/src/router/ProxiedRouterDeployer.ts @@ -46,14 +46,13 @@ export abstract class ProxiedRouterDeployer< * @param chain Name of chain * @param config Router config */ - abstract initializeArgs< - Omitted extends Omit, - RouterKey extends keyof Omitted, - >( + abstract initializeArgs( chain: ChainName, config: Config, ): Promise< - Parameters>['initialize']> + Parameters< + Awaited>['initialize'] + > >; async deployContracts( From 5041ac773b255a7dc6e54110527154191b7423c8 Mon Sep 17 00:00:00 2001 From: Le Yu Date: Sun, 31 Mar 2024 10:19:14 -0400 Subject: [PATCH 14/14] Add check for object --- typescript/sdk/src/token/deploy.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/typescript/sdk/src/token/deploy.ts b/typescript/sdk/src/token/deploy.ts index eab5421693..f72ab12e4f 100644 --- a/typescript/sdk/src/token/deploy.ts +++ b/typescript/sdk/src/token/deploy.ts @@ -104,7 +104,8 @@ export class HypERC20Deployer extends GasRouterDeployer< } async initializeArgs(_: ChainName, config: HypERC20Config): Promise { - if (typeof config.interchainSecurityModule !== 'string') { + // ISM config can be an object, but is not supported right now + if (typeof config.interchainSecurityModule === 'object') { throw new Error('Token deployer does not support ISM objects currently'); } const defaultArgs = [