feat: add weETHs warp route, some drive-by cleanup (#4826)

### Description

- Deploys weETHs between Ethereum and Eclipsemainnet
- Removes all the warp route generation scripts in favor of a single one
- Renames some things throughout infra to be closer to the canonical
warp IDs (e.g. add all chain names, sort them, etc)
- Removes a bunch of now unnecessary ts-ignores
- Moves toward using router configs for non-EVM chains in the warp
configs

Waiting to merge
https://github.com/hyperlane-xyz/hyperlane-registry/pull/362 before
updating the registryrc in here so the warp config checker works

### Drive-by changes

<!--
Are there any minor or drive-by changes also included?
-->

### Related issues

<!--
- Fixes #[issue number here]
-->

### Backward compatibility

<!--
Are these changes backward compatible? Are there any infrastructure
implications, e.g. changes that would prohibit deploying older commits
using this infra tooling?

Yes/No
-->

### Testing

<!--
What kind of testing have these changes undergone?

None/Manual/Unit Tests
-->
pull/4834/head
Trevor Porter 2 weeks ago committed by GitHub
parent f0e8f74087
commit e6f9d5c4fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      .changeset/shy-taxis-suffer.md
  2. 22
      rust/sealevel/client/src/warp_route.rs
  3. 10
      rust/sealevel/environments/mainnet3/warp-routes/weETHs-eclipsemainnet-ethereum/program-ids.json
  4. 17
      rust/sealevel/environments/mainnet3/warp-routes/weETHs-eclipsemainnet-ethereum/token-config.json
  5. 4
      typescript/infra/config/environments/mainnet3/agent.ts
  6. 2
      typescript/infra/config/environments/mainnet3/funding.ts
  7. 4
      typescript/infra/config/environments/mainnet3/index.ts
  8. 27
      typescript/infra/config/environments/mainnet3/owners.ts
  9. 8
      typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseEthereumSolanaUSDCWarpConfig.ts
  10. 12
      typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseEthereumSolanaUSDTWarpConfig.ts
  11. 4
      typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseEthereumTETHWarpConfig.ts
  12. 9
      typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseEthereumWBTCWarpConfig.ts
  13. 36
      typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseEthereumWeETHsWarpConfig.ts
  14. 7
      typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseStrideSTTIAWarpConfig.ts
  15. 8
      typescript/infra/config/environments/mainnet3/warp/configGetters/getEclipseStrideTIAWarpConfig.ts
  16. 5
      typescript/infra/config/environments/mainnet3/warp/warpIds.ts
  17. 18
      typescript/infra/config/warp.ts
  18. 4
      typescript/infra/scripts/agent-utils.ts
  19. 35
      typescript/infra/scripts/funding/fund-keys-from-deployer.ts
  20. 26
      typescript/infra/scripts/generate-eclipse-usdt-warp-route-config.ts
  21. 26
      typescript/infra/scripts/generate-eclipse-wbtc-warp-route-config.ts
  22. 23
      typescript/infra/scripts/generate-renzo-ezeth-warp-route-config.ts
  23. 23
      typescript/infra/scripts/generate-renzo-pzeth-warp-route-config.ts
  24. 37
      typescript/infra/scripts/warp-routes/generate-warp-config.ts
  25. 31
      typescript/infra/src/config/environment.ts
  26. 1
      typescript/infra/src/config/warp.ts
  27. 1
      typescript/utils/src/index.ts
  28. 13
      typescript/utils/src/objects.test.ts
  29. 8
      typescript/utils/src/objects.ts

@ -0,0 +1,5 @@
---
'@hyperlane-xyz/utils': patch
---
Added a mustGet helper

@ -192,19 +192,25 @@ impl RouterDeployer<TokenConfig> for WarpRouteDeployer {
app_config: &TokenConfig, app_config: &TokenConfig,
program_id: Pubkey, program_id: Pubkey,
) { ) {
if let Some(ata_payer_funding_amount) = self.ata_payer_funding_amount { let try_fund_ata_payer = |ctx: &mut Context, client: &RpcClient| {
if matches!( if let Some(ata_payer_funding_amount) = self.ata_payer_funding_amount {
app_config.token_type, if matches!(
TokenType::Collateral(_) | TokenType::Synthetic(_) app_config.token_type,
) { TokenType::Collateral(_) | TokenType::Synthetic(_)
fund_ata_payer_up_to(ctx, client, program_id, ata_payer_funding_amount); ) {
fund_ata_payer_up_to(ctx, client, program_id, ata_payer_funding_amount);
}
} }
} };
let (token_pda, _token_bump) = let (token_pda, _token_bump) =
Pubkey::find_program_address(hyperlane_token_pda_seeds!(), &program_id); Pubkey::find_program_address(hyperlane_token_pda_seeds!(), &program_id);
if account_exists(client, &token_pda).unwrap() { if account_exists(client, &token_pda).unwrap() {
println!("Warp route token already exists, skipping init"); println!("Warp route token already exists, skipping init");
// Fund the ATA payer up to the specified amount.
try_fund_ata_payer(ctx, client);
return; return;
} }
@ -398,6 +404,8 @@ impl RouterDeployer<TokenConfig> for WarpRouteDeployer {
println!("Set the {authority} authority to the mint account. Status: {status}"); println!("Set the {authority} authority to the mint account. Status: {status}");
} }
} }
try_fund_ata_payer(ctx, client);
} }
/// Sets gas router configs on all deployable chains. /// Sets gas router configs on all deployable chains.

