Add erc20 decimals and token metadata tooling (#56)

* Add decimals to synthetic ERC20

* Update config and tests for default token metadata

* Update example token config to fetch metadata

* Update with router

* Pull in 1.3.1
---------

Co-authored-by: Asa Oines <asaoines@gmail.com>
pull/2435/head
Yorke Rhodes 2 years ago committed by GitHub
parent e403671ce1
commit aff4e3a908
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      README.md
  2. 9
      configs/warp-route-token-config.json
  3. 10
      contracts/HypERC20.sol
  4. 4
      contracts/test/ERC721Test.sol
  5. 8
      package.json
  6. 46
      src/config.ts
  7. 450
      src/deploy.ts
  8. 42
      test/erc20.test.ts
  9. 40
      test/erc721.test.ts
  10. 61
      yarn.lock

@ -2,6 +2,8 @@
This repo contains the base Hyperlane ERC20 and ERC721 tokens (HypERC20 and HypERC721). These tokens extend the base standards with an additional `transferRemote` function. Warp Routes make any token or native asset interchain without custom contracts. Read more about Warp Routes and how to deploy your own at [Warp API docs](https://docs.hyperlane.xyz/docs/developers/warp-api).
**NOTE:** ERC721 collateral variants are assumed to [enumerable](https://docs.openzeppelin.com/contracts/4.x/api/token/erc721#IERC721Enumerable) and [metadata](https://docs.openzeppelin.com/contracts/4.x/api/token/erc721#IERC721Metadata) compliant.
## Versions
| Git Ref | Release Date | Notes |

@ -8,27 +8,18 @@
},
"alfajores": {
"type": "synthetic",
"name": "Weth",
"symbol": "WETH",
"totalSupply": 0,
"owner": "0x5bA371aeA18734Cb7195650aFdfCa4f9251aa513",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0xF90cB82a76492614D07B82a7658917f3aC811Ac1"
},
"fuji": {
"type": "synthetic",
"name": "Weth",
"symbol": "WETH",
"totalSupply": 0,
"owner": "0x5bA371aeA18734Cb7195650aFdfCa4f9251aa513",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0xF90cB82a76492614D07B82a7658917f3aC811Ac1"
},
"moonbasealpha": {
"type": "synthetic",
"name": "Weth",
"symbol": "WETH",
"totalSupply": 0,
"owner": "0x5bA371aeA18734Cb7195650aFdfCa4f9251aa513",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0xF90cB82a76492614D07B82a7658917f3aC811Ac1"

@ -11,6 +11,12 @@ import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/
* @dev Supply on each chain is not constant but the aggregate supply across all chains is.
*/
contract HypERC20 is ERC20Upgradeable, TokenRouter {
uint8 private immutable _decimals;
constructor(uint8 decimals) {
_decimals = decimals;
}
/**
* @notice Initializes the Hyperlane router, ERC20 metadata, and mints initial supply to deployer.
* @param _mailbox The address of the mailbox contract.
@ -37,6 +43,10 @@ contract HypERC20 is ERC20Upgradeable, TokenRouter {
_mint(msg.sender, _totalSupply);
}
function decimals() public view override returns (uint8) {
return _decimals;
}
/**
* @dev Burns `_amount` of token from `msg.sender` balance.
* @inheritdoc TokenRouter

@ -1,9 +1,9 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
contract ERC721Test is ERC721 {
contract ERC721Test is ERC721Enumerable {
constructor(
string memory name,
string memory symbol,

@ -1,11 +1,11 @@
{
"name": "@hyperlane-xyz/hyperlane-token",
"description": "A template for interchain ERC20 and ERC721 tokens using Hyperlane",
"version": "1.3.0",
"version": "1.3.1",
"dependencies": {
"@hyperlane-xyz/core": "1.3.0",
"@hyperlane-xyz/sdk": "1.3.0",
"@hyperlane-xyz/utils": "1.3.0",
"@hyperlane-xyz/core": "1.3.1",
"@hyperlane-xyz/sdk": "1.3.1",
"@hyperlane-xyz/utils": "1.3.1",
"@openzeppelin/contracts-upgradeable": "^4.8.0",
"ethers": "^5.7.2"
},

@ -1,6 +1,6 @@
import { ethers } from 'ethers';
import { GasRouterConfig, RouterConfig } from '@hyperlane-xyz/sdk';
import { GasRouterConfig } from '@hyperlane-xyz/sdk';
export enum TokenType {
synthetic = 'synthetic',
@ -10,12 +10,25 @@ export enum TokenType {
native = 'native',
}
export type SyntheticConfig = {
type: TokenType.synthetic | TokenType.syntheticUri;
export type TokenMetadata = {
name: string;
symbol: string;
totalSupply: ethers.BigNumberish;
};
export type ERC20Metadata = TokenMetadata & {
decimals: number;
};
export const isTokenMetadata = (metadata: any): metadata is TokenMetadata =>
metadata.name && metadata.symbol && metadata.totalSupply !== undefined; // totalSupply can be 0
export const isErc20Metadata = (metadata: any): metadata is ERC20Metadata =>
metadata.decimals && isTokenMetadata(metadata);
export type SyntheticConfig = TokenMetadata & {
type: TokenType.synthetic | TokenType.syntheticUri;
};
export type CollateralConfig = {
type: TokenType.collateral | TokenType.collateralUri;
token: string;
@ -44,19 +57,14 @@ export const isUriConfig = (config: TokenConfig) =>
config.type === TokenType.syntheticUri ||
config.type === TokenType.collateralUri;
export type HypERC20Config = Partial<GasRouterConfig> &
RouterConfig &
TokenConfig;
export type HypERC20CollateralConfig = Partial<GasRouterConfig> &
RouterConfig &
CollateralConfig;
export type HypNativeConfig = Partial<GasRouterConfig> &
RouterConfig &
NativeConfig;
export type HypERC721Config = Partial<GasRouterConfig> &
RouterConfig &
TokenConfig;
export type HypERC721CollateralConfig = Partial<GasRouterConfig> &
RouterConfig &
CollateralConfig;
export type HypERC20Config = GasRouterConfig & SyntheticConfig & ERC20Metadata;
export type HypERC20CollateralConfig = GasRouterConfig & CollateralConfig;
export type HypNativeConfig = GasRouterConfig & NativeConfig;
export type ERC20RouterConfig =
| HypERC20Config
| HypERC20CollateralConfig
| HypNativeConfig;
export type HypERC721Config = GasRouterConfig & SyntheticConfig;
export type HypERC721CollateralConfig = GasRouterConfig & CollateralConfig;
export type ERC721RouterConfig = HypERC721Config | HypERC721CollateralConfig;

@ -1,89 +1,143 @@
import { providers } from 'ethers';
import {
ChainMap,
ChainName,
GasRouterConfig,
GasRouterDeployer,
HyperlaneContracts,
MultiProvider,
objMap,
} from '@hyperlane-xyz/sdk';
import { DeployerOptions } from '@hyperlane-xyz/sdk/dist/deploy/HyperlaneDeployer';
import { GasConfig, RouterConfig } from '@hyperlane-xyz/sdk/dist/router/types';
import {
CollateralConfig,
ERC20Metadata,
HypERC20CollateralConfig,
HypERC20Config,
HypERC721CollateralConfig,
HypERC721Config,
HypNativeConfig,
TokenConfig,
TokenMetadata,
isCollateralConfig,
isErc20Metadata,
isNativeConfig,
isSyntheticConfig,
isUriConfig,
} from './config';
import { isTokenMetadata } from './config';
import { ERC721RouterConfig } from './config';
import { ERC20RouterConfig } from './config';
import { HypERC20Factories, HypERC721Factories } from './contracts';
import {
ERC20__factory,
ERC721EnumerableUpgradeable__factory,
HypERC20,
HypERC20Collateral,
HypERC20Collateral__factory,
HypERC20__factory,
HypERC721,
HypERC721Collateral,
HypERC721Collateral__factory,
HypERC721URICollateral__factory,
HypERC721URIStorage__factory,
HypERC721__factory,
HypNative,
HypNative__factory,
} from './types';
enum TokenType {
erc20 = 'erc20',
erc721 = 'erc721',
}
const gasDefaults = (config: TokenConfig, tokenType: TokenType) => {
switch (tokenType) {
case TokenType.erc721:
switch (config.type) {
case 'synthetic':
return 160_000;
case 'syntheticUri':
return 163_000;
case 'collateral':
case 'collateralUri':
default:
return 80_000;
}
default:
case TokenType.erc20:
switch (config.type) {
case 'synthetic':
return 64_000;
case 'native':
return 44_000;
case 'collateral':
default:
return 68_000;
}
}
};
export class HypERC20Deployer extends GasRouterDeployer<
HypERC20Config & GasRouterConfig,
ERC20RouterConfig,
HypERC20Factories
> {
constructor(
multiProvider: MultiProvider,
configMap: ChainMap<HypERC20Config>,
factories: any,
options?: DeployerOptions,
) {
super(
multiProvider,
objMap(
configMap,
(_, config): HypERC20Config & GasRouterConfig =>
({
...config,
gas: config.gas ?? gasDefaults(config, TokenType.erc20),
} as HypERC20Config & GasRouterConfig),
constructor(multiProvider: MultiProvider) {
super(multiProvider, {} as HypERC20Factories); // factories not used in deploy
}
static async fetchMetadata(
provider: providers.Provider,
config: CollateralConfig,
): Promise<ERC20Metadata> {
const erc20 = ERC20__factory.connect(config.token, provider);
const [name, symbol, totalSupply, decimals] = await Promise.all([
erc20.name(),
erc20.symbol(),
erc20.totalSupply(),
erc20.decimals(),
]);
return { name, symbol, totalSupply, decimals };
}
static gasOverheadDefault(config: TokenConfig): number {
switch (config.type) {
case 'synthetic':
return 64_000;
case 'native':
return 44_000;
case 'collateral':
default:
return 68_000;
}
}
protected async deployCollateral(
chain: ChainName,
config: HypERC20CollateralConfig,
): Promise<HypERC20Collateral> {
const router = await this.deployContractFromFactory(
chain,
new HypERC20Collateral__factory(),
'HypERC20Collateral',
[config.token],
);
await this.multiProvider.handleTx(
chain,
router.initialize(config.mailbox, config.interchainGasPaymaster),
);
return router;
}
protected async deployNative(
chain: ChainName,
config: HypNativeConfig,
): Promise<HypNative> {
const router = await this.deployContractFromFactory(
chain,
new HypNative__factory(),
'HypNative',
[],
);
await this.multiProvider.handleTx(
chain,
router.initialize(config.mailbox, config.interchainGasPaymaster),
);
return router;
}
protected async deploySynthetic(
chain: ChainName,
config: HypERC20Config,
): Promise<HypERC20> {
const router = await this.deployContractFromFactory(
chain,
new HypERC20__factory(),
'HypERC20',
[config.decimals],
);
await this.multiProvider.handleTx(
chain,
router.initialize(
config.mailbox,
config.interchainGasPaymaster,
config.totalSupply,
config.name,
config.symbol,
),
factories,
options,
);
return router;
}
router(contracts: HyperlaneContracts<HypERC20Factories>) {
@ -91,119 +145,233 @@ export class HypERC20Deployer extends GasRouterDeployer<
}
async deployContracts(chain: ChainName, config: HypERC20Config) {
let router: HypERC20 | HypERC20Collateral | HypNative;
if (isCollateralConfig(config)) {
const router = await this.deployContractFromFactory(
chain,
new HypERC20Collateral__factory(),
'HypERC20Collateral',
[config.token],
);
await this.multiProvider.handleTx(
chain,
router.initialize(config.mailbox, config.interchainGasPaymaster),
);
return { router };
} else if (isSyntheticConfig(config)) {
const router = await this.deployContractFromFactory(
chain,
new HypERC20__factory(),
'HypERC20',
[],
);
await this.multiProvider.handleTx(
chain,
router.initialize(
config.mailbox,
config.interchainGasPaymaster,
config.totalSupply,
config.name,
config.symbol,
),
);
return { router };
router = await this.deployCollateral(chain, config);
} else if (isNativeConfig(config)) {
const router = await this.deployContractFromFactory(
chain,
new HypNative__factory(),
'HypNative',
[],
);
await this.multiProvider.handleTx(
chain,
router.initialize(config.mailbox, config.interchainGasPaymaster),
);
return { router };
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');
}
return { router };
}
async buildTokenMetadata(
configMap: ChainMap<TokenConfig>,
): Promise<ChainMap<ERC20Metadata>> {
let tokenMetadata: ERC20Metadata | undefined;
for (const [chain, config] of Object.entries(configMap)) {
if (isCollateralConfig(config)) {
const collateralMetadata = await HypERC20Deployer.fetchMetadata(
this.multiProvider.getProvider(chain),
config,
);
tokenMetadata = {
...collateralMetadata,
totalSupply: 0,
};
} else if (isNativeConfig(config)) {
const chainMetadata = this.multiProvider.getChainMetadata(chain);
if (chainMetadata.nativeToken) {
tokenMetadata = {
...chainMetadata.nativeToken,
totalSupply: 0,
};
}
} else if (isErc20Metadata(config)) {
tokenMetadata = config;
}
}
if (!isErc20Metadata(tokenMetadata)) {
throw new Error('Invalid ERC20 token metadata');
}
throw new Error('Invalid config');
return objMap(configMap, () => tokenMetadata!);
}
buildGasOverhead(configMap: ChainMap<TokenConfig>): ChainMap<GasConfig> {
return objMap(configMap, (_, config) => ({
gas: HypERC20Deployer.gasOverheadDefault(config),
}));
}
async deploy(configMap: ChainMap<TokenConfig & RouterConfig>) {
const tokenMetadata = await this.buildTokenMetadata(configMap);
const gasOverhead = this.buildGasOverhead(configMap);
const mergedConfig = objMap(configMap, (chain, config) => {
return {
...tokenMetadata[chain],
...gasOverhead[chain],
...config,
};
}) as ChainMap<ERC20RouterConfig>;
return super.deploy(mergedConfig);
}
}
// TODO: dedupe?
export class HypERC721Deployer extends GasRouterDeployer<
HypERC721Config & GasRouterConfig,
ERC721RouterConfig,
HypERC721Factories
> {
constructor(
multiProvider: MultiProvider,
configMap: ChainMap<HypERC721Config>,
factories: any,
options?: DeployerOptions,
) {
super(
multiProvider,
objMap(
configMap,
(_, config): HypERC721Config & GasRouterConfig =>
({
...config,
gas: config.gas ?? gasDefaults(config, TokenType.erc721),
} as HypERC721Config & GasRouterConfig),
),
factories,
options,
constructor(multiProvider: MultiProvider) {
super(multiProvider, {} as HypERC721Factories); // factories not used in deploy
}
static async fetchMetadata(
provider: providers.Provider,
config: CollateralConfig,
): Promise<TokenMetadata> {
const erc721 = ERC721EnumerableUpgradeable__factory.connect(
config.token,
provider,
);
const [name, symbol, totalSupply] = await Promise.all([
erc721.name(),
erc721.symbol(),
erc721.totalSupply(),
]);
return { name, symbol, totalSupply };
}
router(contracts: HyperlaneContracts<HypERC721Factories>) {
return contracts.router;
static gasOverheadDefault(config: TokenConfig): number {
switch (config.type) {
case 'synthetic':
return 160_000;
case 'syntheticUri':
return 163_000;
case 'collateral':
case 'collateralUri':
default:
return 80_000;
}
}
async deployContracts(chain: ChainName, config: HypERC721Config) {
if (isCollateralConfig(config)) {
const router = await this.deployContractFromFactory(
protected async deployCollateral(
chain: ChainName,
config: HypERC721CollateralConfig,
): Promise<HypERC721Collateral> {
let router: HypERC721Collateral;
if (isUriConfig(config)) {
router = await this.deployContractFromFactory(
chain,
isUriConfig(config)
? new HypERC721URICollateral__factory()
: new HypERC721Collateral__factory(),
`HypERC721${isUriConfig(config) ? 'URI' : ''}Collateral`,
new HypERC721URICollateral__factory(),
'HypERC721URICollateral',
[config.token],
);
await this.multiProvider.handleTx(
} else {
router = await this.deployContractFromFactory(
chain,
router.initialize(config.mailbox, config.interchainGasPaymaster),
new HypERC721Collateral__factory(),
'HypERC721Collateral',
[config.token],
);
return { router };
} else if (isSyntheticConfig(config)) {
const router = await this.deployContractFromFactory(
}
await this.multiProvider.handleTx(
chain,
router.initialize(config.mailbox, config.interchainGasPaymaster),
);
return router;
}
protected async deploySynthetic(
chain: ChainName,
config: HypERC721Config,
): Promise<HypERC721> {
let router: HypERC721;
if (isUriConfig(config)) {
router = await this.deployContractFromFactory(
chain,
isUriConfig(config)
? new HypERC721URIStorage__factory()
: new HypERC721__factory(),
`HypERC721${isUriConfig(config) ? 'URIStorage' : ''}`,
new HypERC721URIStorage__factory(),
'HypERC721URIStorage',
[],
);
await this.multiProvider.handleTx(
} else {
router = await this.deployContractFromFactory(
chain,
router.initialize(
config.mailbox,
config.interchainGasPaymaster,
config.totalSupply,
config.name,
config.symbol,
),
new HypERC721__factory(),
'HypERC721',
[],
);
return { router };
}
throw new Error('Invalid config');
await this.multiProvider.handleTx(
chain,
router.initialize(
config.mailbox,
config.interchainGasPaymaster,
config.totalSupply,
config.name,
config.symbol,
),
);
return router;
}
router(contracts: HyperlaneContracts<HypERC721Factories>) {
return contracts.router;
}
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');
}
return { router };
}
async buildTokenMetadata(
configMap: ChainMap<TokenConfig>,
): Promise<ChainMap<TokenMetadata>> {
let tokenMetadata: TokenMetadata | undefined;
for (const [chain, config] of Object.entries(configMap)) {
if (isCollateralConfig(config)) {
const collateralMetadata = await HypERC721Deployer.fetchMetadata(
this.multiProvider.getProvider(chain),
config,
);
tokenMetadata = {
...collateralMetadata,
totalSupply: 0,
};
} else if (isTokenMetadata(config)) {
tokenMetadata = config;
}
}
if (!isTokenMetadata(tokenMetadata)) {
throw new Error('Invalid ERC721 token metadata');
}
return objMap(configMap, () => tokenMetadata!);
}
buildGasOverhead(configMap: ChainMap<TokenConfig>): ChainMap<GasConfig> {
return objMap(configMap, (_, config) => ({
gas: HypERC721Deployer.gasOverheadDefault(config),
}));
}
async deploy(configMap: ChainMap<TokenConfig & RouterConfig>) {
const tokenMetadata = await this.buildTokenMetadata(configMap);
const gasOverhead = this.buildGasOverhead(configMap);
const mergedConfig = objMap(configMap, (chain, config) => {
return {
...tokenMetadata[chain],
...gasOverhead[chain],
...config,
};
}) as ChainMap<ERC721RouterConfig>;
return super.deploy(mergedConfig);
}
}

@ -10,6 +10,7 @@ import {
Chains,
HyperlaneContractsMap,
MultiProvider,
RouterConfig,
TestCoreApp,
TestCoreDeployer,
deployTestIgpsAndGetRouterConfig,
@ -17,12 +18,7 @@ import {
} from '@hyperlane-xyz/sdk';
import { utils } from '@hyperlane-xyz/utils';
import {
HypERC20Config,
SyntheticConfig,
TokenConfig,
TokenType,
} from '../src/config';
import { TokenConfig, TokenType } from '../src/config';
import { HypERC20Factories } from '../src/contracts';
import { HypERC20Deployer } from '../src/deploy';
import {
@ -41,10 +37,10 @@ let remoteDomain: number;
const totalSupply = 3000;
const amount = 10;
const tokenConfig: SyntheticConfig = {
type: TokenType.synthetic,
const tokenMetadata = {
name: 'HypERC20',
symbol: 'HYP',
decimals: 18,
totalSupply,
};
@ -59,9 +55,9 @@ for (const variant of [
let core: TestCoreApp;
let deployer: HypERC20Deployer;
let contracts: HyperlaneContractsMap<HypERC20Factories>;
let localTokenConfig: TokenConfig = tokenConfig;
let localTokenConfig: TokenConfig;
let local: HypERC20 | HypERC20Collateral | HypNative;
let remote: HypERC20 | HypERC20Collateral;
let remote: HypERC20;
let interchainGasPayment: BigNumber;
beforeEach(async () => {
@ -75,7 +71,7 @@ for (const variant of [
const coreDeployer = new TestCoreDeployer(multiProvider);
const coreContractsMaps = await coreDeployer.deploy();
core = new TestCoreApp(coreContractsMaps, multiProvider);
const coreConfig = await deployTestIgpsAndGetRouterConfig(
const routerConfig = await deployTestIgpsAndGetRouterConfig(
multiProvider,
owner.address,
core.contractsMap,
@ -84,9 +80,9 @@ for (const variant of [
let erc20: ERC20 | undefined;
if (variant === TokenType.collateral) {
erc20 = await new ERC20Test__factory(owner).deploy(
tokenConfig.name,
tokenConfig.symbol,
tokenConfig.totalSupply,
tokenMetadata.name,
tokenMetadata.symbol,
tokenMetadata.totalSupply,
);
localTokenConfig = {
type: variant,
@ -96,17 +92,21 @@ for (const variant of [
localTokenConfig = {
type: variant,
};
} else if (variant === TokenType.synthetic) {
localTokenConfig = { type: variant, ...tokenMetadata };
}
const config: ChainMap<HypERC20Config> = objMap(coreConfig, (key) => ({
...coreConfig[key],
...(key === localChain ? localTokenConfig : tokenConfig),
const config = objMap(routerConfig, (key) => ({
...routerConfig[key],
...(key === localChain
? localTokenConfig
: { type: TokenType.synthetic }),
owner: owner.address,
}));
})) as ChainMap<TokenConfig & RouterConfig>;
deployer = new HypERC20Deployer(multiProvider, config, core);
contracts = await deployer.deploy();
local = contracts[localChain].router as HypERC20;
deployer = new HypERC20Deployer(multiProvider);
contracts = await deployer.deploy(config);
local = contracts[localChain].router;
interchainGasPayment = await local.quoteGasPayment(remoteDomain);

@ -6,7 +6,6 @@ import { ethers } from 'hardhat';
import { InterchainGasPaymaster__factory } from '@hyperlane-xyz/core';
import {
ChainMap,
Chains,
HyperlaneContractsMap,
MultiProvider,
@ -17,12 +16,7 @@ import {
} from '@hyperlane-xyz/sdk';
import { utils } from '@hyperlane-xyz/utils';
import {
HypERC721CollateralConfig,
HypERC721Config,
SyntheticConfig,
TokenType,
} from '../src/config';
import { TokenConfig, TokenType } from '../src/config';
import { HypERC721Factories } from '../src/contracts';
import { HypERC721Deployer } from '../src/deploy';
import {
@ -45,20 +39,21 @@ const tokenId2 = 20;
const tokenId3 = 30;
const tokenId4 = 40;
const tokenMetadata = {
name: 'HypERC721',
symbol: 'HYP',
totalSupply,
};
for (const withCollateral of [true, false]) {
for (const withUri of [true, false]) {
const tokenConfig: SyntheticConfig = {
const tokenConfig: TokenConfig = {
type: withUri ? TokenType.syntheticUri : TokenType.synthetic,
name: 'HypERC721',
symbol: 'HYP',
totalSupply,
...tokenMetadata,
};
const configMap = {
test1: {
...tokenConfig,
totalSupply,
},
test1: tokenConfig,
test2: {
...tokenConfig,
totalSupply: 0,
@ -96,9 +91,7 @@ for (const withCollateral of [true, false]) {
owner.address,
core.contractsMap,
);
const configWithTokenInfo: ChainMap<
HypERC721Config | HypERC721CollateralConfig
> = objMap(coreConfig, (key) => ({
const configWithTokenInfo = objMap(coreConfig, (key) => ({
...coreConfig[key],
...configMap[key],
owner: owner.address,
@ -112,18 +105,15 @@ for (const withCollateral of [true, false]) {
tokenConfig.totalSupply,
);
configWithTokenInfo.test1 = {
...configWithTokenInfo.test1,
type: withUri ? TokenType.collateralUri : TokenType.collateral,
token: erc721.address,
...coreConfig.test1,
};
}
deployer = new HypERC721Deployer(
multiProvider,
configWithTokenInfo,
core,
);
contracts = await deployer.deploy();
deployer = new HypERC721Deployer(multiProvider);
contracts = await deployer.deploy(configWithTokenInfo);
local = contracts[localChain].router;
if (withCollateral) {
// approve wrapper to transfer tokens

@ -1220,14 +1220,14 @@ __metadata:
languageName: node
linkType: hard
"@hyperlane-xyz/core@npm:1.3.0":
version: 1.3.0
resolution: "@hyperlane-xyz/core@npm:1.3.0"
"@hyperlane-xyz/core@npm:1.3.1":
version: 1.3.1
resolution: "@hyperlane-xyz/core@npm:1.3.1"
dependencies:
"@hyperlane-xyz/utils": 1.3.0
"@hyperlane-xyz/utils": 1.3.1
"@openzeppelin/contracts": ^4.8.0
"@openzeppelin/contracts-upgradeable": ^4.8.0
checksum: 8e4c8e72dee2ff2705697f802de06d29fcbdb8789883f051977bbb82748d842647d6274691d918edafa03fa18e9e2fb0359c6af4d8d7f7f99cbe2167a2aef1f4
checksum: bb341b6ab2f7bbde057082ec277d48df5918b5a4c676887af9b49a54f9dc2d349c34cf74de7b1df20bddbadbdc7467628d3689182c01702cb21e0ac0e4e71981
languageName: node
linkType: hard
@ -1235,9 +1235,9 @@ __metadata:
version: 0.0.0-use.local
resolution: "@hyperlane-xyz/hyperlane-token@workspace:."
dependencies:
"@hyperlane-xyz/core": 1.3.0
"@hyperlane-xyz/sdk": 1.3.0
"@hyperlane-xyz/utils": 1.3.0
"@hyperlane-xyz/core": 1.3.1
"@hyperlane-xyz/sdk": 1.3.1
"@hyperlane-xyz/utils": 1.3.1
"@nomiclabs/hardhat-ethers": ^2.2.1
"@nomiclabs/hardhat-waffle": ^2.0.3
"@openzeppelin/contracts-upgradeable": ^4.8.0
@ -1265,28 +1265,30 @@ __metadata:
languageName: unknown
linkType: soft
"@hyperlane-xyz/sdk@npm:1.3.0":
version: 1.3.0
resolution: "@hyperlane-xyz/sdk@npm:1.3.0"
"@hyperlane-xyz/sdk@npm:1.3.1":
version: 1.3.1
resolution: "@hyperlane-xyz/sdk@npm:1.3.1"
dependencies:
"@hyperlane-xyz/core": 1.3.0
"@hyperlane-xyz/utils": 1.3.0
"@hyperlane-xyz/core": 1.3.1
"@hyperlane-xyz/utils": 1.3.1
"@types/coingecko-api": ^1.0.10
"@types/debug": ^4.1.7
"@wagmi/chains": ^0.2.6
coingecko-api: ^1.0.10
cross-fetch: ^3.1.5
debug: ^4.3.4
ethers: ^5.7.2
zod: ^3.21.2
checksum: ef8f964b58cf16bd514ed09b8f22c484dcd08385510aa67bbcb896b7a95c103b7f029d66ef676807b07a9be1aaf816d937fce7d5848f9f38529373d2f276be3d
checksum: 3b1339dafb9ea8ba7c91ac3a51fd86638808bc60a06abd36e94fdc86316a7d591b395e5c94f9646d63331bde258f5013ee434e014ddf4d1db3d20a9b6b81f5dc
languageName: node
linkType: hard
"@hyperlane-xyz/utils@npm:1.3.0":
version: 1.3.0
resolution: "@hyperlane-xyz/utils@npm:1.3.0"
"@hyperlane-xyz/utils@npm:1.3.1":
version: 1.3.1
resolution: "@hyperlane-xyz/utils@npm:1.3.1"
dependencies:
ethers: ^5.7.2
checksum: 22008ac00bc37f23387b5988fa22c9066796dfa5bcc115a1cd51087b160115279cb3fa57061545fa3053de660750a27bbdb94ef8daa47abbfdf0cef8013dc787
checksum: 960c972211618ea9b637bf98cdaf052f6175aa535ba6402617b84110731fe2657f8cdb387cc2be24c8250e87d46a99320f7d609067ee8e42b5d98644d0db4f95
languageName: node
linkType: hard
@ -1803,6 +1805,13 @@ __metadata:
languageName: node
linkType: hard
"@types/coingecko-api@npm:^1.0.10":
version: 1.0.10
resolution: "@types/coingecko-api@npm:1.0.10"
checksum: e9683f9ea9ce2f855f6565089981dd3fceb6c4674365438f3fc3877d089a2fb82cdea011b59d59c7baa1635dc610860cd29a10a4b7a650ff96521ead46f22a50
languageName: node
linkType: hard
"@types/concat-stream@npm:^1.6.0":
version: 1.6.1
resolution: "@types/concat-stream@npm:1.6.1"
@ -1812,6 +1821,15 @@ __metadata:
languageName: node
linkType: hard
"@types/debug@npm:^4.1.7":
version: 4.1.7
resolution: "@types/debug@npm:4.1.7"
dependencies:
"@types/ms": "*"
checksum: 0a7b89d8ed72526858f0b61c6fd81f477853e8c4415bb97f48b1b5545248d2ae389931680b94b393b993a7cfe893537a200647d93defe6d87159b96812305adc
languageName: node
linkType: hard
"@types/form-data@npm:0.0.33":
version: 0.0.33
resolution: "@types/form-data@npm:0.0.33"
@ -1895,6 +1913,13 @@ __metadata:
languageName: node
linkType: hard
"@types/ms@npm:*":
version: 0.7.31
resolution: "@types/ms@npm:0.7.31"
checksum: daadd354aedde024cce6f5aa873fefe7b71b22cd0e28632a69e8b677aeb48ae8caa1c60e5919bb781df040d116b01cb4316335167a3fc0ef6a63fa3614c0f6da
languageName: node
linkType: hard
"@types/node-fetch@npm:^2.5.5":
version: 2.6.2
resolution: "@types/node-fetch@npm:2.6.2"

Loading…
Cancel
Save