Updates for compat with SDK 1.2.0 (#47)

pull/2435/head
J M Rossy 2 years ago committed by GitHub
parent aafbb53e92
commit 4c273a3925
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      package.json
  2. 70
      src/app.ts
  3. 34
      src/config.ts
  4. 94
      src/deploy.ts
  5. 41
      test/erc20.test.ts
  6. 24
      test/erc721.test.ts
  7. 46
      yarn.lock

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

@ -1,10 +1,6 @@
import { BigNumberish } from 'ethers';
import {
ChainName,
GasRouterApp,
RouterContracts,
} from '@hyperlane-xyz/sdk';
import { ChainName, GasRouterApp, RouterContracts } from '@hyperlane-xyz/sdk';
import { types } from '@hyperlane-xyz/utils';
import { HypERC20Contracts, HypERC721Contracts } from './contracts';
@ -12,40 +8,42 @@ import { TokenRouter } from './types';
class HyperlaneTokenApp<
Contracts extends RouterContracts<TokenRouter>,
Chain extends ChainName,
> extends GasRouterApp<Contracts, Chain> {
async transfer<Origin extends Chain>(
origin: Origin,
destination: Exclude<Chain, Origin>,
> extends GasRouterApp<Contracts> {
async transfer(
origin: ChainName,
destination: ChainName,
recipient: types.Address,
amountOrId: BigNumberish,
) {
const originRouter = this.getContracts(origin).router;
const destinationChainConnection = this.multiProvider.getChainConnection(destination);
const destinationNetwork = await destinationChainConnection.provider.getNetwork();
const gasPayment = await originRouter.quoteGasPayment(destinationNetwork.chainId);
const chainConnection = this.multiProvider.getChainConnection(origin);
return chainConnection.handleTx(
originRouter.transferRemote(destinationNetwork.chainId, recipient, amountOrId, {
value: gasPayment,
}),
const destProvider = this.multiProvider.getProvider(destination);
const destinationNetwork = await destProvider.getNetwork();
const gasPayment = await originRouter.quoteGasPayment(
destinationNetwork.chainId,
);
return this.multiProvider.handleTx(
origin,
originRouter.transferRemote(
destinationNetwork.chainId,
recipient,
amountOrId,
{
value: gasPayment,
},
),
);
}
}
export class HypERC20App<Chain extends ChainName> extends HyperlaneTokenApp<
HypERC20Contracts,
Chain
> {
async transfer<Origin extends Chain>(
origin: Origin,
destination: Exclude<Chain, Origin>,
export class HypERC20App extends HyperlaneTokenApp<HypERC20Contracts> {
async transfer(
origin: ChainName,
destination: ChainName,
recipient: types.Address,
amount: BigNumberish,
) {
const originRouter = this.getContracts(origin).router;
const chainConnection = this.multiProvider.getChainConnection(origin);
const signerAddress = await chainConnection.signer!.getAddress();
const signerAddress = await this.multiProvider.getSignerAddress(origin);
const balance = await originRouter.balanceOf(signerAddress);
if (balance.lt(amount))
console.warn(
@ -55,22 +53,20 @@ export class HypERC20App<Chain extends ChainName> extends HyperlaneTokenApp<
}
}
export class HypERC721App<Chain extends ChainName> extends HyperlaneTokenApp<
HypERC721Contracts,
Chain
> {
async transfer<Origin extends Chain>(
origin: Origin,
destination: Exclude<Chain, Origin>,
export class HypERC721App extends HyperlaneTokenApp<HypERC721Contracts> {
async transfer(
origin: ChainName,
destination: ChainName,
recipient: types.Address,
tokenId: BigNumberish,
) {
const originRouter = this.getContracts(origin).router;
const chainConnection = this.multiProvider.getChainConnection(origin);
const signerAddress = await chainConnection.signer!.getAddress();
const signerAddress = await this.multiProvider.getSignerAddress(origin);
const owner = await originRouter.ownerOf(tokenId);
if (signerAddress != owner)
console.warn(`Signer ${signerAddress} not owner of token ${tokenId} on ${origin}`);
console.warn(
`Signer ${signerAddress} not owner of token ${tokenId} on ${origin}`,
);
return super.transfer(origin, destination, recipient, tokenId);
}
}

@ -7,7 +7,7 @@ export enum TokenType {
syntheticUri = 'syntheticUri',
collateral = 'collateral',
collateralUri = 'collateralUri',
native = 'native'
native = 'native',
}
export type SyntheticConfig = {
@ -29,22 +29,34 @@ export type TokenConfig = SyntheticConfig | CollateralConfig | NativeConfig;
export const isCollateralConfig = (
config: TokenConfig,
): config is CollateralConfig =>
(config.type === TokenType.collateral ||
config.type === TokenType.collateralUri);
config.type === TokenType.collateral ||
config.type === TokenType.collateralUri;
export const isSyntheticConfig = (
config: TokenConfig,
): config is SyntheticConfig => config.type === TokenType.synthetic || config.type === TokenType.syntheticUri;
): config is SyntheticConfig =>
config.type === TokenType.synthetic || config.type === TokenType.syntheticUri;
export const isNativeConfig = (config: TokenConfig): config is NativeConfig => config.type === TokenType.native;
export const isNativeConfig = (config: TokenConfig): config is NativeConfig =>
config.type === TokenType.native;
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 = 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;

@ -4,18 +4,18 @@ import {
GasRouterConfig,
GasRouterDeployer,
MultiProvider,
objMap
objMap,
} from '@hyperlane-xyz/sdk';
import { DeployerOptions } from '@hyperlane-xyz/sdk/dist/deploy/HyperlaneDeployer';
import {
HypERC20Config,
HypERC721Config,
TokenConfig,
isCollateralConfig,
isNativeConfig,
isSyntheticConfig,
isUriConfig,
TokenConfig,
} from './config';
import { HypERC20Contracts, HypERC721Contracts } from './contracts';
import {
@ -47,7 +47,7 @@ const gasDefaults = (config: TokenConfig, tokenType: TokenType) => {
return 80_000;
}
default:
case TokenType.erc20:
case TokenType.erc20:
switch (config.type) {
case 'synthetic':
return 64_000;
@ -58,28 +58,35 @@ const gasDefaults = (config: TokenConfig, tokenType: TokenType) => {
return 68_000;
}
}
}
};
export class HypERC20Deployer<
Chain extends ChainName // inferred from configured chains passed to constructor
> extends GasRouterDeployer<
Chain,
export class HypERC20Deployer extends GasRouterDeployer<
HypERC20Config & GasRouterConfig,
HypERC20Contracts,
any // RouterFactories doesn't work well when router has multiple types
> {
constructor(multiProvider: MultiProvider<Chain>, configMap: ChainMap<Chain, HypERC20Config>, factories: any, options?: DeployerOptions) {
super(multiProvider, objMap(configMap, (_, config): HypERC20Config & GasRouterConfig => ({
...config,
gas: config.gas ?? gasDefaults(config, TokenType.erc20)
} as HypERC20Config & GasRouterConfig)), factories, options);
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),
),
factories,
options,
);
}
async deployContracts(
chain: Chain,
config: HypERC20Config,
) {
const connection = this.multiProvider.getChainConnection(chain);
async deployContracts(chain: ChainName, config: HypERC20Config) {
if (isCollateralConfig(config)) {
const router = await this.deployContractFromFactory(
chain,
@ -87,7 +94,8 @@ export class HypERC20Deployer<
'HypERC20Collateral',
[config.token],
);
await connection.handleTx(
await this.multiProvider.handleTx(
chain,
router.initialize(config.mailbox, config.interchainGasPaymaster),
);
return { router };
@ -98,8 +106,8 @@ export class HypERC20Deployer<
'HypERC20',
[],
);
await connection.handleTx(
await this.multiProvider.handleTx(
chain,
router.initialize(
config.mailbox,
config.interchainGasPaymaster,
@ -116,7 +124,8 @@ export class HypERC20Deployer<
'HypNative',
[],
);
await connection.handleTx(
await this.multiProvider.handleTx(
chain,
router.initialize(config.mailbox, config.interchainGasPaymaster),
);
return { router };
@ -126,26 +135,33 @@ export class HypERC20Deployer<
}
// TODO: dedupe?
export class HypERC721Deployer<
Chain extends ChainName
> extends GasRouterDeployer<
Chain,
export class HypERC721Deployer extends GasRouterDeployer<
HypERC721Config & GasRouterConfig,
HypERC721Contracts,
any
> {
constructor(multiProvider: MultiProvider<Chain>, configMap: ChainMap<Chain, 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,
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,
);
}
async deployContracts(
chain: Chain,
config: HypERC721Config,
) {
const connection = this.multiProvider.getChainConnection(chain);
async deployContracts(chain: ChainName, config: HypERC721Config) {
if (isCollateralConfig(config)) {
const router = await this.deployContractFromFactory(
chain,
@ -155,7 +171,8 @@ export class HypERC721Deployer<
`HypERC721${isUriConfig(config) ? 'URI' : ''}Collateral`,
[config.token],
);
await connection.handleTx(
await this.multiProvider.handleTx(
chain,
router.initialize(config.mailbox, config.interchainGasPaymaster),
);
return { router };
@ -168,7 +185,8 @@ export class HypERC721Deployer<
`HypERC721${isUriConfig(config) ? 'URIStorage' : ''}`,
[],
);
await connection.handleTx(
await this.multiProvider.handleTx(
chain,
router.initialize(
config.mailbox,
config.interchainGasPaymaster,

@ -1,17 +1,15 @@
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import '@nomiclabs/hardhat-waffle';
import { expect } from 'chai';
import { BigNumber } from 'ethers';
import { BigNumberish } from 'ethers';
import { BigNumber, BigNumberish } from 'ethers';
import { ethers } from 'hardhat';
import {
ChainMap,
ChainNameToDomainId,
TestChainNames,
Chains,
MultiProvider,
TestCoreApp,
TestCoreDeployer,
getTestMultiProvider,
objMap,
} from '@hyperlane-xyz/sdk';
import { utils } from '@hyperlane-xyz/utils';
@ -33,10 +31,10 @@ import {
HypNative,
} from '../src/types';
const localChain = 'test1';
const remoteChain = 'test2';
const localDomain = ChainNameToDomainId[localChain];
const remoteDomain = ChainNameToDomainId[remoteChain];
const localChain = Chains.test1;
const remoteChain = Chains.test2;
let localDomain: number;
let remoteDomain: number;
const totalSupply = 3000;
const amount = 10;
@ -56,8 +54,8 @@ for (const variant of [
let owner: SignerWithAddress;
let recipient: SignerWithAddress;
let core: TestCoreApp;
let deployer: HypERC20Deployer<TestChainNames>;
let contracts: Record<TestChainNames, HypERC20Contracts>;
let deployer: HypERC20Deployer;
let contracts: ChainMap<HypERC20Contracts>;
let localTokenConfig: TokenConfig = tokenConfig;
let local: HypERC20 | HypERC20Collateral | HypNative;
let remote: HypERC20 | HypERC20Collateral;
@ -65,7 +63,11 @@ for (const variant of [
beforeEach(async () => {
[owner, recipient] = await ethers.getSigners();
const multiProvider = getTestMultiProvider(owner);
const multiProvider = MultiProvider.createTestMultiProvider({
signer: owner,
});
localDomain = multiProvider.getDomainId(localChain);
remoteDomain = multiProvider.getDomainId(remoteChain);
const coreDeployer = new TestCoreDeployer(multiProvider);
const coreContractsMaps = await coreDeployer.deploy();
@ -89,14 +91,11 @@ for (const variant of [
};
}
const config: ChainMap<TestChainNames, HypERC20Config> = objMap(
coreConfig,
(key) => ({
...coreConfig[key],
...(key === localChain ? localTokenConfig : tokenConfig),
owner: owner.address,
}),
);
const config: ChainMap<HypERC20Config> = objMap(coreConfig, (key) => ({
...coreConfig[key],
...(key === localChain ? localTokenConfig : tokenConfig),
owner: owner.address,
}));
deployer = new HypERC20Deployer(multiProvider, config, core);
contracts = await deployer.deploy();
@ -160,7 +159,7 @@ for (const variant of [
const token = ERC20__factory.connect(tokenAddress, owner);
await token.transfer(local.address, totalSupply);
} else if (variant === TokenType.native) {
const remoteDomain = ChainNameToDomainId[remoteChain];
const remoteDomain = core.multiProvider.getDomainId(remoteChain);
// deposit amount
await local.transferRemote(
remoteDomain,

@ -6,11 +6,10 @@ import { ethers } from 'hardhat';
import {
ChainMap,
ChainNameToDomainId,
TestChainNames,
Chains,
MultiProvider,
TestCoreApp,
TestCoreDeployer,
getTestMultiProvider,
objMap,
} from '@hyperlane-xyz/sdk';
import { utils } from '@hyperlane-xyz/utils';
@ -33,10 +32,10 @@ import {
HypERC721URIStorage,
} from '../src/types';
const localChain = 'test1';
const remoteChain = 'test2';
const localDomain = ChainNameToDomainId[localChain];
const remoteDomain = ChainNameToDomainId[remoteChain];
const localChain = Chains.test1;
const remoteChain = Chains.test2;
let localDomain: number;
let remoteDomain: number;
const totalSupply = 50;
const tokenId = 10;
const tokenId2 = 20;
@ -72,22 +71,25 @@ for (const withCollateral of [true, false]) {
let owner: SignerWithAddress;
let recipient: SignerWithAddress;
let core: TestCoreApp;
let deployer: HypERC721Deployer<TestChainNames>;
let contracts: Record<TestChainNames, HypERC721Contracts>;
let deployer: HypERC721Deployer;
let contracts: ChainMap<HypERC721Contracts>;
let local: HypERC721 | HypERC721Collateral | HypERC721URICollateral;
let remote: HypERC721 | HypERC721Collateral | HypERC721URIStorage;
let gas: BigNumberish;
beforeEach(async () => {
[owner, recipient] = await ethers.getSigners();
const multiProvider = getTestMultiProvider(owner);
const multiProvider = MultiProvider.createTestMultiProvider({
signer: owner,
});
localDomain = multiProvider.getDomainId(localChain);
remoteDomain = multiProvider.getDomainId(remoteChain);
const coreDeployer = new TestCoreDeployer(multiProvider);
const coreContractsMaps = await coreDeployer.deploy();
core = new TestCoreApp(coreContractsMaps, multiProvider);
const coreConfig = core.getConnectionClientConfigMap();
const configWithTokenInfo: ChainMap<
TestChainNames,
HypERC721Config | HypERC721CollateralConfig
> = objMap(coreConfig, (key) => ({
...coreConfig[key],

@ -1220,23 +1220,14 @@ __metadata:
languageName: node
linkType: hard
"@hyperlane-xyz/celo-ethers-provider@npm:^0.1.1":
version: 0.1.1
resolution: "@hyperlane-xyz/celo-ethers-provider@npm:0.1.1"
peerDependencies:
ethers: ^5
checksum: 5ea495505b3e4338ec6c419f69b66af2d35b86e7cdab9bc7ee65ba4a233729b2143b0a72cc637f8e8795ecacc18eeda5ac803e8b3de9a63e7ceb5dc14014b3d4
languageName: node
linkType: hard
"@hyperlane-xyz/core@npm:1.1.4":
version: 1.1.4
resolution: "@hyperlane-xyz/core@npm:1.1.4"
"@hyperlane-xyz/core@npm:1.2.0":
version: 1.2.0
resolution: "@hyperlane-xyz/core@npm:1.2.0"
dependencies:
"@hyperlane-xyz/utils": 1.1.4
"@hyperlane-xyz/utils": 1.2.0
"@openzeppelin/contracts": ^4.8.0
"@openzeppelin/contracts-upgradeable": ^4.8.0
checksum: 6e1e70ce7dc23c69ec2f3443cac5956241db834d745fcec6d613ac323004f9e9c279e68182b9995fb3eca572a0a99600de493bc6b7d8e1dc248203aaeaec2251
checksum: be76b1dd90f8bf8b9f2c53a60f7a56ed6eead6e9a1336879795677fddb75e6fd1d092e6c24af0a7e972b35cfff3eb9056229c5df7a852bfbff9e84e6a8fcb9bc
languageName: node
linkType: hard
@ -1244,9 +1235,9 @@ __metadata:
version: 0.0.0-use.local
resolution: "@hyperlane-xyz/hyperlane-token@workspace:."
dependencies:
"@hyperlane-xyz/core": 1.1.4
"@hyperlane-xyz/sdk": 1.1.4
"@hyperlane-xyz/utils": 1.1.4
"@hyperlane-xyz/core": 1.2.0
"@hyperlane-xyz/sdk": 1.2.0
"@hyperlane-xyz/utils": 1.2.0
"@nomiclabs/hardhat-ethers": ^2.2.1
"@nomiclabs/hardhat-waffle": ^2.0.3
"@openzeppelin/contracts-upgradeable": ^4.8.0
@ -1274,28 +1265,27 @@ __metadata:
languageName: unknown
linkType: soft
"@hyperlane-xyz/sdk@npm:1.1.4":
version: 1.1.4
resolution: "@hyperlane-xyz/sdk@npm:1.1.4"
"@hyperlane-xyz/sdk@npm:1.2.0":
version: 1.2.0
resolution: "@hyperlane-xyz/sdk@npm:1.2.0"
dependencies:
"@hyperlane-xyz/celo-ethers-provider": ^0.1.1
"@hyperlane-xyz/core": 1.1.4
"@hyperlane-xyz/utils": 1.1.4
"@hyperlane-xyz/core": 1.2.0
"@hyperlane-xyz/utils": 1.2.0
"@wagmi/chains": ^0.2.6
coingecko-api: ^1.0.10
cross-fetch: ^3.1.5
debug: ^4.3.4
ethers: ^5.7.2
checksum: 600d81648cdbdad2be4200bd772d49128b9bcd5de10d1f811008291ed268610a0bb1cac8061dfa30b5040dc20c7b8919b39ed206d7993f63c65abf3df663c125
checksum: 16d0eeb2f48c656106f4e2fa9101b1ae1382cb04c31571fcc41f167c84bc5d9343d769fd1ce9fd27e7e9b41bc60b3ab4a72742664f129947932e6ef147d6ce72
languageName: node
linkType: hard
"@hyperlane-xyz/utils@npm:1.1.4":
version: 1.1.4
resolution: "@hyperlane-xyz/utils@npm:1.1.4"
"@hyperlane-xyz/utils@npm:1.2.0":
version: 1.2.0
resolution: "@hyperlane-xyz/utils@npm:1.2.0"
dependencies:
ethers: ^5.7.2
checksum: 9860b34cea341e2b49eb341cb2bab57d33b8e818a577f7d50daa3417c7d6dc01311d99cb13e1232d84b0c3551cc4476734e1b9bc0083b4cb1e6c441c3a0f4798
checksum: 320e59e36a9349a8fa57c3bbc85faadbe5b591cd345165e9571511a51a38bcb07dd85026fdaf997db7bcaf1eeae8cc1c12962cf3154c2efcb570cd7df5b9bb7c
languageName: node
linkType: hard

Loading…
Cancel
Save