@ -0,0 +1,10 @@
{
"eclipsemainnet": {
"hex": "0x6196f9127d2caa0f4265d0870d077e6bf979c585b87cceb7537fc6d2c81729b7",
"base58": "7Zx4wU1QAw98MfvnPFqRh1oyumek7G5VAX6TKB3U1tcn"
},
"ethereum": {
"hex": "0x000000000000000000000000ef899e92da472e014be795ecce948308958e25a2",
"base58": "1111111111114LZDAaWurQERWF32Wqjijy9NWQRX"
}
}

@ -0,0 +1,17 @@
{
"eclipsemainnet": {
"type": "synthetic",
"decimals": 9,
"remoteDecimals": 18,
"name": "Super Symbiotic LRT",
"symbol": "weETHs",
"uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/6ce62e9330ae1af0786f60d9fe6da8541b6b2988/deployments/warp_routes/weETHs/metadata.json",
"interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj"
},
"ethereum": {
"type": "collateral",
"decimals": 18,
"token": "0x917cee801a67f933f2e6b33fc0cd1ed2d5909d88",
"foreignDeployment": "0xef899e92DA472E014bE795Ecce948308958E25A2"
}
}

@ -402,13 +402,13 @@ const metricAppContexts = [
{ {
name: 'eclipse_usdc', name: 'eclipse_usdc',
matchingList: matchingList( matchingList: matchingList(
getWarpAddresses(WarpRouteIds.EthereumEclipseUSDC), getWarpAddresses(WarpRouteIds.EclipseEthereumSolanaUSDC),
), ),
}, },
{ {
name: 'eclipse_teth', name: 'eclipse_teth',
matchingList: matchingList( matchingList: matchingList(
getWarpAddresses(WarpRouteIds.EthereumEclipseTETH), getWarpAddresses(WarpRouteIds.EclipseEthereumTETH),
), ),
}, },
{ {

@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig<
> = { > = {
docker: { docker: {
repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo', repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo',
tag: 'b1366fa-20241101-173610', tag: '1b067fe-20241106-190859',
}, },
// We're currently using the same deployer/key funder key as mainnet2. // We're currently using the same deployer/key funder key as mainnet2.
// To minimize nonce clobbering we offset the key funder cron // To minimize nonce clobbering we offset the key funder cron

@ -17,7 +17,7 @@ import { helloWorld } from './helloworld.js';
import { igp } from './igp.js'; import { igp } from './igp.js';
import { infrastructure } from './infrastructure.js'; import { infrastructure } from './infrastructure.js';
import { bridgeAdapterConfigs, relayerConfig } from './liquidityLayer.js'; import { bridgeAdapterConfigs, relayerConfig } from './liquidityLayer.js';
import { ethereumChainOwners } from './owners.js'; import { chainOwners } from './owners.js';
import { supportedChainNames } from './supportedChainNames.js'; import { supportedChainNames } from './supportedChainNames.js';
import { checkWarpDeployConfig } from './warp/checkWarpDeploy.js'; import { checkWarpDeployConfig } from './warp/checkWarpDeploy.js';
@ -48,7 +48,7 @@ export const environment: EnvironmentConfig = {
agents, agents,
core, core,
igp, igp,
owners: ethereumChainOwners, owners: chainOwners,
infra: infrastructure, infra: infrastructure,
helloWorld, helloWorld,
keyFunderConfig, keyFunderConfig,

@ -179,3 +179,30 @@ export const ethereumChainOwners: ChainMap<OwnableConfig> = Object.fromEntries(
]; ];
}), }),
); );
export const chainOwners: ChainMap<OwnableConfig> = {
...ethereumChainOwners,
solanamainnet: {
// Squads multisig
owner: 'BNGDJ1h9brgt6FFVd8No1TVAH48Fp44d7jkuydr1URwJ',
},
eclipsemainnet: {
owner: 'B32qTbw8iDcVdagMAMBfDFCef88N1KtfRG5QoPVzbj5K',
},
injective: {
// Native multisig
owner: 'inj1ac6qpt57vhtfzdecd2an052elwgenwtxcn9chl',
},
neutron: {
// Da0Da0 multisig
owner: 'neutron1fqf5mprg3f5hytvzp3t7spmsum6rjrw80mq8zgkc0h6rxga0dtzqws3uu7',
},
// We intentionally cause issues if these were to be used, but satisfy the types
// and ensure there's an entry for each supported chain.
stride: {
owner: 'n/a - nothing owned here',
},
osmosis: {
owner: 'n/a - nothing owned here',
},
};

