UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

341 lines 15.9 kB
import { expect } from 'chai'; import hre from 'hardhat'; import { zeroAddress } from 'viem'; import { ERC20Test__factory, ERC4626Test__factory, Mailbox__factory, XERC20LockboxTest__factory, XERC20Test__factory, } from '@hyperlane-xyz/core'; import { TestChainName, test3, } from '@hyperlane-xyz/sdk'; import { assert } from '@hyperlane-xyz/utils'; import { TestCoreDeployer } from '../core/TestCoreDeployer.js'; import { HyperlaneProxyFactoryDeployer } from '../deploy/HyperlaneProxyFactoryDeployer.js'; import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js'; import { MultiProvider } from '../providers/MultiProvider.js'; import { EvmERC20WarpRouteReader } from './EvmERC20WarpRouteReader.js'; import { TokenType } from './config.js'; import { HypERC20Deployer } from './deploy.js'; import { derivedIsmAddress } from './types.js'; describe('ERC20WarpRouterReader', async () => { const TOKEN_NAME = 'fake'; const TOKEN_SUPPLY = '100000000000000000000'; const TOKEN_DECIMALS = 18; const GAS = 65000; const chain = TestChainName.test4; let ismFactory; let factories; let erc20Factory; let token; let signer; let deployer; let multiProvider; let coreApp; let routerConfigMap; let baseConfig; let mailbox; let evmERC20WarpRouteReader; let vault; before(async () => { [signer] = await hre.ethers.getSigners(); multiProvider = MultiProvider.createTestMultiProvider({ signer }); const ismFactoryDeployer = new HyperlaneProxyFactoryDeployer(multiProvider); factories = await ismFactoryDeployer.deploy(multiProvider.mapKnownChains(() => ({}))); ismFactory = new HyperlaneIsmFactory(factories, multiProvider); coreApp = await new TestCoreDeployer(multiProvider, ismFactory).deployApp(); routerConfigMap = coreApp.getRouterConfig(signer.address); erc20Factory = new ERC20Test__factory(signer); token = await erc20Factory.deploy(TOKEN_NAME, TOKEN_NAME, TOKEN_SUPPLY, TOKEN_DECIMALS); baseConfig = routerConfigMap[chain]; mailbox = Mailbox__factory.connect(baseConfig.mailbox, signer); evmERC20WarpRouteReader = new EvmERC20WarpRouteReader(multiProvider, chain); deployer = new HypERC20Deployer(multiProvider); const vaultFactory = new ERC4626Test__factory(signer); vault = await vaultFactory.deploy(token.address, TOKEN_NAME, TOKEN_NAME); }); beforeEach(async () => { // Reset the MultiProvider and create a new deployer for each test multiProvider = MultiProvider.createTestMultiProvider({ signer }); deployer = new HypERC20Deployer(multiProvider); }); it('should derive a token type from contract', async () => { const typesToDerive = [ TokenType.collateral, TokenType.collateralVault, TokenType.synthetic, TokenType.native, ]; await Promise.all(typesToDerive.map(async (type) => { // Create config const config = { [chain]: { type, token: type === TokenType.collateralVault ? vault.address : token.address, hook: await mailbox.defaultHook(), name: TOKEN_NAME, symbol: TOKEN_NAME, decimals: TOKEN_DECIMALS, gas: GAS, ...baseConfig, }, }; // Deploy warp route with config const warpRoute = await deployer.deploy(config); const derivedTokenType = await evmERC20WarpRouteReader.deriveTokenType(warpRoute[chain][type].address); expect(derivedTokenType).to.equal(type); })); }); it('should derive collateral config correctly', async () => { // Create config const config = { [chain]: { type: TokenType.collateral, token: token.address, hook: await mailbox.defaultHook(), interchainSecurityModule: await mailbox.defaultIsm(), ...baseConfig, }, }; // Deploy with config const warpRoute = await deployer.deploy(config); // Derive config and check if each value matches const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig(warpRoute[chain].collateral.address); for (const [key, value] of Object.entries(derivedConfig)) { const deployedValue = config[chain][key]; if (deployedValue && typeof value === 'string') expect(deployedValue).to.equal(value); } // Check hook because they're potentially objects expect(derivedConfig.hook).to.deep.equal(await evmERC20WarpRouteReader.evmHookReader.deriveHookConfig(config[chain].hook)); // Check ism expect(derivedIsmAddress(derivedConfig)).to.be.equal(await mailbox.defaultIsm()); // Check if token values matches if (derivedConfig.type === TokenType.collateral) { expect(derivedConfig.name).to.equal(TOKEN_NAME); expect(derivedConfig.symbol).to.equal(TOKEN_NAME); expect(derivedConfig.decimals).to.equal(TOKEN_DECIMALS); } }); it('should derive xerc20 config correctly', async () => { // Create token const xerc20Token = await new XERC20Test__factory(signer).deploy(TOKEN_NAME, TOKEN_NAME, TOKEN_SUPPLY, TOKEN_DECIMALS); // Create config const config = { [chain]: { type: TokenType.XERC20, token: xerc20Token.address, hook: await mailbox.defaultHook(), interchainSecurityModule: await mailbox.defaultIsm(), ...baseConfig, }, }; // Deploy with config const warpRoute = await deployer.deploy(config); // Derive config and check if each value matches const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig(warpRoute[chain].xERC20.address); for (const [key, value] of Object.entries(derivedConfig)) { const deployedValue = config[chain][key]; if (deployedValue && typeof value === 'string') expect(deployedValue).to.equal(value); } // Check hook because they're potentially objects expect(derivedConfig.hook).to.deep.equal(await evmERC20WarpRouteReader.evmHookReader.deriveHookConfig(config[chain].hook)); // Check ism expect(derivedIsmAddress(derivedConfig)).to.be.equal(await mailbox.defaultIsm()); // Check if token values matches if (derivedConfig.type === TokenType.XERC20) { expect(derivedConfig.name).to.equal(TOKEN_NAME); expect(derivedConfig.symbol).to.equal(TOKEN_NAME); expect(derivedConfig.decimals).to.equal(TOKEN_DECIMALS); expect(derivedConfig.token).to.equal(xerc20Token.address); } }); it('should derive xerc20lockbox config correctly', async () => { // Create token const xerc20Lockbox = await new XERC20LockboxTest__factory(signer).deploy(TOKEN_NAME, TOKEN_NAME, TOKEN_SUPPLY, TOKEN_DECIMALS); // Create config const config = { [chain]: { type: TokenType.XERC20Lockbox, token: xerc20Lockbox.address, hook: await mailbox.defaultHook(), interchainSecurityModule: await mailbox.defaultIsm(), ...baseConfig, }, }; // Deploy with config const warpRoute = await deployer.deploy(config); // Derive config and check if each value matches const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig(warpRoute[chain].xERC20Lockbox.address); for (const [key, value] of Object.entries(derivedConfig)) { const deployedValue = config[chain][key]; if (deployedValue && typeof value === 'string') expect(deployedValue).to.equal(value); } // Check hook because they're potentially objects expect(derivedConfig.hook).to.deep.equal(await evmERC20WarpRouteReader.evmHookReader.deriveHookConfig(config[chain].hook)); // Check ism expect(derivedIsmAddress(derivedConfig)).to.be.equal(await mailbox.defaultIsm()); // Check if token values matches if (derivedConfig.type === TokenType.XERC20) { expect(derivedConfig.name).to.equal(TOKEN_NAME); expect(derivedConfig.symbol).to.equal(TOKEN_NAME); expect(derivedConfig.decimals).to.equal(TOKEN_DECIMALS); expect(derivedConfig.token).to.equal(xerc20Lockbox.address); } }); it('should derive synthetic rebase config correctly', async () => { // Create config const config = { [chain]: { type: TokenType.syntheticRebase, collateralChainName: TestChainName.test4, hook: await mailbox.defaultHook(), name: TOKEN_NAME, symbol: TOKEN_NAME, decimals: TOKEN_DECIMALS, ...baseConfig, }, }; // Deploy with config const warpRoute = await deployer.deploy(config); // Derive config and check if each value matches const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig(warpRoute[chain].syntheticRebase.address); for (const [key, value] of Object.entries(derivedConfig)) { const deployedValue = config[chain][key]; if (deployedValue && typeof value === 'string') expect(deployedValue).to.equal(value); } // Check if token values matches if (derivedConfig.type === TokenType.collateral) { expect(derivedConfig.name).to.equal(TOKEN_NAME); expect(derivedConfig.symbol).to.equal(TOKEN_NAME); } }); it('should derive synthetic config correctly', async () => { // Create config const config = { [chain]: { type: TokenType.synthetic, hook: await mailbox.defaultHook(), name: TOKEN_NAME, symbol: TOKEN_NAME, decimals: TOKEN_DECIMALS, initialSupply: TOKEN_SUPPLY, ...baseConfig, }, }; // Deploy with config const warpRoute = await deployer.deploy(config); // Derive config and check if each value matches const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig(warpRoute[chain].synthetic.address); for (const [key, value] of Object.entries(derivedConfig)) { const deployedValue = config[chain][key]; if (deployedValue && typeof value === 'string') expect(deployedValue).to.equal(value); } // Check if token values matches if (derivedConfig.type === TokenType.collateral) { expect(derivedConfig.name).to.equal(TOKEN_NAME); expect(derivedConfig.symbol).to.equal(TOKEN_NAME); } }); it('should derive native config correctly', async () => { // Create config const config = { [chain]: { type: TokenType.native, hook: await mailbox.defaultHook(), ...baseConfig, }, }; // Deploy with config const warpRoute = await deployer.deploy(config); // Derive config and check if each value matches const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig(warpRoute[chain].native.address); for (const [key, value] of Object.entries(derivedConfig)) { const deployedValue = config[chain][key]; if (deployedValue && typeof value === 'string') expect(deployedValue).to.equal(value); } // Check if token values matches expect(derivedConfig.decimals).to.equal(TOKEN_DECIMALS); }); it('should derive collateral vault config correctly', async () => { // Create config const config = { [chain]: { type: TokenType.collateralVault, token: vault.address, ...baseConfig, }, }; // Deploy with config const warpRoute = await deployer.deploy(config); // Derive config and check if each value matches const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig(warpRoute[chain].collateralVault.address); assert(derivedConfig.type === TokenType.collateralVault, 'Must be collateralVault'); expect(derivedConfig.type).to.equal(config[chain].type); expect(derivedConfig.mailbox).to.equal(config[chain].mailbox); expect(derivedConfig.owner).to.equal(config[chain].owner); expect(derivedConfig.token).to.equal(token.address); }); it('should derive rebase collateral vault config correctly', async () => { // Create config const config = { [chain]: { type: TokenType.collateralVaultRebase, token: vault.address, ...baseConfig, }, }; // Deploy with config const warpRoute = await deployer.deploy(config); // Derive config and check if each value matches const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig(warpRoute[chain].collateralVaultRebase.address); assert(derivedConfig.type === TokenType.collateralVaultRebase, 'Must be collateralVaultRebase'); expect(derivedConfig.type).to.equal(config[chain].type); expect(derivedConfig.mailbox).to.equal(config[chain].mailbox); expect(derivedConfig.owner).to.equal(config[chain].owner); expect(derivedConfig.token).to.equal(token.address); }); it('should return 0x0 if ism is not set onchain', async () => { // Create config const config = { [chain]: { type: TokenType.collateral, token: token.address, hook: await mailbox.defaultHook(), ...baseConfig, }, }; // Deploy with config const warpRoute = await deployer.deploy(config); // Derive config and check if each value matches const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig(warpRoute[chain].collateral.address); expect(derivedConfig.interchainSecurityModule).to.be.equal(zeroAddress); }); it('should return the remote routers', async () => { // Create config const otherChain = TestChainName.test3; const otherChainMetadata = test3; const config = { [chain]: { type: TokenType.collateral, token: token.address, hook: await mailbox.defaultHook(), ...baseConfig, }, [otherChain]: { type: TokenType.collateral, token: token.address, hook: await mailbox.defaultHook(), ...baseConfig, }, }; // Deploy with config const warpRoute = await deployer.deploy(config); // Derive config and check if remote router matches const derivedConfig = await evmERC20WarpRouteReader.deriveWarpRouteConfig(warpRoute[chain].collateral.address); expect(Object.keys(derivedConfig.remoteRouters).length).to.equal(1); expect(derivedConfig.remoteRouters[otherChainMetadata.domainId].address).to.be.equal(warpRoute[otherChain].collateral.address); }); }); //# sourceMappingURL=EvmERC20WarpRouteReader.hardhat-test.js.map