fix(cli): ezETH deploy fixes (#4009)

### Description

some minor fixes to make the ezEth deploy work. Does not include the
modifications to contract verification retries that I made.

---------

Co-authored-by: Lee <6251863+ltyu@users.noreply.github.com>
pull/4088/head
Nam Chu Hoai 5 months ago committed by GitHub
parent d35b54670d
commit 4cc9327e52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      .changeset/serious-cups-sneeze.md
  2. 2
      typescript/cli/src/consts.ts
  3. 5
      typescript/cli/src/deploy/utils.ts
  4. 2
      typescript/cli/src/deploy/warp.ts
  5. 77
      typescript/cli/src/utils/balances.ts
  6. 16
      typescript/sdk/src/ism/EvmIsmModule.ts
  7. 21
      typescript/sdk/src/token/deploy.ts

@ -0,0 +1,6 @@
---
'@hyperlane-xyz/cli': minor
'@hyperlane-xyz/sdk': minor
---
Update warp deploy to handle xerc20, initializerArgs to be the signer, update deploy gas constants

@ -1,4 +1,4 @@
export const MINIMUM_CORE_DEPLOY_GAS = (1e8).toString();
export const MINIMUM_WARP_DEPLOY_GAS = (1e7).toString();
export const MINIMUM_WARP_DEPLOY_GAS = (6e8).toString(); // Rough calculation through deployments to testnets with 2x buffer
export const MINIMUM_TEST_SEND_GAS = (3e5).toString();
export const MINIMUM_AVS_GAS = (3e6).toString();

@ -21,7 +21,7 @@ import {
logPink,
logTable,
} from '../logger.js';
import { gasBalancesAreSufficient } from '../utils/balances.js';
import { nativeBalancesAreSufficient } from '../utils/balances.js';
import { ENV } from '../utils/env.js';
import { assertSigner } from '../utils/keys.js';
@ -55,13 +55,12 @@ export async function runPreflightChecksForChains({
assertSigner(signer);
logGreen('✅ Signer is valid');
const sufficient = await gasBalancesAreSufficient(
await nativeBalancesAreSufficient(
multiProvider,
signer,
chainsToGasCheck ?? chains,
minGas,
);
if (sufficient) logGreen('✅ Balances are sufficient');
}
export async function runDeployPlanStep({

@ -110,7 +110,7 @@ async function runDeployPlanStep({ context, configMap }: DeployParams) {
log(`Using token standard ${configMap.isNft ? 'ERC721' : 'ERC20'}`);
logTable(configMap);
if (skipConfirmation) return;
if (skipConfirmation || context.isDryRun) return;
const isConfirmed = await confirm({
message: 'Is this deployment plan correct?',

@ -3,55 +3,44 @@ import { ethers } from 'ethers';
import { ChainName, MultiProvider } from '@hyperlane-xyz/sdk';
import { logGreen, logRed } from '../logger.js';
export async function nativeBalancesAreSufficient(
multiProvider: MultiProvider,
signer: ethers.Signer,
chains: ChainName[],
minBalanceWei: string,
): Promise<boolean> {
minGas: string,
) {
const address = await signer.getAddress();
const minBalance = ethers.utils.formatEther(minBalanceWei.toString());
let sufficient = true;
await Promise.all(
chains.map(async (chain) => {
const balanceWei = await multiProvider
.getProvider(chain)
.getBalance(address);
const balance = ethers.utils.formatEther(balanceWei);
if (balanceWei.lt(minBalanceWei)) {
const symbol =
multiProvider.getChainMetadata(chain).nativeToken?.symbol ?? 'ETH';
const error = `${address} has low balance on ${chain}. At least ${minBalance} recommended but found ${balance.toString()} ${symbol}`;
const isResume = await confirm({
message: `WARNING: ${error} Continue?`,
});
if (!isResume) throw new Error(error);
sufficient = false;
}
}),
);
return sufficient;
}
export async function gasBalancesAreSufficient(
multiProvider: MultiProvider,
signer: ethers.Signer,
chains: ChainName[],
minGas: string,
): Promise<boolean> {
let sufficient = true;
await Promise.all(
chains.map(async (chain) => {
const provider = multiProvider.getProvider(chain);
const gasPrice = await provider.getGasPrice();
const minBalanceWei = gasPrice.mul(minGas).toString();
sufficient = await nativeBalancesAreSufficient(
multiProvider,
signer,
[chain],
minBalanceWei,
const sufficientBalances: boolean[] = [];
for (const chain of chains) {
const provider = multiProvider.getProvider(chain);
const gasPrice = await provider.getGasPrice();
const minBalanceWei = gasPrice.mul(minGas).toString();
const minBalance = ethers.utils.formatEther(minBalanceWei.toString());
const balanceWei = await multiProvider
.getProvider(chain)
.getBalance(address);
const balance = ethers.utils.formatEther(balanceWei.toString());
if (balanceWei.lt(minBalanceWei)) {
const symbol =
multiProvider.getChainMetadata(chain).nativeToken?.symbol ?? 'ETH';
logRed(
`WARNING: ${address} has low balance on ${chain}. At least ${minBalance} recommended but found ${balance} ${symbol}`,
);
}),
);
return sufficient;
sufficientBalances.push(false);
}
}
const allSufficient = sufficientBalances.every((sufficient) => sufficient);
if (allSufficient) {
logGreen('✅ Balances are sufficient');
} else {
const isResume = await confirm({
message: 'Deployment may fail due to insufficient balance(s). Continue?',
});
if (!isResume) throw new Error('Canceled deployment due to low balance');
}
}

@ -466,14 +466,14 @@ export class EvmIsmModule extends HyperlaneModule<
config.domains = availableDomains;
// deploy the submodules first
const submoduleAddresses: Address[] = await Promise.all(
Object.keys(config.domains).map(async (origin) => {
const { address } = await this.deploy({
config: config.domains[origin],
});
return address;
}),
);
const submoduleAddresses: Address[] = [];
for (const origin of Object.keys(config.domains)) {
const { address } = await this.deploy({
config: config.domains[origin],
});
submoduleAddresses.push(address);
}
if (config.type === IsmType.FALLBACK_ROUTING) {
// deploy the fallback routing ISM

@ -5,7 +5,9 @@ import {
ERC20__factory,
ERC721Enumerable__factory,
GasRouter,
IXERC20Lockbox__factory,
} from '@hyperlane-xyz/core';
import { TokenType } from '@hyperlane-xyz/sdk';
import { assert, objKeys, objMap, rootLogger } from '@hyperlane-xyz/utils';
import { HyperlaneContracts } from '../contracts/types.js';
@ -64,11 +66,16 @@ abstract class TokenDeployer<
}
}
async initializeArgs(_: ChainName, config: TokenRouterConfig): Promise<any> {
async initializeArgs(
chain: ChainName,
config: TokenRouterConfig,
): Promise<any> {
const signer = await this.multiProvider.getSigner(chain).getAddress();
const defaultArgs = [
config.hook ?? constants.AddressZero,
config.interchainSecurityModule ?? constants.AddressZero,
config.owner,
// TransferOwnership will happen later in RouterDeployer
signer,
];
if (isCollateralConfig(config) || isNativeConfig(config)) {
return defaultArgs;
@ -117,7 +124,15 @@ abstract class TokenDeployer<
};
}
const erc20 = ERC20__factory.connect(config.token, provider);
const token =
config.type === TokenType.XERC20Lockbox
? await IXERC20Lockbox__factory.connect(
config.token,
provider,
).callStatic.ERC20()
: config.token;
const erc20 = ERC20__factory.connect(token, provider);
const [name, symbol, decimals] = await Promise.all([
erc20.name(),
erc20.symbol(),

Loading…
Cancel
Save