@ -8,13 +8,12 @@ import {
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { tokens } from '../../../../../src/config/warp.js'; import { tokens } from '../../../../../src/config/warp.js';
import { DEPLOYER } from '../../owners.js';
export const getEthereumEclipseUSDCWarpConfig = async ( export const getEclipseEthereumSolanaUSDCWarpConfig = async (
routerConfig: ChainMap<RouterConfig>, routerConfig: ChainMap<RouterConfig>,
): Promise<ChainMap<TokenRouterConfig>> => { ): Promise<ChainMap<TokenRouterConfig>> => {
// @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig
const eclipsemainnet: TokenRouterConfig = { const eclipsemainnet: TokenRouterConfig = {
...routerConfig.eclipsemainnet,
type: TokenType.synthetic, type: TokenType.synthetic,
foreignDeployment: 'D6k6T3G74ij6atCtBiWBs5TbFa1hFVcrFUSGZHuV7q3Z', foreignDeployment: 'D6k6T3G74ij6atCtBiWBs5TbFa1hFVcrFUSGZHuV7q3Z',
gas: 300_000, gas: 300_000,
@ -27,6 +26,9 @@ export const getEthereumEclipseUSDCWarpConfig = async (
token: tokens.ethereum.USDC, token: tokens.ethereum.USDC,
}; };
// Intentionally don't enroll Solana to avoid transferring
// directly between Solana and Ethereum
return { return {
eclipsemainnet, eclipsemainnet,
ethereum, ethereum,

@ -8,20 +8,15 @@ import {
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { tokens } from '../../../../../src/config/warp.js'; import { tokens } from '../../../../../src/config/warp.js';
import { getRegistry as getMainnet3Registry } from '../../chains.js';
export const getEclipseEthereumUSDTWarpConfig = async ( export const getEclipseEthereumSolanaUSDTWarpConfig = async (
routerConfig: ChainMap<RouterConfig>, routerConfig: ChainMap<RouterConfig>,
): Promise<ChainMap<TokenRouterConfig>> => { ): Promise<ChainMap<TokenRouterConfig>> => {
const registry = await getMainnet3Registry();
// @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig
const eclipsemainnet: TokenRouterConfig = { const eclipsemainnet: TokenRouterConfig = {
...routerConfig.eclipsemainnet,
type: TokenType.synthetic, type: TokenType.synthetic,
foreignDeployment: '5g5ujyYUNvdydwyDVCpZwPpgYRqH5RYJRi156cxyE3me', foreignDeployment: '5g5ujyYUNvdydwyDVCpZwPpgYRqH5RYJRi156cxyE3me',
gas: 300_000, gas: 300_000,
mailbox: (await registry.getChainAddresses('eclipsemainnet'))!.mailbox,
owner: '9bRSUPjfS3xS6n5EfkJzHFTRDa4AHLda8BU2pP4HoWnf',
interchainSecurityModule: ethers.constants.AddressZero, interchainSecurityModule: ethers.constants.AddressZero,
}; };
let ethereum: TokenRouterConfig = { let ethereum: TokenRouterConfig = {
@ -31,6 +26,9 @@ export const getEclipseEthereumUSDTWarpConfig = async (
interchainSecurityModule: ethers.constants.AddressZero, interchainSecurityModule: ethers.constants.AddressZero,
}; };
// Intentionally don't enroll Solana to avoid transferring
// directly between Solana and Ethereum
return { return {
eclipsemainnet, eclipsemainnet,
ethereum, ethereum,

@ -7,13 +7,11 @@ import {
TokenType, TokenType,
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { DEPLOYER } from '../../owners.js';
export const getEthereumEclipseTETHWarpConfig = async ( export const getEthereumEclipseTETHWarpConfig = async (
routerConfig: ChainMap<RouterConfig>, routerConfig: ChainMap<RouterConfig>,
): Promise<ChainMap<TokenRouterConfig>> => { ): Promise<ChainMap<TokenRouterConfig>> => {
// @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig
const eclipsemainnet: TokenRouterConfig = { const eclipsemainnet: TokenRouterConfig = {
...routerConfig.eclipsemainnet,
type: TokenType.synthetic, type: TokenType.synthetic,
foreignDeployment: 'BJa3fPvvjKx8gRCWunoSrWBbsmieub37gsGpjp4BfTfW', foreignDeployment: 'BJa3fPvvjKx8gRCWunoSrWBbsmieub37gsGpjp4BfTfW',
gas: 300_000, gas: 300_000,

@ -8,23 +8,18 @@ import {
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { tokens } from '../../../../../src/config/warp.js'; import { tokens } from '../../../../../src/config/warp.js';
import { getRegistry as getMainnet3Registry } from '../../chains.js';
import { DEPLOYER } from '../../owners.js';
export const getEclipseEthereumWBTCWarpConfig = async ( export const getEclipseEthereumWBTCWarpConfig = async (
routerConfig: ChainMap<RouterConfig>, routerConfig: ChainMap<RouterConfig>,
): Promise<ChainMap<TokenRouterConfig>> => { ): Promise<ChainMap<TokenRouterConfig>> => {
const registry = await getMainnet3Registry();
// @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig
const eclipsemainnet: TokenRouterConfig = { const eclipsemainnet: TokenRouterConfig = {
...routerConfig.eclipsemainnet,
type: TokenType.synthetic, type: TokenType.synthetic,
foreignDeployment: 'A7EGCDYFw5R7Jfm6cYtKvY8dmkrYMgwRCJFkyQwpHTYu', foreignDeployment: 'A7EGCDYFw5R7Jfm6cYtKvY8dmkrYMgwRCJFkyQwpHTYu',
gas: 300_000, gas: 300_000,
mailbox: (await registry.getChainAddresses('eclipsemainnet'))!.mailbox,
owner: '9bRSUPjfS3xS6n5EfkJzHFTRDa4AHLda8BU2pP4HoWnf',
interchainSecurityModule: ethers.constants.AddressZero, interchainSecurityModule: ethers.constants.AddressZero,
}; };
let ethereum: TokenRouterConfig = { let ethereum: TokenRouterConfig = {
...routerConfig.ethereum, ...routerConfig.ethereum,
type: TokenType.collateral, type: TokenType.collateral,

@ -0,0 +1,36 @@
import { ethers } from 'ethers';
import {
ChainMap,
RouterConfig,
TokenRouterConfig,
TokenType,
} from '@hyperlane-xyz/sdk';
import { tokens } from '../../../../../src/config/warp.js';
import { DEPLOYER } from '../../owners.js';
export const getEclipseEthereumWeEthsWarpConfig = async (
routerConfig: ChainMap<RouterConfig>,
): Promise<ChainMap<TokenRouterConfig>> => {
const eclipsemainnet: TokenRouterConfig = {
...routerConfig.eclipsemainnet,
type: TokenType.synthetic,
foreignDeployment: '7Zx4wU1QAw98MfvnPFqRh1oyumek7G5VAX6TKB3U1tcn',
gas: 300_000,
interchainSecurityModule: ethers.constants.AddressZero,
};
let ethereum: TokenRouterConfig = {
...routerConfig.ethereum,
type: TokenType.collateral,
token: tokens.ethereum.weETHs,
interchainSecurityModule: ethers.constants.AddressZero,
owner: DEPLOYER,
};
return {
eclipsemainnet,
ethereum,
};
};

@ -6,20 +6,21 @@ import {
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
export const getEclipseStrideTiaWarpConfig = async ( export const getEclipseStrideTiaWarpConfig = async (
_routerConfig: ChainMap<RouterConfig>, routerConfig: ChainMap<RouterConfig>,
): Promise<ChainMap<TokenRouterConfig>> => { ): Promise<ChainMap<TokenRouterConfig>> => {
// @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig
const eclipsemainnet: TokenRouterConfig = { const eclipsemainnet: TokenRouterConfig = {
...routerConfig.eclipsemainnet,
type: TokenType.synthetic, type: TokenType.synthetic,
foreignDeployment: 'BpXHAiktwjx7fN6M9ST9wr6qKAsH27wZFhdHEhReJsR6', foreignDeployment: 'BpXHAiktwjx7fN6M9ST9wr6qKAsH27wZFhdHEhReJsR6',
gas: 300_000, gas: 300_000,
}; };
// @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig
const stride: TokenRouterConfig = { const stride: TokenRouterConfig = {
...routerConfig.stride,
type: TokenType.collateral, type: TokenType.collateral,
foreignDeployment: foreignDeployment:
'stride1pvtesu3ve7qn7ctll2x495mrqf2ysp6fws68grvcu6f7n2ajghgsh2jdj6', 'stride1pvtesu3ve7qn7ctll2x495mrqf2ysp6fws68grvcu6f7n2ajghgsh2jdj6',
token: 'stutia',
}; };
return { return {

@ -6,20 +6,22 @@ import {
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
export const getEclipseStrideStTiaWarpConfig = async ( export const getEclipseStrideStTiaWarpConfig = async (
_routerConfig: ChainMap<RouterConfig>, routerConfig: ChainMap<RouterConfig>,
): Promise<ChainMap<TokenRouterConfig>> => { ): Promise<ChainMap<TokenRouterConfig>> => {
// @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig
const eclipsemainnet: TokenRouterConfig = { const eclipsemainnet: TokenRouterConfig = {
...routerConfig.eclipsemainnet,
type: TokenType.synthetic, type: TokenType.synthetic,
foreignDeployment: 'tKUHyJ5NxhnwU94JUmzh1ekukDcHHX8mZF6fqxbMwX6', foreignDeployment: 'tKUHyJ5NxhnwU94JUmzh1ekukDcHHX8mZF6fqxbMwX6',
gas: 300_000, gas: 300_000,
}; };
// @ts-ignore - foreignDeployment configs don't conform to the TokenRouterConfig
const stride: TokenRouterConfig = { const stride: TokenRouterConfig = {
...routerConfig.stride,
type: TokenType.collateral, type: TokenType.collateral,
foreignDeployment: foreignDeployment:
'stride134axwdlam929m3mar3wv95nvkyep7mr87ravkqcpf8dfe3v0pjlqwrw6ee', 'stride134axwdlam929m3mar3wv95nvkyep7mr87ravkqcpf8dfe3v0pjlqwrw6ee',
token:
'ibc/BF3B4F53F3694B66E13C23107C84B6485BD2B96296BB7EC680EA77BBA75B4801',
}; };
return { return {

@ -4,16 +4,17 @@ export enum WarpRouteIds {
ArbitrumEthereumZircuitAMPHRETH = 'AMPHRETH/arbitrum-ethereum-zircuit', ArbitrumEthereumZircuitAMPHRETH = 'AMPHRETH/arbitrum-ethereum-zircuit',
ArbitrumNeutronEclip = 'ECLIP/arbitrum-neutron', ArbitrumNeutronEclip = 'ECLIP/arbitrum-neutron',
ArbitrumNeutronTIA = 'TIA/arbitrum-neutron', ArbitrumNeutronTIA = 'TIA/arbitrum-neutron',
EclipseEthereumSolanaUSDC = 'USDC/eclipsemainnet-ethereum-solanamainnet',
EclipseEthereumSolanaUSDT = 'USDT/eclipsemainnet-ethereum-solanamainnet', EclipseEthereumSolanaUSDT = 'USDT/eclipsemainnet-ethereum-solanamainnet',
EclipseEthereumTETH = 'tETH/eclipsemainnet-ethereum',
EclipseEthereumWBTC = 'WBTC/eclipsemainnet-ethereum', EclipseEthereumWBTC = 'WBTC/eclipsemainnet-ethereum',
EclipseEthereumWeETHs = 'weETHs/eclipsemainnet-ethereum',
EclipseSolanaSOL = 'SOL/eclipsemainnet-solanamainnet', EclipseSolanaSOL = 'SOL/eclipsemainnet-solanamainnet',
EclipseSolanaWIF = 'WIF/eclipsemainnet-solanamainnet', EclipseSolanaWIF = 'WIF/eclipsemainnet-solanamainnet',
EclipseStrideSTTIA = 'stTIA/eclipse-stride', EclipseStrideSTTIA = 'stTIA/eclipse-stride',
EclipseStrideTIA = 'TIA/eclipse-stride', EclipseStrideTIA = 'TIA/eclipse-stride',
EthereumInevmUSDC = 'USDC/ethereum-inevm', EthereumInevmUSDC = 'USDC/ethereum-inevm',
EthereumInevmUSDT = 'USDT/ethereum-inevm', EthereumInevmUSDT = 'USDT/ethereum-inevm',
EthereumEclipseTETH = 'tETH/eclipsemainnet-ethereum',
EthereumEclipseUSDC = 'USDC/eclipsemainnet-ethereum-solanamainnet',
EthereumSeiFastUSD = 'FASTUSD/ethereum-sei', EthereumSeiFastUSD = 'FASTUSD/ethereum-sei',
EthereumVictionETH = 'ETH/ethereum-viction', EthereumVictionETH = 'ETH/ethereum-viction',
EthereumVictionUSDC = 'USDC/ethereum-viction', EthereumVictionUSDC = 'USDC/ethereum-viction',

@ -6,14 +6,18 @@ import {
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { getHyperlaneCore } from '../scripts/core-utils.js'; import { getHyperlaneCore } from '../scripts/core-utils.js';
import { EnvironmentConfig } from '../src/config/environment.js'; import {
EnvironmentConfig,
getRouterConfigsForAllVms,
} from '../src/config/environment.js';
import { getAncient8EthereumUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getAncient8EthereumUSDCWarpConfig.js'; import { getAncient8EthereumUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getAncient8EthereumUSDCWarpConfig.js';
import { getArbitrumEthereumZircuitAmphrETHWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumEthereumZircuitAmphrETHWarpConfig.js'; import { getArbitrumEthereumZircuitAmphrETHWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumEthereumZircuitAmphrETHWarpConfig.js';
import { getArbitrumNeutronEclipWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronEclipWarpConfig.js'; import { getArbitrumNeutronEclipWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronEclipWarpConfig.js';
import { getArbitrumNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronTiaWarpConfig.js'; import { getArbitrumNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronTiaWarpConfig.js';
import { getEclipseEthereumUSDTWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseEthereumUSDTWarpConfig.js'; import { getEclipseEthereumSolanaUSDTWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseEthereumSolanaUSDTWarpConfig.js';
import { getEclipseEthereumWBTCWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseEthereumWBTCWarpConfig.js'; import { getEclipseEthereumWBTCWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseEthereumWBTCWarpConfig.js';
import { getEclipseEthereumWeEthsWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseEthereumWeETHsWarpConfig.js';
import { getEclipseStrideTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseStrideSTTIAWarpConfig.js'; import { getEclipseStrideTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseStrideSTTIAWarpConfig.js';
import { getEclipseStrideStTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseStrideTIAWarpConfig.js'; import { getEclipseStrideStTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getEclipseStrideTIAWarpConfig.js';
import { getEthereumBscLUMIAWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumBscLumiaLUMIAWarpConfig.js'; import { getEthereumBscLUMIAWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumBscLumiaLUMIAWarpConfig.js';
@ -58,8 +62,10 @@ export const warpConfigGetterMap: Record<
[WarpRouteIds.MantapacificNeutronTIA]: getMantapacificNeutronTiaWarpConfig, [WarpRouteIds.MantapacificNeutronTIA]: getMantapacificNeutronTiaWarpConfig,
[WarpRouteIds.EclipseStrideTIA]: getEclipseStrideTiaWarpConfig, [WarpRouteIds.EclipseStrideTIA]: getEclipseStrideTiaWarpConfig,
[WarpRouteIds.EclipseStrideSTTIA]: getEclipseStrideStTiaWarpConfig, [WarpRouteIds.EclipseStrideSTTIA]: getEclipseStrideStTiaWarpConfig,
[WarpRouteIds.EclipseEthereumSolanaUSDT]: getEclipseEthereumUSDTWarpConfig, [WarpRouteIds.EclipseEthereumSolanaUSDT]:
getEclipseEthereumSolanaUSDTWarpConfig,
[WarpRouteIds.EclipseEthereumWBTC]: getEclipseEthereumWBTCWarpConfig, [WarpRouteIds.EclipseEthereumWBTC]: getEclipseEthereumWBTCWarpConfig,
[WarpRouteIds.EclipseEthereumWeETHs]: getEclipseEthereumWeEthsWarpConfig,
}; };
export async function getWarpConfig( export async function getWarpConfig(
@ -67,8 +73,10 @@ export async function getWarpConfig(
envConfig: EnvironmentConfig, envConfig: EnvironmentConfig,
warpRouteId: string, warpRouteId: string,
): Promise<ChainMap<TokenRouterConfig>> { ): Promise<ChainMap<TokenRouterConfig>> {
const { core } = await getHyperlaneCore(envConfig.environment, multiProvider); const routerConfig = await getRouterConfigsForAllVms(
const routerConfig = core.getRouterConfig(envConfig.owners); envConfig,
multiProvider,
);
const warpConfigGetter = warpConfigGetterMap[warpRouteId]; const warpConfigGetter = warpConfigGetterMap[warpRouteId];
if (!warpConfigGetter) { if (!warpConfigGetter) {

@ -177,6 +177,10 @@ export function withWarpRouteId<T>(args: Argv<T>) {
return args.describe('warpRouteId', 'warp route id').string('warpRouteId'); return args.describe('warpRouteId', 'warp route id').string('warpRouteId');
} }
export function withWarpRouteIdRequired<T>(args: Argv<T>) {
return withWarpRouteId(args).demandOption('warpRouteId');
}
export function withProtocol<T>(args: Argv<T>) { export function withProtocol<T>(args: Argv<T>) {
return args return args
.describe('protocol', 'protocol type') .describe('protocol', 'protocol type')

@ -172,9 +172,32 @@ const sealevelAccountsToTrack: ChainMap<SealevelAccount[]> = {
pubkey: new PublicKey('BH9VfgYaCWbwuupzsTfSy67yR4dwuCbXmFRrm6aAH2NQ'), pubkey: new PublicKey('BH9VfgYaCWbwuupzsTfSy67yR4dwuCbXmFRrm6aAH2NQ'),
walletName: 'WBTC/eclipsemainnet-ethereum/ata-payer', walletName: 'WBTC/eclipsemainnet-ethereum/ata-payer',
}, },
// weETHs warp route ATA payer
{
pubkey: new PublicKey('F4Y6kHrq9qVnmkQhQibxh8nCU2quw5y25z7u8jSHMvtq'),
walletName: 'weETHs/eclipsemainnet-ethereum/ata-payer',
},
], ],
}; };
// Kludge, ignore chains that are technically supportedChainNames
// because we want to continue to run agents, but we don't want to
// try to fund them because we no longer have an available IGP address
// to claim from.
// This was easier to do than modifying the funding config due to the types there.
// We can remove this once they're removed from supportedChainNames.
const chainsToIgnore = [
'alephzeroevm',
'chiliz',
'flow',
'immutablezkevm',
'metall2',
'polynomial',
'rari',
'rootstock',
'superposition',
];
// Funds key addresses for multiple contexts from the deployer key of the context // Funds key addresses for multiple contexts from the deployer key of the context
// specified via the `--context` flag. // specified via the `--context` flag.
// The --contexts-and-roles flag is used to specify the contexts and the key roles // The --contexts-and-roles flag is used to specify the contexts and the key roles
@ -332,7 +355,12 @@ class ContextFunder {
); );
this.igp = HyperlaneIgp.fromAddressesMap( this.igp = HyperlaneIgp.fromAddressesMap(
getEnvAddresses(this.environment), {
...getEnvAddresses(this.environment),
lumia: {
interchainGasPaymaster: '0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E',
},
},
multiProvider, multiProvider,
); );
this.keysToFundPerChain = objMap(roleKeysPerChain, (_chain, roleKeys) => { this.keysToFundPerChain = objMap(roleKeysPerChain, (_chain, roleKeys) => {
@ -503,6 +531,11 @@ class ContextFunder {
const chainKeyEntries = Object.entries(this.keysToFundPerChain); const chainKeyEntries = Object.entries(this.keysToFundPerChain);
const promises = chainKeyEntries.map(async ([chain, keys]) => { const promises = chainKeyEntries.map(async ([chain, keys]) => {
let failureOccurred = false; let failureOccurred = false;
if (chainsToIgnore.includes(chain)) {
logger.warn({ chain }, 'Ignoring chain');
return failureOccurred;
}
if (keys.length > 0) { if (keys.length > 0) {
if (!this.skipIgpClaim) { if (!this.skipIgpClaim) {
failureOccurred ||= await gracefullyHandleError( failureOccurred ||= await gracefullyHandleError(

@ -1,26 +0,0 @@
import { writeFileSync } from 'fs';
import { stringify as yamlStringify } from 'yaml';
import { WarpRouteDeployConfigSchema } from '@hyperlane-xyz/sdk';
import { getEclipseEthereumUSDTWarpConfig } from '../config/environments/mainnet3/warp/configGetters/getEclipseEthereumUSDTWarpConfig.js';
import { getRouterConfig } from './warp-routes/utils.js';
async function main() {
const routerConfig = await getRouterConfig();
const tokenConfig = await getEclipseEthereumUSDTWarpConfig(routerConfig);
const parsed = WarpRouteDeployConfigSchema.safeParse(tokenConfig);
if (!parsed.success) {
console.dir(parsed.error.format(), { depth: null });
return;
}
writeFileSync(
'eclipse-usdt-warp-route-config.yaml',
yamlStringify(parsed.data, null, 2),
);
}
main().catch(console.error).then(console.log);

@ -1,26 +0,0 @@
import { writeFileSync } from 'fs';
import { stringify as yamlStringify } from 'yaml';
import { WarpRouteDeployConfigSchema } from '@hyperlane-xyz/sdk';
import { getEclipseEthereumWBTCWarpConfig } from '../config/environments/mainnet3/warp/configGetters/getEclipseEthereumWBTCWarpConfig.js';
import { getRouterConfig } from './warp-routes/utils.js';
async function main() {
const routerConfig = await getRouterConfig();
const tokenConfig = await getEclipseEthereumWBTCWarpConfig(routerConfig);
const parsed = WarpRouteDeployConfigSchema.safeParse(tokenConfig);
if (!parsed.success) {
console.dir(parsed.error.format(), { depth: null });
return;
}
writeFileSync(
'eclipse-wbtc-warp-route-config.yaml',
yamlStringify(parsed.data, null, 2),
);
}
main().catch(console.error).then(console.log);

@ -1,23 +0,0 @@
import { writeFileSync } from 'fs';
import { stringify as yamlStringify } from 'yaml';
import { WarpRouteDeployConfigSchema } from '@hyperlane-xyz/sdk';
import { getRenzoEZETHWarpConfig } from '../config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.js';
async function main() {
const tokenConfig = await getRenzoEZETHWarpConfig();
const parsed = WarpRouteDeployConfigSchema.safeParse(tokenConfig);
if (!parsed.success) {
console.dir(parsed.error.format(), { depth: null });
return;
}
writeFileSync(
'renzo-ezeth-warp-route-config.yaml',
yamlStringify(parsed.data, null, 2),
);
}
main().catch(console.error).then(console.log);

@ -1,23 +0,0 @@
import { writeFileSync } from 'fs';
import { stringify as yamlStringify } from 'yaml';
import { WarpRouteDeployConfigSchema } from '@hyperlane-xyz/sdk';
import { getRenzoPZETHWarpConfig } from '../config/environments/mainnet3/warp/configGetters/getRenzoPZETHWarpConfig.js';
async function main() {
const tokenConfig = await getRenzoPZETHWarpConfig();
const parsed = WarpRouteDeployConfigSchema.safeParse(tokenConfig);
if (!parsed.success) {
console.dir(parsed.error.format(), { depth: null });
return;
}
writeFileSync(
'renzo-pzeth-warp-route-config.yaml',
yamlStringify(parsed.data, null, 2),
);
}
main().catch(console.error).then(console.log);

@ -0,0 +1,37 @@
import { stringify as yamlStringify } from 'yaml';
import { WarpRouteDeployConfigSchema } from '@hyperlane-xyz/sdk';
import { getWarpConfig } from '../../config/warp.js';
import { writeYamlAtPath } from '../../src/utils/utils.js';
import { getArgs, withWarpRouteIdRequired } from '../agent-utils.js';
import { getEnvironmentConfig, getHyperlaneCore } from '../core-utils.js';
async function main() {
const { warpRouteId, environment, outFile } = await withWarpRouteIdRequired(
getArgs(),
)
.string('outFile')
.describe('outFile', 'The file to write the config to').argv;
const { multiProvider } = await getHyperlaneCore(environment);
const envConfig = getEnvironmentConfig(environment);
const warpConfig = await getWarpConfig(multiProvider, envConfig, warpRouteId);
const parsed = WarpRouteDeployConfigSchema.safeParse(warpConfig);
if (!parsed.success) {
console.dir(parsed.error.format(), { depth: null });
return;
}
console.log('Warp config:');
console.log(yamlStringify(parsed.data, null, 2));
if (outFile) {
console.log(`Writing config to ${outFile}`);
writeYamlAtPath(outFile, parsed.data);
}
}
main().catch(console.error).then(console.log);

@ -8,11 +8,13 @@ import {
MultiProtocolProvider, MultiProtocolProvider,
MultiProvider, MultiProvider,
OwnableConfig, OwnableConfig,
RouterConfig,
} from '@hyperlane-xyz/sdk'; } from '@hyperlane-xyz/sdk';
import { objKeys } from '@hyperlane-xyz/utils'; import { mustGet, objKeys, objMap, objMerge } from '@hyperlane-xyz/utils';
import { Contexts } from '../../config/contexts.js'; import { Contexts } from '../../config/contexts.js';
import { environments } from '../../config/environments/index.js'; import { environments } from '../../config/environments/index.js';
import { getHyperlaneCore } from '../../scripts/core-utils.js';
import { CloudAgentKey } from '../agents/keys.js'; import { CloudAgentKey } from '../agents/keys.js';
import { Role } from '../roles.js'; import { Role } from '../roles.js';
@ -75,3 +77,30 @@ export function assertEnvironment(env: string): DeployEnvironment {
} }
throw new Error(`Invalid environment ${env}, must be one of ${envNames}`); throw new Error(`Invalid environment ${env}, must be one of ${envNames}`);
} }
// Gets the router configs for all chains in the environment.
// Relying solely on HyperlaneCore.getRouterConfig will result
// in missing any non-EVM chains -- here we merge the two.
export async function getRouterConfigsForAllVms(
envConfig: EnvironmentConfig,
multiProvider: MultiProvider,
): Promise<ChainMap<RouterConfig>> {
const { core, chainAddresses } = await getHyperlaneCore(
envConfig.environment,
multiProvider,
);
const evmRouterConfig = core.getRouterConfig(envConfig.owners);
const allRouterConfigs: ChainMap<RouterConfig> = objMap(
chainAddresses,
(chain, addresses) => {
return {
mailbox: mustGet(addresses, 'mailbox'),
owner: mustGet(envConfig.owners, chain).owner,
};
},
);
// Merge, giving evmRouterConfig precedence
return objMerge(allRouterConfigs, evmRouterConfig);
}

@ -9,6 +9,7 @@ export const tokens: ChainMap<Record<string, Address>> = {
deUSD: '0x15700B564Ca08D9439C58cA5053166E8317aa138', deUSD: '0x15700B564Ca08D9439C58cA5053166E8317aa138',
amphrETH: '0x5fD13359Ba15A84B76f7F87568309040176167cd', amphrETH: '0x5fD13359Ba15A84B76f7F87568309040176167cd',
WBTC: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', WBTC: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599',
weETHs: '0x917cee801a67f933f2e6b33fc0cd1ed2d5909d88',
}, },
sei: { sei: {
fastUSD: '0x37a4dD9CED2b19Cfe8FAC251cd727b5787E45269', fastUSD: '0x37a4dD9CED2b19Cfe8FAC251cd727b5787E45269',

@ -112,6 +112,7 @@ export {
invertKeysAndValues, invertKeysAndValues,
isObjEmpty, isObjEmpty,
isObject, isObject,
mustGet,
objFilter, objFilter,
objKeys, objKeys,
objLength, objLength,

@ -9,6 +9,7 @@ import {
invertKeysAndValues, invertKeysAndValues,
isObjEmpty, isObjEmpty,
isObject, isObject,
mustGet,
objFilter, objFilter,
objKeys, objKeys,
objLength, objLength,
@ -340,4 +341,16 @@ describe('Object utilities', () => {
}); });
}); });
}); });
describe('mustGet', () => {
it('should return the value if it exists', () => {
const obj = { a: 1, b: 2 };
expect(mustGet(obj, 'a')).to.equal(1);
});
it('should throw an error if the value does not exist', () => {
const obj = { a: 1, b: 2 };
expect(() => mustGet(obj, 'c')).to.Throw();
});
});
}); });

@ -319,3 +319,11 @@ export function diffObjMerge(
isInvalid: true, isInvalid: true,
}; };
} }
export function mustGet<T>(obj: Record<string, T>, key: string): T {
const value = obj[key];
if (!value) {
throw new Error(`Missing key ${key} in object ${JSON.stringify(obj)}`);
}
return value;
}

Loading…
Cancel
Save