Merge branch 'main' of github.com:abacus-network/abacus-monorepo into trevor/decimal-consistency-checker

pull/4884/head
Trevor Porter 3 days ago
commit 97571fc3e1
  1. 5
      .changeset/chilly-balloons-rule.md
  2. 5
      .changeset/polite-beds-begin.md
  3. 5
      .changeset/spicy-gifts-hear.md
  4. 5
      .changeset/tough-roses-allow.md
  5. 1
      .codespell/ignore.txt
  6. 4
      .eslintignore
  7. 65
      .eslintrc
  8. 10
      .github/workflows/test.yml
  9. 2
      .registryrc
  10. 3
      .syncpackrc
  11. 115
      eslint.config.mjs
  12. 13
      package.json
  13. 3
      rust/main/agents/relayer/src/relayer.rs
  14. 3
      rust/main/agents/scraper/src/agent.rs
  15. 1
      rust/main/agents/validator/src/validator.rs
  16. 46
      rust/main/chains/hyperlane-sealevel/src/interchain_gas.rs
  17. 89
      rust/main/chains/hyperlane-sealevel/src/mailbox.rs
  18. 398
      rust/main/config/mainnet_config.json
  19. 15
      rust/main/hyperlane-base/src/settings/base.rs
  20. 72
      rust/main/hyperlane-base/src/settings/chains.rs
  21. 21
      rust/sealevel/client/src/cmd_utils.rs
  22. 22
      rust/sealevel/client/src/core.rs
  23. 10
      rust/sealevel/environments/mainnet3/warp-routes/apxETH-eclipse-ethereum/program-ids.json
  24. 17
      rust/sealevel/environments/mainnet3/warp-routes/apxETH-eclipse-ethereum/token-config.json
  25. 10
      rust/sealevel/environments/mainnet3/warp-routes/ezSOL-eclipse-solana/program-ids.json
  26. 17
      rust/sealevel/environments/mainnet3/warp-routes/ezSOL-eclipse-solana/token-config.json
  27. 7
      solidity/CHANGELOG.md
  28. 2
      solidity/contracts/PackageVersioned.sol
  29. 8
      solidity/package.json
  30. 6
      typescript/ccip-server/.eslintrc
  31. 2
      typescript/ccip-server/CHANGELOG.md
  32. 17
      typescript/ccip-server/eslint.config.mjs
  33. 11
      typescript/ccip-server/package.json
  34. 14
      typescript/ccip-server/src/server.ts
  35. 4
      typescript/ccip-server/src/services/LightClientService.ts
  36. 8
      typescript/ccip-server/src/services/ProofsService.ts
  37. 9
      typescript/ccip-server/tsconfig.json
  38. 2
      typescript/cli/.eslintignore
  39. 6
      typescript/cli/.eslintrc
  40. 17
      typescript/cli/CHANGELOG.md
  41. 7
      typescript/cli/cli.ts
  42. 20
      typescript/cli/eslint.config.mjs
  43. 21
      typescript/cli/package.json
  44. 2
      typescript/cli/src/avs/check.ts
  45. 1
      typescript/cli/src/check/warp.ts
  46. 15
      typescript/cli/src/commands/config.ts
  47. 5
      typescript/cli/src/commands/options.ts
  48. 2
      typescript/cli/src/commands/relayer.ts
  49. 21
      typescript/cli/src/commands/signCommands.ts
  50. 70
      typescript/cli/src/commands/strategy.ts
  51. 2
      typescript/cli/src/commands/warp.ts
  52. 2
      typescript/cli/src/config/agent.ts
  53. 6
      typescript/cli/src/config/multisig.ts
  54. 186
      typescript/cli/src/config/strategy.ts
  55. 9
      typescript/cli/src/config/submit.ts
  56. 30
      typescript/cli/src/config/warp.ts
  57. 53
      typescript/cli/src/context/context.ts
  58. 34
      typescript/cli/src/context/strategies/chain/ChainResolverFactory.ts
  59. 200
      typescript/cli/src/context/strategies/chain/MultiChainResolver.ts
  60. 25
      typescript/cli/src/context/strategies/chain/SingleChainResolver.ts
  61. 10
      typescript/cli/src/context/strategies/chain/types.ts
  62. 22
      typescript/cli/src/context/strategies/signer/BaseMultiProtocolSigner.ts
  63. 79
      typescript/cli/src/context/strategies/signer/MultiProtocolSignerFactory.ts
  64. 153
      typescript/cli/src/context/strategies/signer/MultiProtocolSignerManager.ts
  65. 4
      typescript/cli/src/context/types.ts
  66. 1
      typescript/cli/src/deploy/agent.ts
  67. 8
      typescript/cli/src/deploy/core.ts
  68. 3
      typescript/cli/src/deploy/dry-run.ts
  69. 34
      typescript/cli/src/deploy/utils.ts
  70. 36
      typescript/cli/src/deploy/warp.ts
  71. 14
      typescript/cli/src/read/warp.ts
  72. 24
      typescript/cli/src/send/transfer.ts
  73. 2
      typescript/cli/src/status/message.ts
  74. 7
      typescript/cli/src/tests/commands/helpers.ts
  75. 12
      typescript/cli/src/utils/balances.ts
  76. 33
      typescript/cli/src/utils/chains.ts
  77. 2
      typescript/cli/src/utils/env.ts
  78. 6
      typescript/cli/src/utils/files.ts
  79. 50
      typescript/cli/src/utils/input.ts
  80. 47
      typescript/cli/src/utils/output.ts
  81. 35
      typescript/cli/src/utils/warp.ts
  82. 4
      typescript/cli/src/validator/preFlightCheck.ts
  83. 2
      typescript/cli/src/version.ts
  84. 2
      typescript/github-proxy/CHANGELOG.md
  85. 4
      typescript/github-proxy/package.json
  86. 5
      typescript/helloworld/.eslintignore
  87. 39
      typescript/helloworld/.eslintrc
  88. 10
      typescript/helloworld/CHANGELOG.md
  89. 17
      typescript/helloworld/eslint.config.mjs
  90. 21
      typescript/helloworld/package.json
  91. 12
      typescript/infra/CHANGELOG.md
  92. 31
      typescript/infra/config/environments/mainnet3/agent.ts
  93. 18
      typescript/infra/config/environments/mainnet3/aw-validators/hyperlane.json
  94. 13
      typescript/infra/config/environments/mainnet3/core.ts
  95. 420
      typescript/infra/config/environments/mainnet3/core/verification.json
  96. 9
      typescript/infra/config/environments/mainnet3/funding.ts
  97. 64
      typescript/infra/config/environments/mainnet3/gasPrices.json
  98. 516
      typescript/infra/config/environments/mainnet3/ism/verification.json
  99. 126
      typescript/infra/config/environments/mainnet3/middleware/accounts/verification.json
  100. 20
      typescript/infra/config/environments/mainnet3/misc-artifacts/everclear-sender-addresses.json
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,5 @@
---
'@hyperlane-xyz/utils': minor
---
Added `isPrivateKeyEvm` function for validating EVM private keys

@ -0,0 +1,5 @@
---
'@hyperlane-xyz/sdk': minor
---
Introduce GcpValidator for retrieving announcements, checkpoints and metadata for a Validator posting to a GCP bucket. Uses GcpStorageWrapper for bucket operations.

@ -0,0 +1,5 @@
---
'@hyperlane-xyz/cli': minor
---
Added strategy management CLI commands and MultiProtocolSigner implementation for flexible cross-chain signer configuration and management

@ -0,0 +1,5 @@
---
'@hyperlane-xyz/sdk': minor
---
Added a getter to derive ATA payer accounts on Sealevel warp routes

@ -5,3 +5,4 @@ receivedFrom
ser
readded
re-use
superseed

@ -1,4 +0,0 @@
node_modules
dist
coverage
*.cts

@ -1,65 +0,0 @@
{
"env": {
"node": true,
"browser": true,
"es2021": true
},
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint","jest"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"rules": {
"no-console": ["error"],
"no-eval": ["error"],
"no-extra-boolean-cast": ["error"],
"no-ex-assign": ["error"],
"no-constant-condition": ["off"],
"no-return-await": ["error"],
"no-restricted-imports": ["error", {
"name": "console",
"message": "Please use a logger and/or the utils' package assert"
}, {
"name": "fs",
"message": "Avoid use of node-specific libraries"
}],
"guard-for-in": ["error"],
"@typescript-eslint/ban-ts-comment": ["off"],
"@typescript-eslint/explicit-module-boundary-types": ["off"],
"@typescript-eslint/no-explicit-any": ["off"],
"@typescript-eslint/no-floating-promises": ["error"],
"@typescript-eslint/no-non-null-assertion": ["off"],
"@typescript-eslint/no-require-imports": ["warn"],
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_"
}
],
"@typescript-eslint/ban-types": [
"error",
{
"types": {
// Unban the {} type which is a useful shorthand for non-nullish value
"{}": false
},
"extendDefaults": true
}
],
"jest/no-disabled-tests": "warn",
"jest/no-focused-tests": "error",
"jest/no-identical-title": "error",
"jest/prefer-to-have-length": "warn",
"jest/valid-expect": "error"
}
}

@ -54,6 +54,10 @@ jobs:
exit 1
fi
# Check for mismatched dep versions across the monorepo
- name: syncpack
run: yarn syncpack list-mismatches
lint-prettier:
runs-on: ubuntu-latest
needs: [yarn-install]
@ -72,6 +76,12 @@ jobs:
.yarn
key: ${{ runner.os }}-yarn-4.5.1-cache-${{ hashFiles('./yarn.lock') }}
fail-on-cache-miss: true
# Build required before linting or the intra-monorepo package cycle checking won't work
- name: yarn-build
uses: ./.github/actions/yarn-build-with-cache
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: lint
run: yarn lint

@ -1 +1 @@
82013508db45dcd55b44d2721414d26817686c8f
385b83950adba6f033be836b627bab7d89aae38d

@ -0,0 +1,3 @@
{
"dependencyTypes": ["prod", "dev"]
}

@ -0,0 +1,115 @@
import { FlatCompat } from '@eslint/eslintrc';
import js from '@eslint/js';
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import importPlugin from 'eslint-plugin-import';
import jest from 'eslint-plugin-jest';
import globals from 'globals';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
export default [
{
ignores: [
'**/node_modules',
'**/dist',
'**/coverage',
'**/*.cjs',
'**/*.cts',
'**/*.mjs',
'jest.config.js',
],
},
...compat.extends(
'eslint:recommended',
'plugin:import/recommended',
'plugin:import/typescript',
'plugin:@typescript-eslint/recommended',
'prettier',
),
{
plugins: {
import: importPlugin,
'@typescript-eslint': typescriptEslint,
jest,
},
languageOptions: {
globals: {
...globals.node,
...globals.browser,
},
parser: tsParser,
ecmaVersion: 12,
sourceType: 'module',
parserOptions: {
project: './tsconfig.json',
},
},
settings: {
'import/resolver': {
typescript: true,
node: true,
},
},
rules: {
'guard-for-in': ['error'],
'import/no-cycle': ['error'],
'import/no-self-import': ['error'],
'import/no-named-as-default-member': ['off'],
'no-console': ['error'],
'no-eval': ['error'],
'no-extra-boolean-cast': ['error'],
'no-ex-assign': ['error'],
'no-constant-condition': ['off'],
'no-return-await': ['error'],
'no-restricted-imports': [
'error',
{
name: 'console',
message: 'Please use a logger and/or the utils package assert',
},
{
name: 'fs',
message: 'Avoid use of node-specific libraries',
},
],
'@typescript-eslint/ban-ts-comment': ['off'],
'@typescript-eslint/explicit-module-boundary-types': ['off'],
'@typescript-eslint/no-explicit-any': ['off'],
'@typescript-eslint/no-floating-promises': ['error'],
'@typescript-eslint/no-non-null-assertion': ['off'],
'@typescript-eslint/no-require-imports': ['warn'],
'@typescript-eslint/no-unused-expressions': ['off'],
'@typescript-eslint/no-empty-object-type': ['off'],
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],
'jest/no-disabled-tests': 'warn',
'jest/no-focused-tests': 'error',
'jest/no-identical-title': 'error',
'jest/prefer-to-have-length': 'warn',
'jest/valid-expect': 'error',
},
},
];

@ -3,16 +3,20 @@
"description": "A yarn workspace of core Hyperlane packages",
"version": "0.0.0",
"devDependencies": {
"@eslint/js": "^9.15.0",
"@trivago/prettier-plugin-sort-imports": "^4.2.1",
"@typescript-eslint/eslint-plugin": "^7.4.0",
"@typescript-eslint/parser": "^7.4.0",
"eslint": "^8.57.0",
"@typescript-eslint/eslint-plugin": "^8.1.6",
"@typescript-eslint/parser": "^8.1.6",
"eslint": "^9.15.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jest": "^28.2.0",
"husky": "^8.0.0",
"lint-staged": "^12.4.3",
"prettier": "^2.8.8",
"tsx": "^4.7.1"
"syncpack": "^13.0.0",
"tsx": "^4.19.1"
},
"dependencies": {
"@changesets/cli": "^2.26.2"
@ -41,6 +45,7 @@
"async": "^2.6.4",
"fetch-ponyfill": "^7.1",
"flat": "^5.0.2",
"globals": "^14.0.0",
"lodash": "^4.17.21",
"recursive-readdir": "^2.2.3",
"underscore": "^1.13",

@ -152,6 +152,7 @@ impl BaseAgent for Relayer {
dbs.iter()
.map(|(d, db)| (d.clone(), Arc::new(db.clone())))
.collect(),
false,
)
.await?
.into_iter()
@ -166,6 +167,7 @@ impl BaseAgent for Relayer {
dbs.iter()
.map(|(d, db)| (d.clone(), Arc::new(db.clone())))
.collect(),
false,
)
.await?
.into_iter()
@ -180,6 +182,7 @@ impl BaseAgent for Relayer {
dbs.iter()
.map(|(d, db)| (d.clone(), Arc::new(db.clone())))
.collect(),
false,
)
.await?
.into_iter()

@ -198,6 +198,7 @@ impl Scraper {
&metrics.clone(),
&contract_sync_metrics.clone(),
store.into(),
true,
)
.await
.unwrap();
@ -229,6 +230,7 @@ impl Scraper {
&metrics.clone(),
&contract_sync_metrics.clone(),
Arc::new(store.clone()) as _,
true,
)
.await
.unwrap();
@ -261,6 +263,7 @@ impl Scraper {
&metrics.clone(),
&contract_sync_metrics.clone(),
Arc::new(store.clone()),
true,
)
.await
.unwrap();

@ -109,6 +109,7 @@ impl BaseAgent for Validator {
&metrics,
&contract_sync_metrics,
msg_db.clone().into(),
false,
)
.await?;

@ -91,7 +91,8 @@ impl InterchainGasPaymaster for SealevelInterchainGasPaymaster {}
pub struct SealevelInterchainGasPaymasterIndexer {
rpc_client: SealevelRpcClient,
igp: SealevelInterchainGasPaymaster,
_log_meta_composer: LogMetaComposer,
log_meta_composer: LogMetaComposer,
advanced_log_meta: bool,
}
/// IGP payment data on Sealevel
@ -107,6 +108,7 @@ impl SealevelInterchainGasPaymasterIndexer {
pub async fn new(
conf: &ConnectionConf,
igp_account_locator: ContractLocator<'_>,
advanced_log_meta: bool,
) -> ChainResult<Self> {
// Set the `processed` commitment at rpc level
let rpc_client = SealevelRpcClient::new(conf.url.to_string());
@ -122,7 +124,8 @@ impl SealevelInterchainGasPaymasterIndexer {
Ok(Self {
rpc_client,
igp,
_log_meta_composer: log_meta_composer,
log_meta_composer,
advanced_log_meta,
})
}
@ -168,23 +171,24 @@ impl SealevelInterchainGasPaymasterIndexer {
gas_amount: gas_payment_account.gas_amount.into(),
};
// let log_meta = self
// .interchain_payment_log_meta(
// U256::from(sequence_number),
// &valid_payment_pda_pubkey,
// &gas_payment_account.slot,
// )
// .await?;
let log_meta = LogMeta {
address: self.igp.program_id.to_bytes().into(),
block_number: gas_payment_account.slot,
// TODO: get these when building out scraper support.
// It's inconvenient to get these :|
block_hash: H256::zero(),
transaction_id: H512::zero(),
transaction_index: 0,
log_index: sequence_number.into(),
let log_meta = if self.advanced_log_meta {
self.interchain_payment_log_meta(
U256::from(sequence_number),
&valid_payment_pda_pubkey,
&gas_payment_account.slot,
)
.await?
} else {
LogMeta {
address: self.igp.program_id.to_bytes().into(),
block_number: gas_payment_account.slot,
// TODO: get these when building out scraper support.
// It's inconvenient to get these :|
block_hash: H256::zero(),
transaction_id: H512::zero(),
transaction_index: 0,
log_index: sequence_number.into(),
}
};
Ok(SealevelGasPayment::new(
@ -212,7 +216,7 @@ impl SealevelInterchainGasPaymasterIndexer {
Ok(expected_pubkey)
}
async fn _interchain_payment_log_meta(
async fn interchain_payment_log_meta(
&self,
log_index: U256,
payment_pda_pubkey: &Pubkey,
@ -220,7 +224,7 @@ impl SealevelInterchainGasPaymasterIndexer {
) -> ChainResult<LogMeta> {
let block = self.rpc_client.get_block(*payment_pda_slot).await?;
self._log_meta_composer
self.log_meta_composer
.log_meta(block, log_index, payment_pda_pubkey, payment_pda_slot)
.map_err(Into::<ChainCommunicationError>::into)
}

@ -501,6 +501,11 @@ impl Mailbox for SealevelMailbox {
// If we're using Jito, we need to send a tip to the Jito fee account.
// Otherwise, we need to set the compute unit price.
if self.use_jito() {
let tip: u64 = std::env::var("JITO_TIP_LAMPORTS")
.ok()
.and_then(|s| s.parse::<u64>().ok())
.unwrap_or(PROCESS_DESIRED_PRIORITIZATION_FEE_LAMPORTS_PER_TX);
// The tip is a standalone transfer to a Jito fee account.
// See https://github.com/jito-labs/mev-protos/blob/master/json_rpc/http.md#sendbundle.
instructions.push(solana_sdk::system_instruction::transfer(
@ -508,7 +513,7 @@ impl Mailbox for SealevelMailbox {
// A random Jito fee account, taken from the getFeeAccount RPC response:
// https://github.com/jito-labs/mev-protos/blob/master/json_rpc/http.md#gettipaccounts
&solana_sdk::pubkey!("DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh"),
PROCESS_DESIRED_PRIORITIZATION_FEE_LAMPORTS_PER_TX,
tip,
));
}
// "processed" level commitment does not guarantee finality.
@ -648,10 +653,15 @@ pub struct SealevelMailboxIndexer {
program_id: Pubkey,
dispatch_message_log_meta_composer: LogMetaComposer,
delivery_message_log_meta_composer: LogMetaComposer,
advanced_log_meta: bool,
}
impl SealevelMailboxIndexer {
pub fn new(conf: &ConnectionConf, locator: ContractLocator) -> ChainResult<Self> {
pub fn new(
conf: &ConnectionConf,
locator: ContractLocator,
advanced_log_meta: bool,
) -> ChainResult<Self> {
let program_id = Pubkey::from(<[u8; 32]>::from(locator.address));
let mailbox = SealevelMailbox::new(conf, locator, None)?;
@ -672,6 +682,7 @@ impl SealevelMailboxIndexer {
mailbox,
dispatch_message_log_meta_composer,
delivery_message_log_meta_composer,
advanced_log_meta,
})
}
@ -712,23 +723,24 @@ impl SealevelMailboxIndexer {
let hyperlane_message =
HyperlaneMessage::read_from(&mut &dispatched_message_account.encoded_message[..])?;
// let log_meta = self
// .dispatch_message_log_meta(
// U256::from(nonce),
// &valid_message_storage_pda_pubkey,
// &dispatched_message_account.slot,
// )
// .await?;
let log_meta = LogMeta {
address: self.program_id.to_bytes().into(),
block_number: dispatched_message_account.slot,
// TODO: get these when building out scraper support.
// It's inconvenient to get these :|
block_hash: H256::zero(),
transaction_id: H512::zero(),
transaction_index: 0,
log_index: U256::zero(),
let log_meta = if self.advanced_log_meta {
self.dispatch_message_log_meta(
U256::from(nonce),
&valid_message_storage_pda_pubkey,
&dispatched_message_account.slot,
)
.await?
} else {
LogMeta {
address: self.program_id.to_bytes().into(),
block_number: dispatched_message_account.slot,
// TODO: get these when building out scraper support.
// It's inconvenient to get these :|
block_hash: H256::zero(),
transaction_id: H512::zero(),
transaction_index: 0,
log_index: U256::zero(),
}
};
Ok((hyperlane_message.into(), log_meta))
@ -748,7 +760,7 @@ impl SealevelMailboxIndexer {
Ok(expected_pubkey)
}
async fn _dispatch_message_log_meta(
async fn dispatch_message_log_meta(
&self,
log_index: U256,
message_storage_pda_pubkey: &Pubkey,
@ -805,23 +817,24 @@ impl SealevelMailboxIndexer {
.into_inner();
let message_id = delivered_message_account.message_id;
// let log_meta = self
// .delivered_message_log_meta(
// U256::from(nonce),
// &valid_message_storage_pda_pubkey,
// &delivered_message_account.slot,
// )
// .await?;
let log_meta = LogMeta {
address: self.program_id.to_bytes().into(),
block_number: delivered_message_account.slot,
// TODO: get these when building out scraper support.
// It's inconvenient to get these :|
block_hash: H256::zero(),
transaction_id: H512::zero(),
transaction_index: 0,
log_index: U256::zero(),
let log_meta = if self.advanced_log_meta {
self.delivered_message_log_meta(
U256::from(nonce),
&valid_message_storage_pda_pubkey,
&delivered_message_account.slot,
)
.await?
} else {
LogMeta {
address: self.program_id.to_bytes().into(),
block_number: delivered_message_account.slot,
// TODO: get these when building out scraper support.
// It's inconvenient to get these :|
block_hash: H256::zero(),
transaction_id: H512::zero(),
transaction_index: 0,
log_index: U256::zero(),
}
};
Ok((message_id.into(), log_meta))
@ -839,7 +852,7 @@ impl SealevelMailboxIndexer {
Ok(expected_pubkey)
}
async fn _delivered_message_log_meta(
async fn delivered_message_log_meta(
&self,
log_index: U256,
message_storage_pda_pubkey: &Pubkey,

@ -1839,7 +1839,7 @@
"aggregationHook": "0xF6C1769d5390Be0f77080eF7791fBbA7eF4D5659",
"blockExplorers": [
{
"apiUrl": "https://explorer.mintchain.io/api/eth-rpc",
"apiUrl": "https://explorer.mintchain.io/api",
"family": "blockscout",
"name": "Mint Explorer",
"url": "https://explorer.mintchain.io"
@ -5731,6 +5731,402 @@
"testRecipient": "0x545E289B88c6d97b74eC0B96e308cae46Bf5f832",
"timelockController": "0x0000000000000000000000000000000000000000",
"validatorAnnounce": "0x26A29486480BD74f9B830a9B8dB33cb43C40f496"
},
"boba": {
"blockExplorers": [
{
"apiUrl": "https://api.routescan.io/v2/network/mainnet/evm/288/etherscan/api",
"family": "routescan",
"name": "bobascan",
"url": "https://bobascan.com"
}
],
"blocks": {
"confirmations": 1,
"estimateBlockTime": 2,
"reorgPeriod": 5
},
"chainId": 288,
"deployer": {
"name": "Abacus Works",
"url": "https://www.hyperlane.xyz"
},
"displayName": "Boba Mainnet",
"domainId": 288,
"gasCurrencyCoinGeckoId": "ethereum",
"name": "boba",
"nativeToken": {
"decimals": 18,
"name": "Ether",
"symbol": "ETH"
},
"protocol": "ethereum",
"rpcUrls": [
{
"http": "https://mainnet.boba.network"
}
],
"technicalStack": "opstack",
"aggregationHook": "0x4533B9ff84bE4f4009409414aF8b8e9c3f4F52a8",
"domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730",
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849",
"interchainAccountIsm": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"interchainAccountRouter": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"interchainGasPaymaster": "0x9534122Aae7978dB8f5f10dF4432233c53e820A1",
"interchainSecurityModule": "0x9c582a96B7350eEd313560Aeb9aBDff047aeaD36",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"pausableHook": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"pausableIsm": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563",
"protocolFee": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8",
"proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"staticAggregationIsm": "0x46De8b87577624b9ce63201238982b95ad0d7Ea4",
"staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"storageGasOracle": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"testRecipient": "0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE",
"timelockController": "0x0000000000000000000000000000000000000000",
"validatorAnnounce": "0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e",
"index": {
"from": 10598389
}
},
"duckchain": {
"blockExplorers": [
{
"apiUrl": "https://scan.duckchain.io/api",
"family": "blockscout",
"name": "DuckChain Explorer",
"url": "https://scan.duckchain.io"
}
],
"blocks": {
"confirmations": 3,
"estimateBlockTime": 1,
"reorgPeriod": 5
},
"chainId": 5545,
"deployer": {
"name": "Abacus Works",
"url": "https://www.hyperlane.xyz"
},
"displayName": "DuckChain",
"domainId": 5545,
"gasCurrencyCoinGeckoId": "the-open-network",
"index": {
"from": 1149918
},
"name": "duckchain",
"nativeToken": {
"decimals": 18,
"name": "Toncoin",
"symbol": "TON"
},
"protocol": "ethereum",
"rpcUrls": [
{
"http": "https://rpc.duckchain.io"
},
{
"http": "https://rpc-hk.duckchain.io"
}
],
"technicalStack": "arbitrumnitro",
"aggregationHook": "0x4533B9ff84bE4f4009409414aF8b8e9c3f4F52a8",
"domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730",
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849",
"interchainAccountIsm": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"interchainAccountRouter": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"interchainGasPaymaster": "0x9534122Aae7978dB8f5f10dF4432233c53e820A1",
"interchainSecurityModule": "0x739800B825916456b55CF832A535eE253bC1f358",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"pausableHook": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"pausableIsm": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563",
"protocolFee": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8",
"proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"staticAggregationIsm": "0x46De8b87577624b9ce63201238982b95ad0d7Ea4",
"staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"storageGasOracle": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"testRecipient": "0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE",
"timelockController": "0x0000000000000000000000000000000000000000",
"validatorAnnounce": "0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e"
},
"superseed": {
"blockExplorers": [
{
"apiUrl": "https://explorer.superseed.xyz/api",
"family": "blockscout",
"name": "Superseed Explorer",
"url": "https://explorer.superseed.xyz"
}
],
"blocks": {
"confirmations": 1,
"estimateBlockTime": 2,
"reorgPeriod": 5
},
"chainId": 5330,
"deployer": {
"name": "Abacus Works",
"url": "https://www.hyperlane.xyz"
},
"displayName": "Superseed",
"domainId": 5330,
"gasCurrencyCoinGeckoId": "ethereum",
"name": "superseed",
"nativeToken": {
"decimals": 18,
"name": "Ether",
"symbol": "ETH"
},
"protocol": "ethereum",
"rpcUrls": [
{
"http": "https://mainnet.superseed.xyz"
}
],
"technicalStack": "opstack",
"aggregationHook": "0x4533B9ff84bE4f4009409414aF8b8e9c3f4F52a8",
"domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730",
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849",
"interchainAccountIsm": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"interchainAccountRouter": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"interchainGasPaymaster": "0x9534122Aae7978dB8f5f10dF4432233c53e820A1",
"interchainSecurityModule": "0x9bdafD7aEd501B30f72b24Ce85d423eB77f51ba0",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"pausableHook": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"pausableIsm": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563",
"protocolFee": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8",
"proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"staticAggregationIsm": "0x46De8b87577624b9ce63201238982b95ad0d7Ea4",
"staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"storageGasOracle": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"testRecipient": "0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE",
"timelockController": "0x0000000000000000000000000000000000000000",
"validatorAnnounce": "0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e",
"index": {
"from": 3010957
}
},
"unichain": {
"blockExplorers": [
{
"apiUrl": "https://unichain.blockscout.com/api",
"family": "blockscout",
"name": "Unichain Explorer",
"url": "https://unichain.blockscout.com"
}
],
"blocks": {
"confirmations": 1,
"estimateBlockTime": 1,
"reorgPeriod": 5
},
"chainId": 130,
"deployer": {
"name": "Abacus Works",
"url": "https://www.hyperlane.xyz"
},
"displayName": "Unichain",
"domainId": 130,
"gasCurrencyCoinGeckoId": "ethereum",
"name": "unichain",
"nativeToken": {
"decimals": 18,
"name": "Ether",
"symbol": "ETH"
},
"protocol": "ethereum",
"rpcUrls": [
{
"http": "https://mainnet.unichain.org"
}
],
"technicalStack": "opstack",
"aggregationHook": "0x4533B9ff84bE4f4009409414aF8b8e9c3f4F52a8",
"domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730",
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849",
"interchainAccountIsm": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"interchainAccountRouter": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"interchainGasPaymaster": "0x9534122Aae7978dB8f5f10dF4432233c53e820A1",
"interchainSecurityModule": "0xce5718713f019b71F7d37058cD75d12e01dE2611",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"pausableHook": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"pausableIsm": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563",
"protocolFee": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8",
"proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"staticAggregationIsm": "0x46De8b87577624b9ce63201238982b95ad0d7Ea4",
"staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"storageGasOracle": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"testRecipient": "0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE",
"timelockController": "0x0000000000000000000000000000000000000000",
"validatorAnnounce": "0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e",
"index": {
"from": 1453239
}
},
"vana": {
"blockExplorers": [
{
"apiUrl": "https://vanascan.io/api/eth-rpc",
"family": "blockscout",
"name": "Vana Explorer",
"url": "https://vanascan.io"
}
],
"blocks": {
"confirmations": 1,
"estimateBlockTime": 6,
"reorgPeriod": 5
},
"chainId": 1480,
"deployer": {
"name": "Abacus Works",
"url": "https://www.hyperlane.xyz"
},
"displayName": "Vana",
"domainId": 1480,
"gasCurrencyCoinGeckoId": "vana",
"name": "vana",
"nativeToken": {
"decimals": 18,
"name": "Vana",
"symbol": "VANA"
},
"protocol": "ethereum",
"rpcUrls": [
{
"http": "https://rpc.vana.org"
}
],
"technicalStack": "other",
"aggregationHook": "0x4533B9ff84bE4f4009409414aF8b8e9c3f4F52a8",
"domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730",
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849",
"interchainAccountIsm": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"interchainAccountRouter": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"interchainGasPaymaster": "0x9534122Aae7978dB8f5f10dF4432233c53e820A1",
"interchainSecurityModule": "0xce5718713f019b71F7d37058cD75d12e01dE2611",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"pausableHook": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"pausableIsm": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563",
"protocolFee": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8",
"proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"staticAggregationIsm": "0x46De8b87577624b9ce63201238982b95ad0d7Ea4",
"staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"storageGasOracle": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"testRecipient": "0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE",
"timelockController": "0x0000000000000000000000000000000000000000",
"validatorAnnounce": "0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e",
"index": {
"from": 629917
}
},
"bsquared": {
"blockExplorers": [
{
"apiUrl": "https://explorer.bsquared.network/api",
"family": "etherscan",
"name": "B² Network Explorer",
"url": "https://explorer.bsquared.network"
}
],
"blocks": {
"confirmations": 1,
"estimateBlockTime": 3,
"reorgPeriod": 5
},
"chainId": 223,
"deployer": {
"name": "Abacus Works",
"url": "https://www.hyperlane.xyz"
},
"displayName": "B² Network",
"domainId": 223,
"gasCurrencyCoinGeckoId": "bitcoin",
"name": "bsquared",
"nativeToken": {
"decimals": 18,
"name": "Bitcoin",
"symbol": "BTC"
},
"protocol": "ethereum",
"rpcUrls": [
{
"http": "https://rpc.bsquared.network"
},
{
"http": "https://rpc.ankr.com/b2"
},
{
"http": "https://mainnet.b2-rpc.com"
},
{
"http": "https://b2-mainnet.alt.technology"
}
],
"technicalStack": "other",
"aggregationHook": "0x03D610d916D5D274e4A31c026fd6884281A35d9C",
"domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730",
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0x60bB6D060393D3C206719A7bD61844cC82891cfB",
"interchainAccountIsm": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"interchainAccountRouter": "0x4D50044335dc1d4D26c343AdeDf6E47808475Deb",
"interchainGasPaymaster": "0x70EbA87Cd15616f32C736B3f3BdCfaeD0713a82B",
"interchainSecurityModule": "0x7dBb82188F553161d4B4ac3a2362Bff3a57e21D2",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"pausableHook": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de",
"pausableIsm": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849",
"protocolFee": "0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE",
"proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"staticAggregationHookFactory": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"staticAggregationIsm": "0x7dBb82188F553161d4B4ac3a2362Bff3a57e21D2",
"staticAggregationIsmFactory": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"staticMerkleRootMultisigIsmFactory": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"staticMerkleRootWeightedMultisigIsmFactory": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"staticMessageIdMultisigIsmFactory": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"staticMessageIdWeightedMultisigIsmFactory": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"storageGasOracle": "0x451dF8AB0936D85526D816f0b4dCaDD934A034A4",
"testRecipient": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597",
"timelockController": "0x0000000000000000000000000000000000000000",
"validatorAnnounce": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"index": {
"from": 9687363
}
}
},
"defaultRpcConsensusType": "fallback"

@ -151,13 +151,14 @@ impl Settings {
build_contract_fns!(build_validator_announce, build_validator_announces -> dyn ValidatorAnnounce);
build_contract_fns!(build_provider, build_providers -> dyn HyperlaneProvider);
/// Build a contract sync for type `T` using log store `D`
/// Build a contract sync for type `T` using log store `S`
pub async fn sequenced_contract_sync<T, S>(
&self,
domain: &HyperlaneDomain,
metrics: &CoreMetrics,
sync_metrics: &ContractSyncMetrics,
store: Arc<S>,
advanced_log_meta: bool,
) -> eyre::Result<Arc<SequencedDataContractSync<T>>>
where
T: Indexable + Debug,
@ -166,7 +167,8 @@ impl Settings {
{
let setup = self.chain_setup(domain)?;
// Currently, all indexers are of the `SequenceIndexer` type
let indexer = SequenceIndexer::<T>::try_from_with_metrics(setup, metrics).await?;
let indexer =
SequenceIndexer::<T>::try_from_with_metrics(setup, metrics, advanced_log_meta).await?;
Ok(Arc::new(ContractSync::new(
domain.clone(),
store.clone() as SequenceAwareLogStore<_>,
@ -175,13 +177,14 @@ impl Settings {
)))
}
/// Build a contract sync for type `T` using log store `D`
/// Build a contract sync for type `T` using log store `S`
pub async fn watermark_contract_sync<T, S>(
&self,
domain: &HyperlaneDomain,
metrics: &CoreMetrics,
sync_metrics: &ContractSyncMetrics,
store: Arc<S>,
advanced_log_meta: bool,
) -> eyre::Result<Arc<WatermarkContractSync<T>>>
where
T: Indexable + Debug,
@ -190,7 +193,8 @@ impl Settings {
{
let setup = self.chain_setup(domain)?;
// Currently, all indexers are of the `SequenceIndexer` type
let indexer = SequenceIndexer::<T>::try_from_with_metrics(setup, metrics).await?;
let indexer =
SequenceIndexer::<T>::try_from_with_metrics(setup, metrics, advanced_log_meta).await?;
Ok(Arc::new(ContractSync::new(
domain.clone(),
store.clone() as WatermarkLogStore<_>,
@ -208,6 +212,7 @@ impl Settings {
metrics: &CoreMetrics,
sync_metrics: &ContractSyncMetrics,
stores: HashMap<HyperlaneDomain, Arc<S>>,
advanced_log_meta: bool,
) -> Result<HashMap<HyperlaneDomain, Arc<dyn ContractSyncer<T>>>>
where
T: Indexable + Debug + Send + Sync + Clone + Eq + Hash + 'static,
@ -227,6 +232,7 @@ impl Settings {
metrics,
sync_metrics,
stores.get(domain).unwrap().clone(),
advanced_log_meta,
)
.await
.map(|r| r as Arc<dyn ContractSyncer<T>>)?,
@ -236,6 +242,7 @@ impl Settings {
metrics,
sync_metrics,
stores.get(domain).unwrap().clone(),
advanced_log_meta,
)
.await
.map(|r| r as Arc<dyn ContractSyncer<T>>)?,

@ -33,7 +33,11 @@ use super::ChainSigner;
#[async_trait]
pub trait TryFromWithMetrics<T>: Sized {
/// Try to convert the chain configuration into the type
async fn try_from_with_metrics(conf: &ChainConf, metrics: &CoreMetrics) -> Result<Self>;
async fn try_from_with_metrics(
conf: &ChainConf,
metrics: &CoreMetrics,
advanced_log_meta: bool,
) -> Result<Self>;
}
/// A chain setup is a domain ID, an address on that chain (where the mailbox is
@ -72,22 +76,38 @@ pub type MerkleTreeHookIndexer = Arc<dyn SequenceAwareIndexer<MerkleTreeInsertio
#[async_trait]
impl TryFromWithMetrics<ChainConf> for MessageIndexer {
async fn try_from_with_metrics(conf: &ChainConf, metrics: &CoreMetrics) -> Result<Self> {
conf.build_message_indexer(metrics).await.map(Into::into)
async fn try_from_with_metrics(
conf: &ChainConf,
metrics: &CoreMetrics,
advanced_log_meta: bool,
) -> Result<Self> {
conf.build_message_indexer(metrics, advanced_log_meta)
.await
.map(Into::into)
}
}
#[async_trait]
impl TryFromWithMetrics<ChainConf> for DeliveryIndexer {
async fn try_from_with_metrics(conf: &ChainConf, metrics: &CoreMetrics) -> Result<Self> {
conf.build_delivery_indexer(metrics).await.map(Into::into)
async fn try_from_with_metrics(
conf: &ChainConf,
metrics: &CoreMetrics,
advanced_log_meta: bool,
) -> Result<Self> {
conf.build_delivery_indexer(metrics, advanced_log_meta)
.await
.map(Into::into)
}
}
#[async_trait]
impl TryFromWithMetrics<ChainConf> for IgpIndexer {
async fn try_from_with_metrics(conf: &ChainConf, metrics: &CoreMetrics) -> Result<Self> {
conf.build_interchain_gas_payment_indexer(metrics)
async fn try_from_with_metrics(
conf: &ChainConf,
metrics: &CoreMetrics,
advanced_log_meta: bool,
) -> Result<Self> {
conf.build_interchain_gas_payment_indexer(metrics, advanced_log_meta)
.await
.map(Into::into)
}
@ -95,8 +115,12 @@ impl TryFromWithMetrics<ChainConf> for IgpIndexer {
#[async_trait]
impl TryFromWithMetrics<ChainConf> for MerkleTreeHookIndexer {
async fn try_from_with_metrics(conf: &ChainConf, metrics: &CoreMetrics) -> Result<Self> {
conf.build_merkle_tree_hook_indexer(metrics)
async fn try_from_with_metrics(
conf: &ChainConf,
metrics: &CoreMetrics,
advanced_log_meta: bool,
) -> Result<Self> {
conf.build_merkle_tree_hook_indexer(metrics, advanced_log_meta)
.await
.map(Into::into)
}
@ -266,6 +290,7 @@ impl ChainConf {
pub async fn build_message_indexer(
&self,
metrics: &CoreMetrics,
advanced_log_meta: bool,
) -> Result<Box<dyn SequenceAwareIndexer<HyperlaneMessage>>> {
let ctx = "Building delivery indexer";
let locator = self.locator(self.addresses.mailbox);
@ -284,7 +309,11 @@ impl ChainConf {
}
ChainConnectionConf::Fuel(_) => todo!(),
ChainConnectionConf::Sealevel(conf) => {
let indexer = Box::new(h_sealevel::SealevelMailboxIndexer::new(conf, locator)?);
let indexer = Box::new(h_sealevel::SealevelMailboxIndexer::new(
conf,
locator,
advanced_log_meta,
)?);
Ok(indexer as Box<dyn SequenceAwareIndexer<HyperlaneMessage>>)
}
ChainConnectionConf::Cosmos(conf) => {
@ -306,6 +335,7 @@ impl ChainConf {
pub async fn build_delivery_indexer(
&self,
metrics: &CoreMetrics,
advanced_log_meta: bool,
) -> Result<Box<dyn SequenceAwareIndexer<H256>>> {
let ctx = "Building delivery indexer";
let locator = self.locator(self.addresses.mailbox);
@ -324,7 +354,11 @@ impl ChainConf {
}
ChainConnectionConf::Fuel(_) => todo!(),
ChainConnectionConf::Sealevel(conf) => {
let indexer = Box::new(h_sealevel::SealevelMailboxIndexer::new(conf, locator)?);
let indexer = Box::new(h_sealevel::SealevelMailboxIndexer::new(
conf,
locator,
advanced_log_meta,
)?);
Ok(indexer as Box<dyn SequenceAwareIndexer<H256>>)
}
ChainConnectionConf::Cosmos(conf) => {
@ -385,6 +419,7 @@ impl ChainConf {
pub async fn build_interchain_gas_payment_indexer(
&self,
metrics: &CoreMetrics,
advanced_log_meta: bool,
) -> Result<Box<dyn SequenceAwareIndexer<InterchainGasPayment>>> {
let ctx = "Building IGP indexer";
let locator = self.locator(self.addresses.interchain_gas_paymaster);
@ -407,7 +442,12 @@ impl ChainConf {
ChainConnectionConf::Fuel(_) => todo!(),
ChainConnectionConf::Sealevel(conf) => {
let indexer = Box::new(
h_sealevel::SealevelInterchainGasPaymasterIndexer::new(conf, locator).await?,
h_sealevel::SealevelInterchainGasPaymasterIndexer::new(
conf,
locator,
advanced_log_meta,
)
.await?,
);
Ok(indexer as Box<dyn SequenceAwareIndexer<InterchainGasPayment>>)
}
@ -428,6 +468,7 @@ impl ChainConf {
pub async fn build_merkle_tree_hook_indexer(
&self,
metrics: &CoreMetrics,
advanced_log_meta: bool,
) -> Result<Box<dyn SequenceAwareIndexer<MerkleTreeInsertion>>> {
let ctx = "Building merkle tree hook indexer";
let locator = self.locator(self.addresses.merkle_tree_hook);
@ -446,8 +487,11 @@ impl ChainConf {
}
ChainConnectionConf::Fuel(_) => todo!(),
ChainConnectionConf::Sealevel(conf) => {
let mailbox_indexer =
Box::new(h_sealevel::SealevelMailboxIndexer::new(conf, locator)?);
let mailbox_indexer = Box::new(h_sealevel::SealevelMailboxIndexer::new(
conf,
locator,
advanced_log_meta,
)?);
let indexer = Box::new(h_sealevel::SealevelMerkleTreeHookIndexer::new(
*mailbox_indexer,
));

@ -17,6 +17,23 @@ use solana_sdk::{
const SOLANA_DOMAIN: u32 = 1399811149;
pub(crate) fn get_compute_unit_price_micro_lamports_for_id(domain: u32) -> u64 {
get_compute_unit_price(domain == SOLANA_DOMAIN)
}
pub(crate) fn get_compute_unit_price_micro_lamports_for_chain_name(chain_name: &str) -> u64 {
get_compute_unit_price(chain_name == "solanamainnet")
}
fn get_compute_unit_price(is_solanamainnet: bool) -> u64 {
if is_solanamainnet {
// Generally taking a low/medium value from https://www.quicknode.com/gas-tracker/solana
500_000
} else {
0
}
}
pub(crate) fn account_exists(client: &RpcClient, account: &Pubkey) -> Result<bool, ClientError> {
// Using `get_account_with_commitment` instead of `get_account` so we get Ok(None) when the account
// doesn't exist, rather than an error
@ -73,9 +90,9 @@ pub(crate) fn deploy_program(
program_keypair_path,
];
let compute_unit_price = get_compute_unit_price_micro_lamports_for_id(local_domain).to_string();
if local_domain.eq(&SOLANA_DOMAIN) {
// May need tweaking depending on gas prices / available balance
command.append(&mut vec!["--with-compute-unit-price", "550000"]);
command.extend(vec!["--with-compute-unit-price", &compute_unit_price]);
}
build_cmd(command.as_slice(), None, None);

@ -9,26 +9,21 @@ use solana_sdk::{compute_budget, compute_budget::ComputeBudgetInstruction};
use std::collections::HashMap;
use std::{fs::File, path::Path};
use crate::cmd_utils::get_compute_unit_price_micro_lamports_for_chain_name;
use crate::ONE_SOL_IN_LAMPORTS;
use crate::{
artifacts::{read_json, write_json},
cmd_utils::{create_and_write_keypair, create_new_directory, deploy_program},
multisig_ism::deploy_multisig_ism_message_id,
Context, CoreCmd, CoreDeploy, CoreSubCmd,
};
use crate::{DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, ONE_SOL_IN_LAMPORTS};
use hyperlane_core::H256;
use hyperlane_sealevel_igp::accounts::{SOL_DECIMALS, TOKEN_EXCHANGE_RATE_SCALE};
pub(crate) fn adjust_gas_price_if_needed(chain_name: &str, ctx: &mut Context) {
if chain_name.eq("solanamainnet") {
let compute_unit_price = get_compute_unit_price_micro_lamports_for_chain_name(chain_name);
let mut initial_instructions = ctx.initial_instructions.borrow_mut();
const PROCESS_DESIRED_PRIORITIZATION_FEE_LAMPORTS_PER_TX: u64 = 50_000_000;
const MICRO_LAMPORT_FEE_PER_LIMIT: u64 =
// Convert to micro-lamports
(PROCESS_DESIRED_PRIORITIZATION_FEE_LAMPORTS_PER_TX * 1_000_000)
// Divide by the max compute units
/ DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64;
for i in initial_instructions.iter_mut() {
if i.instruction.program_id != compute_budget::id() {
continue;
@ -41,9 +36,8 @@ pub(crate) fn adjust_gas_price_if_needed(chain_name: &str, ctx: &mut Context) {
ComputeBudgetInstruction::SetComputeUnitPrice { .. }
) {
// The compute unit price has already been set, so we override it and return early
i.instruction = ComputeBudgetInstruction::set_compute_unit_price(
MICRO_LAMPORT_FEE_PER_LIMIT,
);
i.instruction =
ComputeBudgetInstruction::set_compute_unit_price(compute_unit_price);
return;
}
}
@ -51,10 +45,10 @@ pub(crate) fn adjust_gas_price_if_needed(chain_name: &str, ctx: &mut Context) {
initial_instructions.push(
(
ComputeBudgetInstruction::set_compute_unit_price(MICRO_LAMPORT_FEE_PER_LIMIT),
ComputeBudgetInstruction::set_compute_unit_price(compute_unit_price),
Some(format!(
"Set compute unit price to {}",
MICRO_LAMPORT_FEE_PER_LIMIT
"Set compute unit price to {} micro-lamports",
compute_unit_price
)),
)
.into(),

@ -0,0 +1,10 @@
{
"eclipsemainnet": {
"hex": "0x82f7445ccda6396092998c8f841f0d4eb63cca29ba23cfd2609d283f3ee9d13f",
"base58": "9pEgj7m2VkwLtJHPtTw5d8vbB7kfjzcXXCRgdwruW7C2"
},
"ethereum": {
"hex": "0x000000000000000000000000d34fe1685c28a68bb4b8faaadcb2769962ae737c",
"base58": "1111111111113wkPRLXCJuj9539UEURsN3qhoaYb"
}
}

@ -0,0 +1,17 @@
{
"eclipsemainnet": {
"type": "synthetic",
"decimals": 9,
"remoteDecimals": 18,
"name": "Autocompounding Pirex Ether",
"symbol": "apxETH",
"uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/ae7df1bc00af19f8ba692c14e4df3acdbf30497d/deployments/warp_routes/APXETH/metadata.json",
"interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj"
},
"ethereum": {
"type": "collateral",
"decimals": 18,
"token": "0x9ba021b0a9b958b5e75ce9f6dff97c7ee52cb3e6",
"foreignDeployment": "0xd34FE1685c28A68Bb4B8fAaadCb2769962AE737c"
}
}

@ -0,0 +1,10 @@
{
"eclipsemainnet": {
"hex": "0xb06d58417c929a624e9b689e604e6d60ca652168ee76b9a290bd5b974b22b306",
"base58": "CshTfxXWMvnRAwBTCjQ4577bkP5po5ZuNG1QTuQxA5Au"
},
"solanamainnet": {
"hex": "0x08bb318b88b38cc6f450b185e51a9c42402dc9d36fa6741c19c2aa62464a5eb3",
"base58": "b5pMgizA9vrGRt3hVqnU7vUVGBQUnLpwPzcJhG1ucyQ"
}
}

@ -0,0 +1,17 @@
{
"solanamainnet": {
"type": "collateral",
"decimals": 9,
"interchainGasPaymaster": "AkeHBbE5JkwVppujCQQ6WuxsVsJtruBAjUo6fDCFp6fF",
"token": "ezSoL6fY1PVdJcJsUpe5CM3xkfmy3zoVCABybm5WtiC",
"splTokenProgram": "token"
},
"eclipsemainnet": {
"type": "synthetic",
"decimals": 9,
"name": "Renzo Restaked SOL",
"symbol": "ezSOL",
"uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/ae7df1bc00af19f8ba692c14e4df3acdbf30497d/deployments/warp_routes/EZSOL/metadata.json",
"interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj"
}
}

@ -1,5 +1,12 @@
# @hyperlane-xyz/core
## 5.8.2
### Patch Changes
- Updated dependencies [fa6d5f5c6]
- @hyperlane-xyz/utils@7.2.0
## 5.8.1
### Patch Changes

@ -7,5 +7,5 @@ pragma solidity >=0.6.11;
**/
abstract contract PackageVersioned {
// GENERATED CODE - DO NOT EDIT
string public constant PACKAGE_VERSION = "5.8.1";
string public constant PACKAGE_VERSION = "5.8.2";
}

@ -1,14 +1,14 @@
{
"name": "@hyperlane-xyz/core",
"description": "Core solidity contracts for Hyperlane",
"version": "5.8.1",
"version": "5.8.2",
"dependencies": {
"@arbitrum/nitro-contracts": "^1.2.1",
"@eth-optimism/contracts": "^0.6.0",
"@hyperlane-xyz/utils": "7.1.0",
"@hyperlane-xyz/utils": "7.2.0",
"@layerzerolabs/lz-evm-oapp-v2": "2.0.2",
"@openzeppelin/contracts": "^4.9.3",
"@openzeppelin/contracts-upgradeable": "^v4.9.3",
"@openzeppelin/contracts-upgradeable": "^4.9.3",
"fx-portal": "^1.0.3"
},
"devDependencies": {
@ -19,7 +19,7 @@
"@typechain/ethers-v6": "^0.5.1",
"@typechain/hardhat": "^9.1.0",
"@types/node": "^18.14.5",
"chai": "4.5.0",
"chai": "^4.5.0",
"ethereum-waffle": "^4.0.10",
"ethers": "^5.7.2",
"hardhat": "^2.22.2",

@ -1,6 +0,0 @@
{
"rules": {
"no-console": ["off"]
}
}

@ -1,5 +1,7 @@
# @hyperlane-xyz/ccip-server
## 7.2.0
## 7.1.0
## 7.0.0

@ -0,0 +1,17 @@
import MonorepoDefaults from '../../eslint.config.mjs';
export default [
...MonorepoDefaults,
{
files: ['./src/**/*.ts'],
},
{
rules: {
'no-console': ['off'],
'no-restricted-imports': ['off'],
},
},
{
ignores: ['**/__mocks__/*','**/tests/*',]
}
];

@ -1,6 +1,6 @@
{
"name": "@hyperlane-xyz/ccip-server",
"version": "7.1.0",
"version": "7.2.0",
"description": "CCIP server",
"typings": "dist/index.d.ts",
"typedocMain": "src/index.ts",
@ -12,27 +12,30 @@
"node": ">=16"
},
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "tsx src/server.ts",
"dev": "nodemon src/server.ts",
"test": "jest",
"lint": "eslint -c ./eslint.config.mjs",
"prettier": "prettier --write ./src/* ./tests/"
},
"author": "brolee",
"license": "Apache-2.0",
"devDependencies": {
"@jest/globals": "^29.7.0",
"@types/node": "^16.9.1",
"@types/node": "^18.14.5",
"eslint": "^9.15.0",
"jest": "^29.7.0",
"nodemon": "^3.0.3",
"prettier": "^2.8.8",
"ts-jest": "^29.1.2",
"ts-node": "^10.8.0",
"tsx": "^4.7.1",
"tsx": "^4.19.1",
"typescript": "5.3.3"
},
"dependencies": {
"@chainlink/ccip-read-server": "^0.2.1",
"dotenv-flow": "^4.1.0",
"ethers": "5.7.2"
"ethers": "^5.7.2"
}
}

@ -6,12 +6,14 @@ import { ProofsService } from './services/ProofsService';
// Initialize Services
const proofsService = new ProofsService(
config.LIGHT_CLIENT_ADDR,
config.RPC_ADDRESS,
config.STEP_FN_ID,
config.CHAIN_ID,
config.SUCCINCT_PLATFORM_URL,
config.SUCCINCT_API_KEY,
{
lightClientAddress: config.LIGHT_CLIENT_ADDR,
stepFunctionId: config.STEP_FN_ID,
platformUrl: config.SUCCINCT_PLATFORM_URL,
apiKey: config.SUCCINCT_API_KEY,
},
{ url: config.RPC_ADDRESS, chainId: config.CHAIN_ID },
{ url: `${config.SERVER_URL_PREFIX}:${config.SERVER_PORT}` },
);
// Initialize Server and add Service handlers

@ -27,8 +27,8 @@ class LightClientService {
* @param slot
* @returns
*/
async getSyncCommitteePoseidons(slot: bigint): Promise<string> {
return await this.lightClientContract.syncCommitteePoseidons(
getSyncCommitteePoseidons(slot: bigint): Promise<string> {
return this.lightClientContract.syncCommitteePoseidons(
this.getSyncCommitteePeriod(slot),
);
}

@ -4,8 +4,7 @@ import { TelepathyCcipReadIsmAbi } from '../abis/TelepathyCcipReadIsmAbi';
import { HyperlaneService } from './HyperlaneService';
import { LightClientService, SuccinctConfig } from './LightClientService';
import { RPCService } from './RPCService';
import { ProofResult } from './RPCService';
import { ProofResult, RPCService } from './RPCService';
import { ProofStatus } from './common/ProofStatusEnum';
type RPCConfig = {
@ -100,10 +99,7 @@ class ProofsService {
);
const slot = await this.lightClientService.calculateSlot(BigInt(timestamp));
const syncCommitteePoseidon = ''; // TODO get from LC
return await this.lightClientService.requestProof(
syncCommitteePoseidon,
slot,
);
return this.lightClientService.requestProof(syncCommitteePoseidon, slot);
}
/**

@ -0,0 +1,9 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "./dist/",
"rootDir": "./src"
},
"exclude": ["./node_modules/", "./dist/"],
"include": ["./src/*.ts"]
}

@ -1,2 +0,0 @@
node_modules
dist

@ -1,6 +0,0 @@
{
"rules": {
"no-console": ["off"],
"no-restricted-imports": ["off"]
}
}

@ -1,5 +1,22 @@
# @hyperlane-xyz/cli
## 7.2.0
### Minor Changes
- d51815760: Support using the CLI to deploy warp routes that involve foreign deployments
- 81ab4332f: Remove ismFactoryAddresses from warpConfig
- 4b3537470: Changed the type of defaultMultisigConfigs, to track validator aliases in addition to their addresses.
### Patch Changes
- Updated dependencies [81ab4332f]
- Updated dependencies [4b3537470]
- Updated dependencies [fa6d5f5c6]
- Updated dependencies [fa6d5f5c6]
- @hyperlane-xyz/sdk@7.2.0
- @hyperlane-xyz/utils@7.2.0
## 7.1.0
### Minor Changes

@ -19,15 +19,17 @@ import {
overrideRegistryUriCommandOption,
registryUriCommandOption,
skipConfirmationOption,
strategyCommandOption,
} from './src/commands/options.js';
import { registryCommand } from './src/commands/registry.js';
import { relayerCommand } from './src/commands/relayer.js';
import { sendCommand } from './src/commands/send.js';
import { statusCommand } from './src/commands/status.js';
import { strategyCommand } from './src/commands/strategy.js';
import { submitCommand } from './src/commands/submit.js';
import { validatorCommand } from './src/commands/validator.js';
import { warpCommand } from './src/commands/warp.js';
import { contextMiddleware } from './src/context/context.js';
import { contextMiddleware, signerMiddleware } from './src/context/context.js';
import { configureLogger, errorRed } from './src/logger.js';
import { checkVersion } from './src/utils/version-check.js';
import { VERSION } from './src/version.js';
@ -49,12 +51,14 @@ try {
.option('key', keyCommandOption)
.option('disableProxy', disableProxyCommandOption)
.option('yes', skipConfirmationOption)
.option('strategy', strategyCommandOption)
.global(['log', 'verbosity', 'registry', 'overrides', 'yes'])
.middleware([
(argv) => {
configureLogger(argv.log as LogFormat, argv.verbosity as LogLevel);
},
contextMiddleware,
signerMiddleware,
])
.command(avsCommand)
.command(configCommand)
@ -66,6 +70,7 @@ try {
.command(relayerCommand)
.command(sendCommand)
.command(statusCommand)
.command(strategyCommand)
.command(submitCommand)
.command(validatorCommand)
.command(warpCommand)

@ -0,0 +1,20 @@
import MonorepoDefaults from '../../eslint.config.mjs';
export default [
...MonorepoDefaults,
{
files: ['./src/**/*.ts', './cli.ts', './env.ts'],
},
{
rules: {
'no-console': ['off'],
'no-restricted-imports': ['off'],
},
},
{
ignores: ['./src/tests/**/*.ts'],
rules: {
'import/no-cycle': ['off'],
},
},
];

@ -1,16 +1,16 @@
{
"name": "@hyperlane-xyz/cli",
"version": "7.1.0",
"version": "7.2.0",
"description": "A command-line utility for common Hyperlane operations",
"dependencies": {
"@aws-sdk/client-kms": "^3.577.0",
"@aws-sdk/client-s3": "^3.577.0",
"@hyperlane-xyz/registry": "6.1.0",
"@hyperlane-xyz/sdk": "7.1.0",
"@hyperlane-xyz/utils": "7.1.0",
"@hyperlane-xyz/sdk": "7.2.0",
"@hyperlane-xyz/utils": "7.2.0",
"@inquirer/core": "9.0.10",
"@inquirer/figures": "1.0.5",
"@inquirer/prompts": "^3.0.0",
"@inquirer/prompts": "3.3.2",
"ansi-escapes": "^7.0.0",
"asn1.js": "^5.4.1",
"bignumber.js": "^9.1.1",
@ -18,7 +18,7 @@
"ethers": "^5.7.2",
"latest-version": "^8.0.0",
"terminal-link": "^3.0.0",
"tsx": "^4.7.1",
"tsx": "^4.19.1",
"yaml": "2.4.5",
"yargs": "^17.7.2",
"zod": "^3.21.2",
@ -26,18 +26,21 @@
"zx": "^8.1.4"
},
"devDependencies": {
"@eslint/js": "^9.15.0",
"@ethersproject/abi": "*",
"@ethersproject/providers": "*",
"@types/chai-as-promised": "^8",
"@types/mocha": "^10.0.1",
"@types/node": "^18.14.5",
"@types/yargs": "^17.0.24",
"@typescript-eslint/eslint-plugin": "^7.4.0",
"@typescript-eslint/parser": "^7.4.0",
"@typescript-eslint/eslint-plugin": "^8.1.6",
"@typescript-eslint/parser": "^8.1.6",
"chai": "^4.5.0",
"chai-as-promised": "^8.0.0",
"eslint": "^8.57.0",
"eslint": "^9.15.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"mocha": "^10.2.0",
"prettier": "^2.8.8",
"typescript": "5.3.3"
@ -47,7 +50,7 @@
"build": "yarn version:update && tsc",
"dev": "yarn version:update && tsc --watch",
"clean": "rm -rf ./dist",
"lint": "eslint . --ext .ts",
"lint": "eslint -c ./eslint.config.mjs",
"prettier": "prettier --write ./src ./examples",
"test:ci": "yarn mocha --config .mocharc.json",
"test:e2e": "./scripts/run-e2e-test.sh",

@ -429,7 +429,7 @@ const getEcdsaStakeRegistryAddress = (
): Address | undefined => {
try {
return avsAddresses[chain]['ecdsaStakeRegistry'];
} catch (err) {
} catch {
topLevelErrors.push(
` EcdsaStakeRegistry address not found for ${chain}`,
);

@ -4,7 +4,6 @@ import { WarpRouteDeployConfig, normalizeConfig } from '@hyperlane-xyz/sdk';
import { ObjectDiff, diffObjMerge } from '@hyperlane-xyz/utils';
import { log, logGreen } from '../logger.js';
import '../utils/output.js';
import { formatYamlViolationsOutput } from '../utils/output.js';
export async function runWarpRouteCheck({

@ -3,6 +3,7 @@ import { CommandModule } from 'yargs';
import { readChainConfigs } from '../config/chain.js';
import { readIsmConfig } from '../config/ism.js';
import { readMultisigConfig } from '../config/multisig.js';
import { readChainSubmissionStrategyConfig } from '../config/strategy.js';
import { readWarpRouteDeployConfig } from '../config/warp.js';
import { CommandModuleWithContext } from '../context/types.js';
import { log, logGreen } from '../logger.js';
@ -31,6 +32,7 @@ const validateCommand: CommandModule = {
.command(validateChainCommand)
.command(validateIsmCommand)
.command(validateIsmAdvancedCommand)
.command(validateStrategyCommand)
.command(validateWarpCommand)
.version(false)
.demandCommand(),
@ -76,6 +78,19 @@ const validateIsmAdvancedCommand: CommandModuleWithContext<{ path: string }> = {
},
};
const validateStrategyCommand: CommandModuleWithContext<{ path: string }> = {
command: 'strategy',
describe: 'Validates a Strategy config file',
builder: {
path: inputFileCommandOption(),
},
handler: async ({ path }) => {
await readChainSubmissionStrategyConfig(path);
logGreen('Config is valid');
process.exit(0);
},
};
const validateWarpCommand: CommandModuleWithContext<{ path: string }> = {
command: 'warp',
describe: 'Validate a Warp Route deployment config file',

@ -95,6 +95,7 @@ export const DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH =
'./configs/warp-route-deployment.yaml';
export const DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH = './configs/core-config.yaml';
export const DEFAULT_STRATEGY_CONFIG_PATH = `${os.homedir()}/.hyperlane/strategies/default-strategy.yaml`;
export const warpDeploymentConfigCommandOption: Options = {
type: 'string',
@ -196,8 +197,8 @@ export const transactionsCommandOption: Options = {
export const strategyCommandOption: Options = {
type: 'string',
description: 'The submission strategy input file path.',
alias: 's',
demandOption: true,
alias: ['s', 'strategy'],
demandOption: false,
};
export const addressCommandOption = (

@ -9,7 +9,7 @@ import { Address } from '@hyperlane-xyz/utils';
import { CommandModuleWithContext } from '../context/types.js';
import { log } from '../logger.js';
import { tryReadJson, writeJson } from '../utils/files.js';
import { getWarpCoreConfigOrExit } from '../utils/input.js';
import { getWarpCoreConfigOrExit } from '../utils/warp.js';
import {
agentTargetsCommandOption,

@ -1,7 +1,14 @@
// Commands that send tx and require a key to sign.
// It's useful to have this listed here so the context
// middleware can request keys up front when required.
export const SIGN_COMMANDS = ['deploy', 'send', 'status', 'submit', 'relayer'];
export const SIGN_COMMANDS = [
'apply',
'deploy',
'send',
'status',
'submit',
'relayer',
];
export function isSignCommand(argv: any): boolean {
return (
@ -9,3 +16,15 @@ export function isSignCommand(argv: any): boolean {
(argv._.length > 1 && SIGN_COMMANDS.includes(argv._[1]))
);
}
export enum CommandType {
WARP_DEPLOY = 'warp:deploy',
WARP_SEND = 'warp:send',
WARP_APPLY = 'warp:apply',
WARP_READ = 'warp:read',
SEND_MESSAGE = 'send:message',
AGENT_KURTOSIS = 'deploy:kurtosis-agents',
STATUS = 'status:',
SUBMIT = 'submit:',
RELAYER = 'relayer:',
}

@ -0,0 +1,70 @@
import { stringify as yamlStringify } from 'yaml';
import { CommandModule } from 'yargs';
import {
createStrategyConfig,
readChainSubmissionStrategyConfig,
} from '../config/strategy.js';
import { CommandModuleWithWriteContext } from '../context/types.js';
import { log, logCommandHeader } from '../logger.js';
import { indentYamlOrJson } from '../utils/files.js';
import { maskSensitiveData } from '../utils/output.js';
import {
DEFAULT_STRATEGY_CONFIG_PATH,
outputFileCommandOption,
strategyCommandOption,
} from './options.js';
/**
* Parent command
*/
export const strategyCommand: CommandModule = {
command: 'strategy',
describe: 'Manage Hyperlane deployment strategies',
builder: (yargs) =>
yargs.command(init).command(read).version(false).demandCommand(),
handler: () => log('Command required'),
};
export const init: CommandModuleWithWriteContext<{
out: string;
}> = {
command: 'init',
describe: 'Creates strategy configuration',
builder: {
out: outputFileCommandOption(DEFAULT_STRATEGY_CONFIG_PATH),
},
handler: async ({ context, out }) => {
logCommandHeader(`Hyperlane Strategy Init`);
await createStrategyConfig({
context,
outPath: out,
});
process.exit(0);
},
};
export const read: CommandModuleWithWriteContext<{
strategy: string;
}> = {
command: 'read',
describe: 'Reads strategy configuration',
builder: {
strategy: {
...strategyCommandOption,
demandOption: true,
default: DEFAULT_STRATEGY_CONFIG_PATH,
},
},
handler: async ({ strategy: strategyUrl }) => {
logCommandHeader(`Hyperlane Strategy Read`);
const strategy = await readChainSubmissionStrategyConfig(strategyUrl);
const maskedConfig = maskSensitiveData(strategy);
log(indentYamlOrJson(yamlStringify(maskedConfig, null, 2), 4));
process.exit(0);
},
};

@ -23,8 +23,8 @@ import {
removeEndingSlash,
writeYamlOrJson,
} from '../utils/files.js';
import { getWarpCoreConfigOrExit } from '../utils/input.js';
import { selectRegistryWarpRoute } from '../utils/tokens.js';
import { getWarpCoreConfigOrExit } from '../utils/warp.js';
import { runVerifyWarpRoute } from '../verify/warp.js';
import {

@ -99,7 +99,7 @@ async function getStartBlocks(
try {
const deployedBlock = await mailbox.deployedBlock();
return deployedBlock.toNumber();
} catch (err) {
} catch {
errorRed(
`❌ Failed to get deployed block to set an index for ${chain}, this is potentially an issue with rpc provider or a misconfiguration`,
);

@ -1,7 +1,7 @@
import { confirm, input } from '@inquirer/prompts';
import { z } from 'zod';
import { ChainMap, MultisigConfig, ZHash } from '@hyperlane-xyz/sdk';
import { ChainMap, MultisigIsmConfig, ZHash } from '@hyperlane-xyz/sdk';
import {
Address,
isValidAddress,
@ -33,7 +33,7 @@ export function readMultisigConfig(filePath: string) {
);
}
const parsedConfig = result.data;
const formattedConfig: ChainMap<MultisigConfig> = objMap(
const formattedConfig: ChainMap<Omit<MultisigIsmConfig, 'type'>> = objMap(
parsedConfig,
(_, config) => {
if (config.threshold > config.validators.length)
@ -50,7 +50,7 @@ export function readMultisigConfig(filePath: string) {
return {
threshold: config.threshold,
validators: validators,
} as MultisigConfig;
};
},
);
logGreen(`All multisig configs in ${filePath} are valid`);

@ -0,0 +1,186 @@
import { confirm, input, password, select } from '@inquirer/prompts';
import { Wallet } from 'ethers';
import { stringify as yamlStringify } from 'yaml';
import {
ChainSubmissionStrategy,
ChainSubmissionStrategySchema,
TxSubmitterType,
} from '@hyperlane-xyz/sdk';
import {
ProtocolType,
assert,
errorToString,
isAddress,
isPrivateKeyEvm,
} from '@hyperlane-xyz/utils';
import { CommandContext } from '../context/types.js';
import { errorRed, log, logBlue, logGreen, logRed } from '../logger.js';
import { runSingleChainSelectionStep } from '../utils/chains.js';
import {
indentYamlOrJson,
isFile,
readYamlOrJson,
writeYamlOrJson,
} from '../utils/files.js';
import { maskSensitiveData } from '../utils/output.js';
/**
* Reads and validates a chain submission strategy configuration from a file
*/
export async function readChainSubmissionStrategyConfig(
filePath: string,
): Promise<ChainSubmissionStrategy> {
log(`Reading submission strategy in ${filePath}`);
try {
const strategyConfig = readYamlOrJson<ChainSubmissionStrategy>(filePath);
const parseResult = ChainSubmissionStrategySchema.parse(strategyConfig);
return parseResult;
} catch (error) {
logRed(` Error reading strategy config:`, errorToString(error));
throw error; // Re-throw to let caller handle the error
}
}
/**
* Safely reads chain submission strategy config, returns empty object if any errors occur
*/
export async function safeReadChainSubmissionStrategyConfig(
filePath: string,
): Promise<ChainSubmissionStrategy> {
try {
const trimmedFilePath = filePath.trim();
if (!isFile(trimmedFilePath)) {
logBlue(`File ${trimmedFilePath} does not exist, returning empty config`);
return {};
}
return await readChainSubmissionStrategyConfig(trimmedFilePath);
} catch (error) {
logRed(
`Failed to read strategy config, defaulting to empty config:`,
errorToString(error),
);
return {};
}
}
export async function createStrategyConfig({
context,
outPath,
}: {
context: CommandContext;
outPath: string;
}) {
let strategy: ChainSubmissionStrategy;
try {
const strategyObj = await readYamlOrJson(outPath);
strategy = ChainSubmissionStrategySchema.parse(strategyObj);
} catch {
strategy = writeYamlOrJson(outPath, {}, 'yaml');
}
const chain = await runSingleChainSelectionStep(context.chainMetadata);
const chainProtocol = context.chainMetadata[chain].protocol;
if (
!context.skipConfirmation &&
strategy &&
Object.prototype.hasOwnProperty.call(strategy, chain)
) {
const isConfirmed = await confirm({
message: `Default strategy for chain ${chain} already exists. Are you sure you want to overwrite existing strategy config?`,
default: false,
});
assert(isConfirmed, 'Strategy initialization cancelled by user.');
}
const isEthereum = chainProtocol === ProtocolType.Ethereum;
const submitterType = isEthereum
? await select({
message: 'Select the submitter type',
choices: Object.values(TxSubmitterType).map((value) => ({
name: value,
value: value,
})),
})
: TxSubmitterType.JSON_RPC; // Do other non-evm chains support gnosis and account impersonation?
const submitter: Record<string, any> = { type: submitterType };
switch (submitterType) {
case TxSubmitterType.JSON_RPC:
submitter.privateKey = await password({
message: 'Enter the private key for JSON-RPC submission:',
validate: (pk) => (isEthereum ? isPrivateKeyEvm(pk) : true),
});
submitter.userAddress = isEthereum
? await new Wallet(submitter.privateKey).getAddress()
: await input({
message: 'Enter the user address for JSON-RPC submission:',
});
submitter.chain = chain;
break;
case TxSubmitterType.IMPERSONATED_ACCOUNT:
submitter.userAddress = await input({
message: 'Enter the user address to impersonate',
validate: (address) =>
isAddress(address) ? true : 'Invalid Ethereum address',
});
assert(
submitter.userAddress,
'User address is required for impersonated account',
);
break;
case TxSubmitterType.GNOSIS_SAFE:
case TxSubmitterType.GNOSIS_TX_BUILDER:
submitter.safeAddress = await input({
message: 'Enter the Safe address',
validate: (address) =>
isAddress(address) ? true : 'Invalid Safe address',
});
submitter.chain = chain;
if (submitterType === TxSubmitterType.GNOSIS_TX_BUILDER) {
submitter.version = await input({
message: 'Enter the Safe version (default: 1.0)',
default: '1.0',
});
}
break;
default:
throw new Error(`Unsupported submitter type: ${submitterType}`);
}
const strategyResult: ChainSubmissionStrategy = {
...strategy,
[chain]: {
submitter: submitter as ChainSubmissionStrategy[string]['submitter'],
},
};
try {
const strategyConfig = ChainSubmissionStrategySchema.parse(strategyResult);
logBlue(`Strategy configuration is valid. Writing to file ${outPath}:\n`);
const maskedConfig = maskSensitiveData(strategyConfig);
log(indentYamlOrJson(yamlStringify(maskedConfig, null, 2), 4));
writeYamlOrJson(outPath, strategyConfig);
logGreen('✅ Successfully created a new strategy configuration.');
} catch {
// don't log error since it may contain sensitive data
errorRed(
`The strategy configuration is invalid. Please review the submitter settings.`,
);
}
}

@ -3,9 +3,8 @@ import { stringify as yamlStringify } from 'yaml';
import {
AnnotatedEV5Transaction,
SubmissionStrategy,
getChainIdFromTxs,
} from '@hyperlane-xyz/sdk';
import { assert, errorToString } from '@hyperlane-xyz/utils';
import { ProtocolType, assert, errorToString } from '@hyperlane-xyz/utils';
import { WriteCommandContext } from '../context/types.js';
import { logGray, logRed } from '../logger.js';
@ -27,17 +26,15 @@ export async function runSubmit({
receiptsFilepath: string;
submissionStrategy: SubmissionStrategy;
}) {
const { chainMetadata, multiProvider } = context;
const { multiProvider } = context;
assert(
submissionStrategy,
'Submission strategy required to submit transactions.\nPlease create a submission strategy. See examples in cli/examples/submit/strategy/*.',
);
const transactions = getTransactions(transactionsFilepath);
const chainId = getChainIdFromTxs(transactions);
const protocol = chainMetadata[chainId].protocol;
const submitterBuilder = await getSubmitterBuilder<typeof protocol>({
const submitterBuilder = await getSubmitterBuilder<ProtocolType>({
submissionStrategy,
multiProvider,
});

@ -21,6 +21,8 @@ import {
promiseObjAll,
} from '@hyperlane-xyz/utils';
import { DEFAULT_STRATEGY_CONFIG_PATH } from '../commands/options.js';
import { MultiProtocolSignerManager } from '../context/strategies/signer/MultiProtocolSignerManager.js';
import { CommandContext } from '../context/types.js';
import { errorRed, log, logBlue, logGreen } from '../logger.js';
import { runMultiChainSelectionStep } from '../utils/chains.js';
@ -35,6 +37,7 @@ import {
} from '../utils/input.js';
import { createAdvancedIsmConfig } from './ism.js';
import { readChainSubmissionStrategyConfig } from './strategy.js';
const TYPE_DESCRIPTIONS: Record<TokenType, string> = {
[TokenType.synthetic]: 'A new ERC20 with remote transfer functionality',
@ -122,13 +125,6 @@ export async function createWarpRouteDeployConfig({
}) {
logBlue('Creating a new warp route deployment config...');
const owner = await detectAndConfirmOrPrompt(
async () => context.signer?.getAddress(),
'Enter the desired',
'owner address',
'signer',
);
const warpChains = await runMultiChainSelectionStep({
chainMetadata: context.chainMetadata,
message: 'Select chains to connect',
@ -138,11 +134,31 @@ export async function createWarpRouteDeployConfig({
requiresConfirmation: !context.skipConfirmation,
});
const strategyConfig = await readChainSubmissionStrategyConfig(
context.strategyPath ?? DEFAULT_STRATEGY_CONFIG_PATH,
);
const multiProtocolSigner = new MultiProtocolSignerManager(
strategyConfig,
warpChains,
context.multiProvider,
{ key: context.key },
);
const multiProviderWithSigners = await multiProtocolSigner.getMultiProvider();
const result: WarpRouteDeployConfig = {};
let typeChoices = TYPE_CHOICES;
for (const chain of warpChains) {
logBlue(`${chain}: Configuring warp route...`);
const owner = await detectAndConfirmOrPrompt(
async () => multiProviderWithSigners.getSigner(chain).getAddress(),
'Enter the desired',
'owner address',
'signer',
);
// default to the mailbox from the registry and if not found ask to the user to submit one
const chainAddresses = await context.registry.getChainAddresses(chain);

@ -16,14 +16,18 @@ import {
} from '@hyperlane-xyz/sdk';
import { isHttpsUrl, isNullish, rootLogger } from '@hyperlane-xyz/utils';
import { DEFAULT_STRATEGY_CONFIG_PATH } from '../commands/options.js';
import { isSignCommand } from '../commands/signCommands.js';
import { safeReadChainSubmissionStrategyConfig } from '../config/strategy.js';
import { PROXY_DEPLOYED_URL } from '../consts.js';
import { forkNetworkToMultiProvider, verifyAnvil } from '../deploy/dry-run.js';
import { logBlue } from '../logger.js';
import { runSingleChainSelectionStep } from '../utils/chains.js';
import { detectAndConfirmOrPrompt } from '../utils/input.js';
import { getImpersonatedSigner, getSigner } from '../utils/keys.js';
import { getImpersonatedSigner } from '../utils/keys.js';
import { ChainResolverFactory } from './strategies/chain/ChainResolverFactory.js';
import { MultiProtocolSignerManager } from './strategies/signer/MultiProtocolSignerManager.js';
import {
CommandContext,
ContextSettings,
@ -41,6 +45,7 @@ export async function contextMiddleware(argv: Record<string, any>) {
requiresKey,
disableProxy: argv.disableProxy,
skipConfirmation: argv.yes,
strategyPath: argv.strategy,
};
if (!isDryRun && settings.fromAddress)
throw new Error(
@ -52,6 +57,44 @@ export async function contextMiddleware(argv: Record<string, any>) {
argv.context = context;
}
export async function signerMiddleware(argv: Record<string, any>) {
const { key, requiresKey, multiProvider, strategyPath } = argv.context;
if (!requiresKey && !key) return argv;
const strategyConfig = await safeReadChainSubmissionStrategyConfig(
strategyPath ?? DEFAULT_STRATEGY_CONFIG_PATH,
);
/**
* Intercepts Hyperlane command to determine chains.
*/
const chainStrategy = ChainResolverFactory.getStrategy(argv);
/**
* Resolves chains based on the chain strategy.
*/
const chains = await chainStrategy.resolveChains(argv);
/**
* Extracts signer config
*/
const multiProtocolSigner = new MultiProtocolSignerManager(
strategyConfig,
chains,
multiProvider,
{ key },
);
/**
* @notice Attaches signers to MultiProvider and assigns it to argv.multiProvider
*/
argv.multiProvider = await multiProtocolSigner.getMultiProvider();
argv.multiProtocolSigner = multiProtocolSigner;
return argv;
}
/**
* Retrieves context for the user-selected command
* @returns context for the current command
@ -66,18 +109,14 @@ export async function getContext({
}: ContextSettings): Promise<CommandContext> {
const registry = getRegistry(registryUri, registryOverrideUri, !disableProxy);
let signer: ethers.Wallet | undefined = undefined;
if (key || requiresKey) {
({ key, signer } = await getSigner({ key, skipConfirmation }));
}
const multiProvider = await getMultiProvider(registry, signer);
const multiProvider = await getMultiProvider(registry);
return {
registry,
requiresKey,
chainMetadata: multiProvider.metadata,
multiProvider,
key,
signer,
skipConfirmation: !!skipConfirmation,
} as CommandContext;
}

@ -0,0 +1,34 @@
import { CommandType } from '../../../commands/signCommands.js';
import { MultiChainResolver } from './MultiChainResolver.js';
import { SingleChainResolver } from './SingleChainResolver.js';
import { ChainResolver } from './types.js';
/**
* @class ChainResolverFactory
* @description Intercepts commands to determine the appropriate chain resolver strategy based on command type.
*/
export class ChainResolverFactory {
private static strategyMap: Map<CommandType, () => ChainResolver> = new Map([
[CommandType.WARP_DEPLOY, () => MultiChainResolver.forWarpRouteConfig()],
[CommandType.WARP_SEND, () => MultiChainResolver.forOriginDestination()],
[CommandType.WARP_APPLY, () => MultiChainResolver.forWarpRouteConfig()],
[CommandType.WARP_READ, () => MultiChainResolver.forWarpCoreConfig()],
[CommandType.SEND_MESSAGE, () => MultiChainResolver.forOriginDestination()],
[CommandType.AGENT_KURTOSIS, () => MultiChainResolver.forAgentKurtosis()],
[CommandType.STATUS, () => MultiChainResolver.forOriginDestination()],
[CommandType.SUBMIT, () => MultiChainResolver.forStrategyConfig()],
[CommandType.RELAYER, () => MultiChainResolver.forRelayer()],
]);
/**
* @param argv - Command line arguments.
* @returns ChainResolver - The appropriate chain resolver strategy based on the command type.
*/
static getStrategy(argv: Record<string, any>): ChainResolver {
const commandKey = `${argv._[0]}:${argv._[1] || ''}`.trim() as CommandType;
const createStrategy =
this.strategyMap.get(commandKey) || (() => new SingleChainResolver());
return createStrategy();
}
}

@ -0,0 +1,200 @@
import { ChainMap, ChainName } from '@hyperlane-xyz/sdk';
import { assert } from '@hyperlane-xyz/utils';
import { DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH } from '../../../commands/options.js';
import { readChainSubmissionStrategyConfig } from '../../../config/strategy.js';
import { logRed } from '../../../logger.js';
import {
extractChainsFromObj,
runMultiChainSelectionStep,
runSingleChainSelectionStep,
} from '../../../utils/chains.js';
import {
isFile,
readYamlOrJson,
runFileSelectionStep,
} from '../../../utils/files.js';
import { getWarpCoreConfigOrExit } from '../../../utils/warp.js';
import { ChainResolver } from './types.js';
enum ChainSelectionMode {
ORIGIN_DESTINATION,
AGENT_KURTOSIS,
WARP_CONFIG,
WARP_READ,
STRATEGY,
RELAYER,
}
// This class could be broken down into multiple strategies
/**
* @title MultiChainResolver
* @notice Resolves chains based on the specified selection mode.
*/
export class MultiChainResolver implements ChainResolver {
constructor(private mode: ChainSelectionMode) {}
async resolveChains(argv: ChainMap<any>): Promise<ChainName[]> {
switch (this.mode) {
case ChainSelectionMode.WARP_CONFIG:
return this.resolveWarpRouteConfigChains(argv);
case ChainSelectionMode.WARP_READ:
return this.resolveWarpCoreConfigChains(argv);
case ChainSelectionMode.AGENT_KURTOSIS:
return this.resolveAgentChains(argv);
case ChainSelectionMode.STRATEGY:
return this.resolveStrategyChains(argv);
case ChainSelectionMode.RELAYER:
return this.resolveRelayerChains(argv);
case ChainSelectionMode.ORIGIN_DESTINATION:
default:
return this.resolveOriginDestinationChains(argv);
}
}
private async resolveWarpRouteConfigChains(
argv: Record<string, any>,
): Promise<ChainName[]> {
argv.config ||= DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH;
argv.context.chains = await this.getWarpRouteConfigChains(
argv.config.trim(),
argv.skipConfirmation,
);
return argv.context.chains;
}
private async resolveWarpCoreConfigChains(
argv: Record<string, any>,
): Promise<ChainName[]> {
if (argv.symbol || argv.warp) {
const warpCoreConfig = await getWarpCoreConfigOrExit({
context: argv.context,
warp: argv.warp,
symbol: argv.symbol,
});
argv.context.warpCoreConfig = warpCoreConfig;
const chains = extractChainsFromObj(warpCoreConfig);
return chains;
} else if (argv.chain) {
return [argv.chain];
} else {
throw new Error(
`Please specify either a symbol, chain and address or warp file`,
);
}
}
private async resolveAgentChains(
argv: Record<string, any>,
): Promise<ChainName[]> {
const { chainMetadata } = argv.context;
argv.origin =
argv.origin ??
(await runSingleChainSelectionStep(
chainMetadata,
'Select the origin chain',
));
if (!argv.targets) {
const selectedRelayChains = await runMultiChainSelectionStep({
chainMetadata: chainMetadata,
message: 'Select chains to relay between',
requireNumber: 2,
});
argv.targets = selectedRelayChains.join(',');
}
return [argv.origin, ...argv.targets];
}
private async resolveOriginDestinationChains(
argv: Record<string, any>,
): Promise<ChainName[]> {
const { chainMetadata } = argv.context;
argv.origin =
argv.origin ??
(await runSingleChainSelectionStep(
chainMetadata,
'Select the origin chain',
));
argv.destination =
argv.destination ??
(await runSingleChainSelectionStep(
chainMetadata,
'Select the destination chain',
));
return [argv.origin, argv.destination];
}
private async resolveStrategyChains(
argv: Record<string, any>,
): Promise<ChainName[]> {
const strategy = await readChainSubmissionStrategyConfig(argv.strategy);
return extractChainsFromObj(strategy);
}
private async resolveRelayerChains(
argv: Record<string, any>,
): Promise<ChainName[]> {
return argv.chains.split(',').map((item: string) => item.trim());
}
private async getWarpRouteConfigChains(
configPath: string,
skipConfirmation: boolean,
): Promise<ChainName[]> {
if (!configPath || !isFile(configPath)) {
assert(!skipConfirmation, 'Warp route deployment config is required');
configPath = await runFileSelectionStep(
'./configs',
'Warp route deployment config',
'warp',
);
} else {
logRed(`Using warp route deployment config at ${configPath}`);
}
// Alternative to readWarpRouteDeployConfig that doesn't use context for signer and zod validation
const warpRouteConfig = (await readYamlOrJson(configPath)) as Record<
string,
any
>;
const chains = Object.keys(warpRouteConfig) as ChainName[];
assert(
chains.length !== 0,
'No chains found in warp route deployment config',
);
return chains;
}
static forAgentKurtosis(): MultiChainResolver {
return new MultiChainResolver(ChainSelectionMode.AGENT_KURTOSIS);
}
static forOriginDestination(): MultiChainResolver {
return new MultiChainResolver(ChainSelectionMode.ORIGIN_DESTINATION);
}
static forRelayer(): MultiChainResolver {
return new MultiChainResolver(ChainSelectionMode.RELAYER);
}
static forStrategyConfig(): MultiChainResolver {
return new MultiChainResolver(ChainSelectionMode.STRATEGY);
}
static forWarpRouteConfig(): MultiChainResolver {
return new MultiChainResolver(ChainSelectionMode.WARP_CONFIG);
}
static forWarpCoreConfig(): MultiChainResolver {
return new MultiChainResolver(ChainSelectionMode.WARP_READ);
}
}

@ -0,0 +1,25 @@
import { ChainMap, ChainName } from '@hyperlane-xyz/sdk';
import { runSingleChainSelectionStep } from '../../../utils/chains.js';
import { ChainResolver } from './types.js';
/**
* @title SingleChainResolver
* @notice Strategy implementation for managing single-chain operations
* @dev Primarily used for operations like 'core:apply' and 'warp:read'
*/
export class SingleChainResolver implements ChainResolver {
/**
* @notice Determines the chain to be used for signing operations
* @dev Either uses the chain specified in argv or prompts for interactive selection
*/
async resolveChains(argv: ChainMap<any>): Promise<ChainName[]> {
argv.chain ||= await runSingleChainSelectionStep(
argv.context.chainMetadata,
'Select chain to connect:',
);
return [argv.chain]; // Explicitly return as single-item array
}
}

@ -0,0 +1,10 @@
import { ChainMap, ChainName } from '@hyperlane-xyz/sdk';
export interface ChainResolver {
/**
* Determines the chains to be used for signing
* @param argv Command arguments
* @returns Array of chain names
*/
resolveChains(argv: ChainMap<any>): Promise<ChainName[]>;
}

@ -0,0 +1,22 @@
import { Signer } from 'ethers';
import { ChainName, ChainSubmissionStrategy } from '@hyperlane-xyz/sdk';
import { Address } from '@hyperlane-xyz/utils';
export interface SignerConfig {
privateKey: string;
address?: Address; // For chains like StarkNet that require address
extraParams?: Record<string, any>; // For any additional chain-specific params
}
export interface IMultiProtocolSigner {
getSignerConfig(chain: ChainName): Promise<SignerConfig> | SignerConfig;
getSigner(config: SignerConfig): Signer;
}
export abstract class BaseMultiProtocolSigner implements IMultiProtocolSigner {
constructor(protected config: ChainSubmissionStrategy) {}
abstract getSignerConfig(chain: ChainName): Promise<SignerConfig>;
abstract getSigner(config: SignerConfig): Signer;
}

@ -0,0 +1,79 @@
import { password } from '@inquirer/prompts';
import { Signer, Wallet } from 'ethers';
import {
ChainName,
ChainSubmissionStrategy,
ChainTechnicalStack,
MultiProvider,
TxSubmitterType,
} from '@hyperlane-xyz/sdk';
import { ProtocolType } from '@hyperlane-xyz/utils';
import {
BaseMultiProtocolSigner,
IMultiProtocolSigner,
SignerConfig,
} from './BaseMultiProtocolSigner.js';
export class MultiProtocolSignerFactory {
static getSignerStrategy(
chain: ChainName,
strategyConfig: ChainSubmissionStrategy,
multiProvider: MultiProvider,
): IMultiProtocolSigner {
const { protocol, technicalStack } = multiProvider.getChainMetadata(chain);
switch (protocol) {
case ProtocolType.Ethereum:
if (technicalStack === ChainTechnicalStack.ZkSync)
return new ZKSyncSignerStrategy(strategyConfig);
return new EthereumSignerStrategy(strategyConfig);
default:
throw new Error(`Unsupported protocol: ${protocol}`);
}
}
}
class EthereumSignerStrategy extends BaseMultiProtocolSigner {
async getSignerConfig(chain: ChainName): Promise<SignerConfig> {
const submitter = this.config[chain]?.submitter as {
type: TxSubmitterType.JSON_RPC;
privateKey?: string;
};
const privateKey =
submitter?.privateKey ??
(await password({
message: `Please enter the private key for chain ${chain}`,
}));
return { privateKey };
}
getSigner(config: SignerConfig): Signer {
return new Wallet(config.privateKey);
}
}
// 99% overlap with EthereumSignerStrategy for the sake of keeping MultiProtocolSignerFactory clean
// TODO: import ZKSync signer
class ZKSyncSignerStrategy extends BaseMultiProtocolSigner {
async getSignerConfig(chain: ChainName): Promise<SignerConfig> {
const submitter = this.config[chain]?.submitter as {
privateKey?: string;
};
const privateKey =
submitter?.privateKey ??
(await password({
message: `Please enter the private key for chain ${chain}`,
}));
return { privateKey };
}
getSigner(config: SignerConfig): Signer {
return new Wallet(config.privateKey);
}
}

@ -0,0 +1,153 @@
import { Signer } from 'ethers';
import { Logger } from 'pino';
import {
ChainName,
ChainSubmissionStrategy,
MultiProvider,
} from '@hyperlane-xyz/sdk';
import { assert, rootLogger } from '@hyperlane-xyz/utils';
import { ENV } from '../../../utils/env.js';
import { IMultiProtocolSigner } from './BaseMultiProtocolSigner.js';
import { MultiProtocolSignerFactory } from './MultiProtocolSignerFactory.js';
export interface MultiProtocolSignerOptions {
logger?: Logger;
key?: string;
}
/**
* @title MultiProtocolSignerManager
* @dev Context manager for signers across multiple protocols
*/
export class MultiProtocolSignerManager {
protected readonly signerStrategies: Map<ChainName, IMultiProtocolSigner>;
protected readonly signers: Map<ChainName, Signer>;
public readonly logger: Logger;
constructor(
protected readonly submissionStrategy: ChainSubmissionStrategy,
protected readonly chains: ChainName[],
protected readonly multiProvider: MultiProvider,
protected readonly options: MultiProtocolSignerOptions = {},
) {
this.logger =
options?.logger ||
rootLogger.child({
module: 'MultiProtocolSignerManager',
});
this.signerStrategies = new Map();
this.signers = new Map();
this.initializeStrategies();
}
/**
* @notice Sets up chain-specific signer strategies
*/
protected initializeStrategies(): void {
for (const chain of this.chains) {
const strategy = MultiProtocolSignerFactory.getSignerStrategy(
chain,
this.submissionStrategy,
this.multiProvider,
);
this.signerStrategies.set(chain, strategy);
}
}
/**
* @dev Configures signers for EVM chains in MultiProvider
*/
async getMultiProvider(): Promise<MultiProvider> {
for (const chain of this.chains) {
const signer = await this.initSigner(chain);
this.multiProvider.setSigner(chain, signer);
}
return this.multiProvider;
}
/**
* @notice Creates signer for specific chain
*/
async initSigner(chain: ChainName): Promise<Signer> {
const { privateKey } = await this.resolveConfig(chain);
const signerStrategy = this.signerStrategies.get(chain);
assert(signerStrategy, `No signer strategy found for chain ${chain}`);
return signerStrategy.getSigner({ privateKey });
}
/**
* @notice Creates signers for all chains
*/
async initAllSigners(): Promise<typeof this.signers> {
const signerConfigs = await this.resolveAllConfigs();
for (const { chain, privateKey } of signerConfigs) {
const signerStrategy = this.signerStrategies.get(chain);
if (signerStrategy) {
this.signers.set(chain, signerStrategy.getSigner({ privateKey }));
}
}
return this.signers;
}
/**
* @notice Resolves all chain configurations
*/
private async resolveAllConfigs(): Promise<
Array<{ chain: ChainName; privateKey: string }>
> {
return Promise.all(this.chains.map((chain) => this.resolveConfig(chain)));
}
/**
* @notice Resolves single chain configuration
*/
private async resolveConfig(
chain: ChainName,
): Promise<{ chain: ChainName; privateKey: string }> {
const signerStrategy = this.signerStrategies.get(chain);
assert(signerStrategy, `No signer strategy found for chain ${chain}`);
let privateKey: string;
if (this.options.key) {
this.logger.info(
`Using private key passed via CLI --key flag for chain ${chain}`,
);
privateKey = this.options.key;
} else if (ENV.HYP_KEY) {
this.logger.info(`Using private key from .env for chain ${chain}`);
privateKey = ENV.HYP_KEY;
} else {
privateKey = await this.extractPrivateKey(chain, signerStrategy);
}
return { chain, privateKey };
}
/**
* @notice Gets private key from strategy
*/
private async extractPrivateKey(
chain: ChainName,
signerStrategy: IMultiProtocolSigner,
): Promise<string> {
const strategyConfig = await signerStrategy.getSignerConfig(chain);
assert(
strategyConfig.privateKey,
`No private key found for chain ${chain}`,
);
this.logger.info(
`Extracting private key from strategy config/user prompt for chain ${chain}`,
);
return strategyConfig.privateKey;
}
}

@ -6,6 +6,7 @@ import type {
ChainMap,
ChainMetadata,
MultiProvider,
WarpCoreConfig,
} from '@hyperlane-xyz/sdk';
export interface ContextSettings {
@ -16,6 +17,7 @@ export interface ContextSettings {
requiresKey?: boolean;
disableProxy?: boolean;
skipConfirmation?: boolean;
strategyPath?: string;
}
export interface CommandContext {
@ -25,6 +27,8 @@ export interface CommandContext {
skipConfirmation: boolean;
key?: string;
signer?: ethers.Signer;
warpCoreConfig?: WarpCoreConfig;
strategyPath?: string;
}
export interface WriteCommandContext extends CommandContext {

@ -21,6 +21,7 @@ export async function runKurtosisAgentDeploy({
relayChains?: string;
agentConfigurationPath?: string;
}) {
// Future works: decide what to do with this, since its handled in MultiChainResolver - AGENT_KURTOSIS mode
if (!originChain) {
originChain = await runSingleChainSelectionStep(
context.chainMetadata,

@ -1,12 +1,12 @@
import { stringify as yamlStringify } from 'yaml';
import { buildArtifact as coreBuildArtifact } from '@hyperlane-xyz/core/buildArtifact.js';
import { DeployedCoreAddresses } from '@hyperlane-xyz/sdk';
import {
ChainMap,
ChainName,
ContractVerifier,
CoreConfig,
DeployedCoreAddresses,
EvmCoreModule,
ExplorerLicenseType,
} from '@hyperlane-xyz/sdk';
@ -43,7 +43,6 @@ export async function runCoreDeploy(params: DeployParams) {
let chain = params.chain;
const {
signer,
isDryRun,
chainMetadata,
dryRunChain,
@ -62,13 +61,14 @@ export async function runCoreDeploy(params: DeployParams) {
'Select chain to connect:',
);
}
let apiKeys: ChainMap<string> = {};
if (!skipConfirmation)
apiKeys = await requestAndSaveApiKeys([chain], chainMetadata, registry);
const signer = multiProvider.getSigner(chain);
const deploymentParams: DeployParams = {
context,
context: { ...context, signer },
chain,
config,
};

@ -5,12 +5,11 @@ import {
resetFork,
setFork,
} from '@hyperlane-xyz/sdk';
import { toUpperCamelCase } from '@hyperlane-xyz/utils';
import { logGray, logGreen, warnYellow } from '../logger.js';
import { ENV } from '../utils/env.js';
import { toUpperCamelCase } from './utils.js';
/**
* Forks a provided network onto MultiProvider
* @param multiProvider the MultiProvider to be prepared

@ -41,7 +41,7 @@ export async function runPreflightChecksForChains({
chainsToGasCheck?: ChainName[];
}) {
log('Running pre-flight checks for chains...');
const { signer, multiProvider } = context;
const { multiProvider } = context;
if (!chains?.length) throw new Error('Empty chain selection');
for (const chain of chains) {
@ -49,15 +49,14 @@ export async function runPreflightChecksForChains({
if (!metadata) throw new Error(`No chain config found for ${chain}`);
if (metadata.protocol !== ProtocolType.Ethereum)
throw new Error('Only Ethereum chains are supported for now');
const signer = multiProvider.getSigner(chain);
assertSigner(signer);
logGreen(`${chain} signer is valid`);
}
logGreen('✅ Chains are valid');
assertSigner(signer);
logGreen('✅ Signer is valid');
await nativeBalancesAreSufficient(
multiProvider,
signer,
chainsToGasCheck ?? chains,
minGas,
);
@ -70,8 +69,13 @@ export async function runDeployPlanStep({
context: WriteCommandContext;
chain: ChainName;
}) {
const { signer, chainMetadata: chainMetadataMap, skipConfirmation } = context;
const address = await signer.getAddress();
const {
chainMetadata: chainMetadataMap,
multiProvider,
skipConfirmation,
} = context;
const address = await multiProvider.getSigner(chain).getAddress();
logBlue('\nDeployment plan');
logGray('===============');
@ -124,7 +128,7 @@ export function isZODISMConfig(filepath: string): boolean {
export async function prepareDeploy(
context: WriteCommandContext,
userAddress: Address,
userAddress: Address | null,
chains: ChainName[],
): Promise<Record<string, BigNumber>> {
const { multiProvider, isDryRun } = context;
@ -134,7 +138,9 @@ export async function prepareDeploy(
const provider = isDryRun
? getLocalProvider(ENV.ANVIL_IP_ADDR, ENV.ANVIL_PORT)
: multiProvider.getProvider(chain);
const currentBalance = await provider.getBalance(userAddress);
const address =
userAddress ?? (await multiProvider.getSigner(chain).getAddress());
const currentBalance = await provider.getBalance(address);
initialBalances[chain] = currentBalance;
}),
);
@ -145,7 +151,7 @@ export async function completeDeploy(
context: WriteCommandContext,
command: string,
initialBalances: Record<string, BigNumber>,
userAddress: Address,
userAddress: Address | null,
chains: ChainName[],
) {
const { multiProvider, isDryRun } = context;
@ -154,7 +160,9 @@ export async function completeDeploy(
const provider = isDryRun
? getLocalProvider(ENV.ANVIL_IP_ADDR, ENV.ANVIL_PORT)
: multiProvider.getProvider(chain);
const currentBalance = await provider.getBalance(userAddress);
const address =
userAddress ?? (await multiProvider.getSigner(chain).getAddress());
const currentBalance = await provider.getBalance(address);
const balanceDelta = initialBalances[chain].sub(currentBalance);
if (isDryRun && balanceDelta.lt(0)) break;
logPink(
@ -169,10 +177,6 @@ export async function completeDeploy(
if (isDryRun) await completeDryRun(command);
}
export function toUpperCamelCase(string: string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function transformChainMetadataForDisplay(chainMetadata: ChainMetadata) {
return {
Name: chainMetadata.name,

@ -100,7 +100,7 @@ export async function runWarpRouteDeploy({
context: WriteCommandContext;
warpRouteDeploymentConfigPath?: string;
}) {
const { signer, skipConfirmation, chainMetadata, registry } = context;
const { skipConfirmation, chainMetadata, registry } = context;
if (
!warpRouteDeploymentConfigPath ||
@ -136,15 +136,18 @@ export async function runWarpRouteDeploy({
await runDeployPlanStep(deploymentParams);
// Some of the below functions throw if passed non-EVM chains
const ethereumChains = chains.filter(
(chain) => chainMetadata[chain].protocol === ProtocolType.Ethereum,
);
await runPreflightChecksForChains({
context,
chains,
chains: ethereumChains,
minGas: MINIMUM_WARP_DEPLOY_GAS,
});
const userAddress = await signer.getAddress();
const initialBalances = await prepareDeploy(context, userAddress, chains);
const initialBalances = await prepareDeploy(context, null, ethereumChains);
const deployedContracts = await executeDeploy(deploymentParams, apiKeys);
@ -155,7 +158,7 @@ export async function runWarpRouteDeploy({
await writeDeploymentArtifacts(warpCoreConfig, context);
await completeDeploy(context, 'warp', initialBalances, userAddress, chains);
await completeDeploy(context, 'warp', initialBalances, null, ethereumChains!);
}
async function runDeployPlanStep({ context, warpDeployConfig }: DeployParams) {
@ -534,7 +537,8 @@ async function updateExistingWarpRoute(
) {
logBlue('Updating deployed Warp Routes');
const { multiProvider, registry } = params.context;
const addresses = await registry.getAddresses();
const registryAddresses =
(await registry.getAddresses()) as ChainMap<ProxyFactoryFactoriesAddresses>;
const contractVerifier = new ContractVerifier(
multiProvider,
apiKeys,
@ -553,15 +557,13 @@ async function updateExistingWarpRoute(
`Missing artifacts for ${chain}. Probably new deployment. Skipping update...`,
);
config.ismFactoryAddresses = addresses[
chain
] as ProxyFactoryFactoriesAddresses;
const evmERC20WarpModule = new EvmERC20WarpModule(
multiProvider,
{
config,
chain,
addresses: {
...registryAddresses[chain],
deployedTokenRoute: deployedConfig.addressOrDenom!,
},
},
@ -646,7 +648,9 @@ async function enrollRemoteRouters(
deployedContractsMap: HyperlaneContractsMap<HypERC20Factories>,
): Promise<AnnotatedEV5Transaction[]> {
logBlue(`Enrolling deployed routers with each other...`);
const { multiProvider } = params.context;
const { multiProvider, registry } = params.context;
const registryAddresses =
(await registry.getAddresses()) as ChainMap<ProxyFactoryFactoriesAddresses>;
const deployedRoutersAddresses: ChainMap<Address> = objMap(
deployedContractsMap,
(_, contracts) => getRouter(contracts).address,
@ -674,7 +678,10 @@ async function enrollRemoteRouters(
const evmERC20WarpModule = new EvmERC20WarpModule(multiProvider, {
config: mutatedWarpRouteConfig,
chain,
addresses: { deployedTokenRoute: router.address },
addresses: {
...registryAddresses[chain],
deployedTokenRoute: router.address,
},
});
const otherChains = multiProvider
@ -937,7 +944,7 @@ async function getWarpApplySubmitter({
context: WriteCommandContext;
strategyUrl?: string;
}): Promise<TxSubmitterBuilder<ProtocolType>> {
const { chainMetadata, multiProvider } = context;
const { multiProvider } = context;
const submissionStrategy: SubmissionStrategy = strategyUrl
? readChainSubmissionStrategy(strategyUrl)[chain]
@ -948,8 +955,7 @@ async function getWarpApplySubmitter({
},
};
const protocol = chainMetadata[chain].protocol;
return getSubmitterBuilder<typeof protocol>({
return getSubmitterBuilder<ProtocolType>({
submissionStrategy,
multiProvider,
});

@ -15,7 +15,7 @@ import { isAddressEvm, objMap, promiseObjAll } from '@hyperlane-xyz/utils';
import { CommandContext } from '../context/types.js';
import { logGray, logRed, logTable } from '../logger.js';
import { getWarpCoreConfigOrExit } from '../utils/input.js';
import { getWarpCoreConfigOrExit } from '../utils/warp.js';
export async function runWarpRouteRead({
context,
@ -34,11 +34,13 @@ export async function runWarpRouteRead({
let addresses: ChainMap<string>;
if (symbol || warp) {
const warpCoreConfig = await getWarpCoreConfigOrExit({
context,
warp,
symbol,
});
const warpCoreConfig =
context.warpCoreConfig ?? // this case is be handled by MultiChainHandler.forWarpCoreConfig() interceptor
(await getWarpCoreConfigOrExit({
context,
warp,
symbol,
}));
// TODO: merge with XERC20TokenAdapter and WarpRouteReader
const xerc20Limits = await Promise.all(

@ -40,8 +40,8 @@ export async function sendTestTransfer({
}: {
context: WriteCommandContext;
warpCoreConfig: WarpCoreConfig;
origin?: ChainName;
destination?: ChainName;
origin?: ChainName; // resolved in signerMiddleware
destination?: ChainName; // resolved in signerMiddleware
amount: string;
recipient?: string;
timeoutSec: number;
@ -106,10 +106,15 @@ async function executeDelivery({
skipWaitForDelivery: boolean;
selfRelay?: boolean;
}) {
const { signer, multiProvider, registry } = context;
const { multiProvider, registry } = context;
const signer = multiProvider.getSigner(origin);
const recipientSigner = multiProvider.getSigner(destination);
const recipientAddress = await recipientSigner.getAddress();
const signerAddress = await signer.getAddress();
recipient ||= signerAddress;
recipient ||= recipientAddress;
const chainAddresses = await registry.getAddresses();
@ -136,12 +141,11 @@ async function executeDelivery({
token = warpCore.findToken(origin, routerAddress)!;
}
const senderAddress = await signer.getAddress();
const errors = await warpCore.validateTransfer({
originTokenAmount: token.amount(amount),
destination,
recipient: recipient ?? senderAddress,
sender: senderAddress,
recipient,
sender: signerAddress,
});
if (errors) {
logRed('Error validating transfer', JSON.stringify(errors));
@ -152,8 +156,8 @@ async function executeDelivery({
const transferTxs = await warpCore.getTransferRemoteTxs({
originTokenAmount: new TokenAmount(amount, token),
destination,
sender: senderAddress,
recipient: recipient ?? senderAddress,
sender: signerAddress,
recipient,
});
const txReceipts = [];
@ -172,7 +176,7 @@ async function executeDelivery({
const parsed = parseWarpRouteMessage(message.parsed.body);
logBlue(
`Sent transfer from sender (${senderAddress}) on ${origin} to recipient (${recipient}) on ${destination}.`,
`Sent transfer from sender (${signerAddress}) on ${origin} to recipient (${recipient}) on ${destination}.`,
);
logBlue(`Message ID: ${message.id}`);
log(`Message:\n${indentYamlOrJson(yamlStringify(message, null, 2), 4)}`);

@ -52,7 +52,7 @@ export async function checkMessageStatus({
} else {
try {
dispatchedReceipt = await core.getDispatchTx(origin, messageId);
} catch (e) {
} catch {
logRed(`Failed to infer dispatch transaction for message ${messageId}`);
dispatchTx = await input({

@ -1,3 +1,4 @@
import { ethers } from 'ethers';
import { $ } from 'zx';
import { ERC20Test__factory, ERC4626Test__factory } from '@hyperlane-xyz/core';
@ -142,6 +143,9 @@ export async function deployToken(privateKey: string, chain: string) {
key: privateKey,
});
// Future works: make signer compatible with protocol/chain stack
multiProvider.setSigner(chain, new ethers.Wallet(privateKey));
const token = await new ERC20Test__factory(
multiProvider.getSigner(chain),
).deploy('token', 'token', '100000000000000000000', 18);
@ -161,6 +165,9 @@ export async function deploy4626Vault(
key: privateKey,
});
// Future works: make signer compatible with protocol/chain stack
multiProvider.setSigner(chain, new ethers.Wallet(privateKey));
const vault = await new ERC4626Test__factory(
multiProvider.getSigner(chain),
).deploy(tokenAddress, 'VAULT', 'VAULT');

@ -2,19 +2,23 @@ import { confirm } from '@inquirer/prompts';
import { ethers } from 'ethers';
import { ChainName, MultiProvider } from '@hyperlane-xyz/sdk';
import { ProtocolType } from '@hyperlane-xyz/utils';
import { logGreen, logRed } from '../logger.js';
import { logGray, logGreen, logRed } from '../logger.js';
export async function nativeBalancesAreSufficient(
multiProvider: MultiProvider,
signer: ethers.Signer,
chains: ChainName[],
minGas: string,
) {
const address = await signer.getAddress();
const sufficientBalances: boolean[] = [];
for (const chain of chains) {
// Only Ethereum chains are supported
if (multiProvider.getProtocol(chain) !== ProtocolType.Ethereum) {
logGray(`Skipping balance check for non-EVM chain: ${chain}`);
continue;
}
const address = multiProvider.getSigner(chain).getAddress();
const provider = multiProvider.getProvider(chain);
const gasPrice = await provider.getGasPrice();
const minBalanceWei = gasPrice.mul(minGas).toString();

@ -171,3 +171,36 @@ function handleNewChain(chainNames: string[]) {
process.exit(0);
}
}
/**
* @notice Extracts chain names from a nested configuration object
* @param config Object to search for chain names
* @return Array of discovered chain names
*/
export function extractChainsFromObj(config: Record<string, any>): string[] {
const chains: string[] = [];
// Recursively search for chain/chainName fields
function findChainFields(obj: any) {
if (obj === null || typeof obj !== 'object') return;
if (Array.isArray(obj)) {
obj.forEach((item) => findChainFields(item));
return;
}
if ('chain' in obj) {
chains.push(obj.chain);
}
if ('chainName' in obj) {
chains.push(obj.chainName);
}
// Recursively search in all nested values
Object.values(obj).forEach((value) => findChainFields(value));
}
findChainFields(config);
return chains;
}

@ -1,4 +1,4 @@
import z from 'zod';
import { z } from 'zod';
const envScheme = z.object({
HYP_KEY: z.string().optional(),

@ -42,7 +42,7 @@ export function isFile(filepath: string) {
if (!filepath) return false;
try {
return fs.existsSync(filepath) && fs.lstatSync(filepath).isFile();
} catch (error) {
} catch {
log(`Error checking for file: ${filepath}`);
return false;
}
@ -70,7 +70,7 @@ export function readJson<T>(filepath: string): T {
export function tryReadJson<T>(filepath: string): T | null {
try {
return readJson(filepath) as T;
} catch (error) {
} catch {
return null;
}
}
@ -98,7 +98,7 @@ export function readYaml<T>(filepath: string): T {
export function tryReadYamlAtPath<T>(filepath: string): T | null {
try {
return readYaml(filepath);
} catch (error) {
} catch {
return null;
}
}

@ -14,24 +14,18 @@ import {
} from '@inquirer/core';
import figures from '@inquirer/figures';
import { KeypressEvent, confirm, input, isSpaceKey } from '@inquirer/prompts';
import type { PartialDeep } from '@inquirer/type';
import type { PartialDeep, Prompt } from '@inquirer/type';
import ansiEscapes from 'ansi-escapes';
import chalk from 'chalk';
import { ProxyAdmin__factory } from '@hyperlane-xyz/core';
import {
ChainName,
DeployedOwnableConfig,
WarpCoreConfig,
} from '@hyperlane-xyz/sdk';
import { ChainName, DeployedOwnableConfig } from '@hyperlane-xyz/sdk';
import { Address, isAddress, rootLogger } from '@hyperlane-xyz/utils';
import { readWarpCoreConfig } from '../config/warp.js';
import { CommandContext } from '../context/types.js';
import { logGray, logRed } from '../logger.js';
import { logGray } from '../logger.js';
import { indentYamlOrJson } from './files.js';
import { selectRegistryWarpRoute } from './tokens.js';
export async function detectAndConfirmOrPrompt(
detect: () => Promise<string | undefined>,
@ -52,8 +46,9 @@ export async function detectAndConfirmOrPrompt(
return detectedValue;
}
}
// eslint-disable-next-line no-empty
} catch (e) {}
} catch {
// Fallback to input prompt
}
return input({ message: `${prompt} ${label}:`, default: detectedValue });
}
@ -136,34 +131,6 @@ export async function setProxyAdminConfig(
}
}
/**
* Gets a {@link WarpCoreConfig} based on the provided path or prompts the user to choose one:
* - if `symbol` is provided the user will have to select one of the available warp routes.
* - if `warp` is provided the config will be read by the provided file path.
* - if none is provided the CLI will exit.
*/
export async function getWarpCoreConfigOrExit({
context,
symbol,
warp,
}: {
context: CommandContext;
symbol?: string;
warp?: string;
}): Promise<WarpCoreConfig> {
let warpCoreConfig: WarpCoreConfig;
if (symbol) {
warpCoreConfig = await selectRegistryWarpRoute(context.registry, symbol);
} else if (warp) {
warpCoreConfig = readWarpCoreConfig(warp);
} else {
logRed(`Please specify either a symbol or warp config`);
process.exit(0);
}
return warpCoreConfig;
}
/**
* Searchable checkbox code
*
@ -497,7 +464,10 @@ function isDownKey(key: KeypressEvent): boolean {
return key.name === 'down';
}
export const searchableCheckBox = createPrompt(
export const searchableCheckBox: Prompt<
any,
SearchableCheckboxConfig<any>
> = createPrompt(
<Value>(
config: SearchableCheckboxConfig<Value>,
done: (value: Array<Value>) => void,

@ -54,3 +54,50 @@ export function formatYamlViolationsOutput(
return highlightedLines.join('\n');
}
/**
* @notice Masks sensitive key with dots
* @param key Sensitive key to mask
* @return Masked key
*/
export function maskSensitiveKey(key: string): string {
if (!key) return key;
const middle = '•'.repeat(key.length);
return `${middle}`;
}
const SENSITIVE_PATTERNS = [
'privatekey',
'key',
'secret',
'secretkey',
'password',
];
const isSensitiveKey = (key: string) => {
const lowerKey = key.toLowerCase();
return SENSITIVE_PATTERNS.some((pattern) => lowerKey.includes(pattern));
};
/**
* @notice Recursively masks sensitive data in objects
* @param obj Object with potential sensitive data
* @return Object with masked sensitive data
*/
export function maskSensitiveData(obj: any): any {
if (!obj) return obj;
if (typeof obj === 'object') {
const masked = { ...obj };
for (const [key, value] of Object.entries(masked)) {
if (isSensitiveKey(key) && typeof value === 'string') {
masked[key] = maskSensitiveKey(value);
} else if (typeof value === 'object') {
masked[key] = maskSensitiveData(value);
}
}
return masked;
}
return obj;
}

@ -0,0 +1,35 @@
import { WarpCoreConfig } from '@hyperlane-xyz/sdk';
import { readWarpCoreConfig } from '../config/warp.js';
import { CommandContext } from '../context/types.js';
import { logRed } from '../logger.js';
import { selectRegistryWarpRoute } from './tokens.js';
/**
* Gets a {@link WarpCoreConfig} based on the provided path or prompts the user to choose one:
* - if `symbol` is provided the user will have to select one of the available warp routes.
* - if `warp` is provided the config will be read by the provided file path.
* - if none is provided the CLI will exit.
*/
export async function getWarpCoreConfigOrExit({
context,
symbol,
warp,
}: {
context: CommandContext;
symbol?: string;
warp?: string;
}): Promise<WarpCoreConfig> {
let warpCoreConfig: WarpCoreConfig;
if (symbol) {
warpCoreConfig = await selectRegistryWarpRoute(context.registry, symbol);
} else if (warp) {
warpCoreConfig = readWarpCoreConfig(warp);
} else {
logRed(`Please specify either a symbol or warp config`);
process.exit(0);
}
return warpCoreConfig;
}

@ -44,7 +44,7 @@ export const checkValidatorSetup = async (
try {
validatorStorageLocations =
await validatorAnnounce.getAnnouncedStorageLocations(validatorsArray);
} catch (e) {
} catch {
errorSet.add('Failed to read announced storage locations on chain.');
}
@ -64,7 +64,7 @@ export const checkValidatorSetup = async (
let s3Validator: S3Validator;
try {
s3Validator = await S3Validator.fromStorageLocation(s3StorageLocation);
} catch (e) {
} catch {
errorRed(
`❌ Failed to fetch storage locations for validator ${validator}, this may be due to the storage location not being an S3 bucket\n\n`,
);

@ -1 +1 @@
export const VERSION = '7.1.0';
export const VERSION = '7.2.0';

@ -1,5 +1,7 @@
# @hyperlane-xyz/github-proxy
## 7.2.0
## 7.1.0
## 7.0.0

@ -1,7 +1,7 @@
{
"name": "@hyperlane-xyz/github-proxy",
"description": "Github proxy that adds the API key to requests",
"version": "7.1.0",
"version": "7.2.0",
"private": true,
"scripts": {
"deploy": "wrangler deploy",
@ -27,7 +27,7 @@
"@cloudflare/vitest-pool-workers": "^0.4.5",
"@cloudflare/workers-types": "^4.20240821.1",
"@faker-js/faker": "^8.4.1",
"chai": "4.5.0",
"chai": "^4.5.0",
"prettier": "^2.8.8",
"typescript": "5.3.3",
"vitest": "1.4.0",

@ -1,5 +0,0 @@
node_modules
dist
coverage
src/types
hardhat.config.ts

@ -1,39 +0,0 @@
{
"env": {
"node": true,
"browser": true,
"es2021": true
},
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"rules": {
"no-eval": ["error"],
"no-ex-assign": ["error"],
"no-constant-condition": ["off"],
"@typescript-eslint/ban-ts-comment": ["off"],
"@typescript-eslint/explicit-module-boundary-types": ["off"],
"@typescript-eslint/no-explicit-any": ["off"],
"@typescript-eslint/no-floating-promises": ["error"],
"@typescript-eslint/no-non-null-assertion": ["off"],
"@typescript-eslint/no-require-imports": ["warn"],
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_"
}
]
}
}

@ -1,5 +1,15 @@
# @hyperlane-xyz/helloworld
## 7.2.0
### Patch Changes
- Updated dependencies [81ab4332f]
- Updated dependencies [4b3537470]
- Updated dependencies [fa6d5f5c6]
- @hyperlane-xyz/sdk@7.2.0
- @hyperlane-xyz/core@5.8.2
## 7.1.0
### Patch Changes

@ -0,0 +1,17 @@
import MonorepoDefaults from '../../eslint.config.mjs';
export default [
...MonorepoDefaults,
{
files: ['./src/**/*.ts'],
},
{
ignores: ["**/src/types/*"],
},
{
ignores: ['./src/scripts'],
rules: {
'no-console': ['off'],
},
},
];

@ -1,26 +1,29 @@
{
"name": "@hyperlane-xyz/helloworld",
"description": "A basic skeleton of an Hyperlane app",
"version": "7.1.0",
"version": "7.2.0",
"dependencies": {
"@hyperlane-xyz/core": "5.8.1",
"@hyperlane-xyz/core": "5.8.2",
"@hyperlane-xyz/registry": "6.1.0",
"@hyperlane-xyz/sdk": "7.1.0",
"@hyperlane-xyz/sdk": "7.2.0",
"@openzeppelin/contracts-upgradeable": "^4.9.3",
"ethers": "^5.7.2"
},
"devDependencies": {
"@eslint/js": "^9.15.0",
"@nomiclabs/hardhat-ethers": "^2.2.3",
"@nomiclabs/hardhat-waffle": "^2.0.6",
"@trivago/prettier-plugin-sort-imports": "^4.2.1",
"@typechain/ethers-v5": "^11.1.2",
"@typechain/ethers-v6": "^0.5.1",
"@typechain/hardhat": "^9.1.0",
"@typescript-eslint/eslint-plugin": "^7.4.0",
"@typescript-eslint/parser": "^7.4.0",
"chai": "4.5.0",
"eslint": "^8.57.0",
"@typescript-eslint/eslint-plugin": "^8.1.6",
"@typescript-eslint/parser": "^8.1.6",
"chai": "^4.5.0",
"eslint": "^9.15.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"ethereum-waffle": "^4.0.10",
"hardhat": "^2.22.2",
"hardhat-gas-reporter": "^1.0.9",
@ -56,7 +59,9 @@
"build": "yarn hardhat-esm compile && tsc",
"clean": "yarn hardhat-esm clean && rm -rf dist cache src/types",
"coverage": "yarn hardhat-esm coverage",
"lint": "solhint contracts/**/*.sol && eslint . --ext .ts",
"lint": "yarn lint:sol && yarn lint:ts",
"lint:sol": "solhint contracts/**/*.sol",
"lint:ts": "eslint -c ./eslint.config.mjs",
"hardhat-esm": "NODE_OPTIONS='--experimental-loader ts-node/esm/transpile-only --no-warnings=ExperimentalWarning' hardhat --config hardhat.config.cts",
"prettier": "prettier --write ./contracts ./src",
"test": "yarn hardhat-esm test ./src/test/**/*.test.ts",

@ -1,5 +1,17 @@
# @hyperlane-xyz/infra
## 7.2.0
### Patch Changes
- Updated dependencies [81ab4332f]
- Updated dependencies [4b3537470]
- Updated dependencies [fa6d5f5c6]
- Updated dependencies [fa6d5f5c6]
- @hyperlane-xyz/sdk@7.2.0
- @hyperlane-xyz/utils@7.2.0
- @hyperlane-xyz/helloworld@7.2.0
## 7.1.0
### Minor Changes

@ -22,6 +22,7 @@ import { getDomainId } from '../../registry.js';
import { environment } from './chains.js';
import { helloWorld } from './helloworld.js';
import aaveSenderAddresses from './misc-artifacts/aave-sender-addresses.json';
import everclearSenderAddresses from './misc-artifacts/everclear-sender-addresses.json';
import merklyEthAddresses from './misc-artifacts/merkly-eth-addresses.json';
import merklyNftAddresses from './misc-artifacts/merkly-eth-addresses.json';
import merklyErc20Addresses from './misc-artifacts/merkly-eth-addresses.json';
@ -64,7 +65,9 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
bitlayer: true,
blast: true,
bob: true,
boba: true,
bsc: true,
bsquared: true,
celo: true,
cheesechain: true,
chilizmainnet: true,
@ -72,6 +75,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
cyber: true,
degenchain: true,
dogechain: true,
duckchain: true,
eclipsemainnet: true,
endurance: true,
ethereum: true,
@ -124,9 +128,12 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
snaxchain: true,
solanamainnet: true,
stride: false,
superseed: true,
superpositionmainnet: true,
taiko: true,
tangle: true,
unichain: true,
vana: true,
viction: true,
worldchain: true,
xai: true,
@ -152,7 +159,9 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
bitlayer: true,
blast: true,
bob: true,
boba: true,
bsc: true,
bsquared: true,
celo: true,
cheesechain: true,
chilizmainnet: true,
@ -160,6 +169,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
cyber: true,
degenchain: true,
dogechain: true,
duckchain: true,
eclipsemainnet: true,
endurance: true,
ethereum: true,
@ -213,9 +223,12 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
snaxchain: true,
solanamainnet: true,
stride: true,
superseed: true,
superpositionmainnet: true,
taiko: true,
tangle: true,
unichain: true,
vana: true,
viction: true,
worldchain: true,
xai: true,
@ -241,7 +254,9 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
bitlayer: true,
blast: true,
bob: true,
boba: true,
bsc: true,
bsquared: true,
celo: true,
cheesechain: true,
chilizmainnet: true,
@ -249,6 +264,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
cyber: true,
degenchain: true,
dogechain: true,
duckchain: true,
// Cannot scrape Sealevel chains
eclipsemainnet: false,
endurance: true,
@ -303,9 +319,12 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
// Cannot scrape Sealevel chains
solanamainnet: false,
stride: true,
superseed: true,
superpositionmainnet: true,
taiko: true,
tangle: true,
unichain: true,
vana: true,
// Has RPC non-compliance that breaks scraping.
viction: false,
worldchain: true,
@ -395,6 +414,12 @@ const metricAppContextsGetter = (): MetricAppContext[] => {
name: 'aave',
matchingList: senderMatchingList(aaveSenderAddresses),
},
{
// https://docs.everclear.org/resources/contracts/mainnet
// Messages between HubGateway (Everclear hub) <> EverclearSpoke (all other spoke chains)
name: 'everclear_gateway',
matchingList: senderMatchingList(everclearSenderAddresses),
},
];
};
@ -429,7 +454,7 @@ const hyperlane: RootAgentConfig = {
rpcConsensusType: RpcConsensusType.Fallback,
docker: {
repo,
tag: '25a927d-20241114-171323',
tag: 'da277d9-20241128-121942',
},
gasPaymentEnforcement: gasPaymentEnforcement,
metricAppContextsGetter,
@ -438,7 +463,7 @@ const hyperlane: RootAgentConfig = {
validators: {
docker: {
repo,
tag: '75d62ae-20241107-060707',
tag: 'd834d81-20241125-135658',
},
rpcConsensusType: RpcConsensusType.Quorum,
chains: validatorChainConfig(Contexts.Hyperlane),
@ -448,7 +473,7 @@ const hyperlane: RootAgentConfig = {
rpcConsensusType: RpcConsensusType.Fallback,
docker: {
repo,
tag: '75d62ae-20241107-060707',
tag: 'd834d81-20241125-135658',
},
resources: scraperResources,
},

@ -53,6 +53,9 @@
"bob": {
"validators": ["0x20f283be1eb0e81e22f51705dcb79883cfdd34aa"]
},
"boba": {
"validators": ["0xebeb92c94ca8408e73aa16fd554cb3a7df075c59"]
},
"bsc": {
"validators": [
"0x570af9b7b36568c8877eebba6c6727aa9dab7268",
@ -60,6 +63,9 @@
"0x03047213365800f065356b4a2fe97c3c3a52296a"
]
},
"bsquared": {
"validators": ["0xcadc90933c9fbe843358a4e70e46ad2db78e28aa"]
},
"celo": {
"validators": [
"0x63478422679303c3e4fc611b771fa4a707ef7f4a",
@ -85,6 +91,9 @@
"dogechain": {
"validators": ["0xe43f742c37858746e6d7e458bc591180d0cba440"]
},
"duckchain": {
"validators": ["0x91d55fe6dac596a6735d96365e21ce4bca21d83c"]
},
"eclipsemainnet": {
"validators": ["0xebb52d7eaa3ff7a5a6260bfe5111ce52d57401d0"]
},
@ -278,6 +287,9 @@
"solanamainnet": {
"validators": ["0x28464752829b3ea59a497fca0bdff575c534c3ff"]
},
"superseed": {
"validators": ["0xdc2b87cb555411bb138d3a4e5f7832c87fae2b88"]
},
"superpositionmainnet": {
"validators": ["0x3f489acdd341c6b4dd86293fa2cc5ecc8ccf4f84"]
},
@ -287,6 +299,12 @@
"tangle": {
"validators": ["0x1ee52cbbfacd7dcb0ba4e91efaa6fbc61602b15b"]
},
"unichain": {
"validators": ["0x9773a382342ebf604a2e5de0a1f462fb499e28b1"]
},
"vana": {
"validators": ["0xfdf3b0dfd4b822d10cacb15c8ae945ea269e7534"]
},
"viction": {
"validators": ["0x1f87c368f8e05a85ef9126d984a980a20930cb9c"]
},

@ -16,6 +16,7 @@ import {
ProtocolFeeHookConfig,
RoutingIsmConfig,
defaultMultisigConfigs,
multisigConfigToIsmConfig,
} from '@hyperlane-xyz/sdk';
import { Address, objMap } from '@hyperlane-xyz/utils';
@ -32,15 +33,11 @@ export const core: ChainMap<CoreConfig> = objMap(
.map((origin) => [origin, defaultMultisigConfigs[origin]]),
);
const merkleRoot = (multisig: MultisigConfig): MultisigIsmConfig => ({
type: IsmType.MERKLE_ROOT_MULTISIG,
...multisig,
});
const merkleRoot = (multisig: MultisigConfig): MultisigIsmConfig =>
multisigConfigToIsmConfig(IsmType.MERKLE_ROOT_MULTISIG, multisig);
const messageIdIsm = (multisig: MultisigConfig): MultisigIsmConfig => ({
type: IsmType.MESSAGE_ID_MULTISIG,
...multisig,
});
const messageIdIsm = (multisig: MultisigConfig): MultisigIsmConfig =>
multisigConfigToIsmConfig(IsmType.MESSAGE_ID_MULTISIG, multisig);
const routingIsm: RoutingIsmConfig = {
type: IsmType.ROUTING,

@ -5376,5 +5376,425 @@
"constructorArguments": "00000000000000000000000096d51cc3f7500d501baeb1a2a62bb96fa03532f8",
"isProxy": false
}
],
"boba": [
{
"name": "ProxyAdmin",
"address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"constructorArguments": "",
"isProxy": false
},
{
"name": "Mailbox",
"address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"constructorArguments": "0000000000000000000000000000000000000000000000000000000000000120",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D"
},
{
"name": "MerkleTreeHook",
"address": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "FallbackRoutingHook",
"address": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000009eaac366bfd70430cfee6e70265fefff1cfc9e47",
"isProxy": false
},
{
"name": "PausableHook",
"address": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StorageGasOracle",
"address": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"constructorArguments": "",
"isProxy": false
},
{
"name": "InterchainGasPaymaster",
"address": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de",
"constructorArguments": "",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x9534122Aae7978dB8f5f10dF4432233c53e820A1",
"constructorArguments": "00000000000000000000000083475ca5beb2eaa59a2ff48a0544ebaa4a32c2de0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de"
},
{
"name": "ProtocolFee",
"address": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8",
"constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba",
"isProxy": false
},
{
"name": "ValidatorAnnounce",
"address": "0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
}
],
"superseed": [
{
"name": "ProxyAdmin",
"address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"constructorArguments": "",
"isProxy": false
},
{
"name": "Mailbox",
"address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"constructorArguments": "00000000000000000000000000000000000000000000000000000000000014d2",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D"
},
{
"name": "MerkleTreeHook",
"address": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "FallbackRoutingHook",
"address": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000009eaac366bfd70430cfee6e70265fefff1cfc9e47",
"isProxy": false
},
{
"name": "PausableHook",
"address": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StorageGasOracle",
"address": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"constructorArguments": "",
"isProxy": false
},
{
"name": "InterchainGasPaymaster",
"address": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de",
"constructorArguments": "",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x9534122Aae7978dB8f5f10dF4432233c53e820A1",
"constructorArguments": "00000000000000000000000083475ca5beb2eaa59a2ff48a0544ebaa4a32c2de0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de"
},
{
"name": "ProtocolFee",
"address": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8",
"constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba",
"isProxy": false
},
{
"name": "ValidatorAnnounce",
"address": "0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
}
],
"unichain": [
{
"name": "ProxyAdmin",
"address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"constructorArguments": "",
"isProxy": false
},
{
"name": "Mailbox",
"address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"constructorArguments": "0000000000000000000000000000000000000000000000000000000000000082",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D"
},
{
"name": "MerkleTreeHook",
"address": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "FallbackRoutingHook",
"address": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000009eaac366bfd70430cfee6e70265fefff1cfc9e47",
"isProxy": false
},
{
"name": "PausableHook",
"address": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StorageGasOracle",
"address": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"constructorArguments": "",
"isProxy": false
},
{
"name": "InterchainGasPaymaster",
"address": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de",
"constructorArguments": "",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x9534122Aae7978dB8f5f10dF4432233c53e820A1",
"constructorArguments": "00000000000000000000000083475ca5beb2eaa59a2ff48a0544ebaa4a32c2de0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de"
},
{
"name": "ProtocolFee",
"address": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8",
"constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba",
"isProxy": false
},
{
"name": "ValidatorAnnounce",
"address": "0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
}
],
"duckchain": [
{
"name": "ProxyAdmin",
"address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"constructorArguments": "",
"isProxy": false
},
{
"name": "Mailbox",
"address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"constructorArguments": "00000000000000000000000000000000000000000000000000000000000015a9",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D"
},
{
"name": "MerkleTreeHook",
"address": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "FallbackRoutingHook",
"address": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000009eaac366bfd70430cfee6e70265fefff1cfc9e47",
"isProxy": false
},
{
"name": "PausableHook",
"address": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StorageGasOracle",
"address": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"constructorArguments": "",
"isProxy": false
},
{
"name": "InterchainGasPaymaster",
"address": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de",
"constructorArguments": "",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x9534122Aae7978dB8f5f10dF4432233c53e820A1",
"constructorArguments": "00000000000000000000000083475ca5beb2eaa59a2ff48a0544ebaa4a32c2de0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de"
},
{
"name": "ProtocolFee",
"address": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8",
"constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba",
"isProxy": false
},
{
"name": "ValidatorAnnounce",
"address": "0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
}
],
"vana": [
{
"name": "ProxyAdmin",
"address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"constructorArguments": "",
"isProxy": false
},
{
"name": "Mailbox",
"address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"constructorArguments": "00000000000000000000000000000000000000000000000000000000000005c8",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D"
},
{
"name": "MerkleTreeHook",
"address": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "FallbackRoutingHook",
"address": "0x0D3bD9F1bcDA82bD1682b2C895a907d7aaE45849",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba0000000000000000000000009eaac366bfd70430cfee6e70265fefff1cfc9e47",
"isProxy": false
},
{
"name": "PausableHook",
"address": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StorageGasOracle",
"address": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"constructorArguments": "",
"isProxy": false
},
{
"name": "InterchainGasPaymaster",
"address": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de",
"constructorArguments": "",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x9534122Aae7978dB8f5f10dF4432233c53e820A1",
"constructorArguments": "00000000000000000000000083475ca5beb2eaa59a2ff48a0544ebaa4a32c2de0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de"
},
{
"name": "ProtocolFee",
"address": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8",
"constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba",
"isProxy": false
},
{
"name": "ValidatorAnnounce",
"address": "0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
}
],
"bsquared": [
{
"name": "ProxyAdmin",
"address": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"constructorArguments": "",
"isProxy": false
},
{
"name": "Mailbox",
"address": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"constructorArguments": "00000000000000000000000000000000000000000000000000000000000000df",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"constructorArguments": "000000000000000000000000ea87ae93fa0019a82a727bfd3ebd1cfca8f64f1d0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D"
},
{
"name": "MerkleTreeHook",
"address": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "FallbackRoutingHook",
"address": "0x60bB6D060393D3C206719A7bD61844cC82891cfB",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000bb0ae51bca526cf313b6a95bfab020794af6c394",
"isProxy": false
},
{
"name": "PausableHook",
"address": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StorageGasOracle",
"address": "0x451dF8AB0936D85526D816f0b4dCaDD934A034A4",
"constructorArguments": "",
"isProxy": false
},
{
"name": "InterchainGasPaymaster",
"address": "0x81EbEdfc1220BE33C3B9c5E09c1FCab849a392A6",
"constructorArguments": "",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x70EbA87Cd15616f32C736B3f3BdCfaeD0713a82B",
"constructorArguments": "00000000000000000000000081ebedfc1220be33c3b9c5e09c1fcab849a392a60000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x81EbEdfc1220BE33C3B9c5E09c1FCab849a392A6"
},
{
"name": "ProtocolFee",
"address": "0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE",
"constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba",
"isProxy": false
},
{
"name": "ValidatorAnnounce",
"address": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
}
]
}

@ -10,7 +10,7 @@ export const keyFunderConfig: KeyFunderConfig<
> = {
docker: {
repo: 'gcr.io/abacus-labs-dev/hyperlane-monorepo',
tag: '1ed620c-20241107-052148',
tag: 'aac6787-20241128-103715',
},
// We're currently using the same deployer/key funder key as mainnet2.
// To minimize nonce clobbering we offset the key funder cron
@ -40,7 +40,9 @@ export const keyFunderConfig: KeyFunderConfig<
bitlayer: '0.002',
blast: '0.2',
bob: '0.2',
boba: '0.05',
bsc: '5',
bsquared: '0.002',
celo: '3',
cheesechain: '50',
chilizmainnet: '200',
@ -48,6 +50,7 @@ export const keyFunderConfig: KeyFunderConfig<
cyber: '0.05',
degenchain: '100',
dogechain: '100',
duckchain: '5',
endurance: '20',
ethereum: '0.5',
everclear: '0.05',
@ -96,9 +99,13 @@ export const keyFunderConfig: KeyFunderConfig<
snaxchain: '0.05',
// ignore non-evm chains
stride: '0',
superseed: '0.05',
superpositionmainnet: '0.05',
taiko: '0.2',
tangle: '2',
unichain: '0.05',
// temporarily low until we're able to fund more
vana: '0.001',
viction: '3',
worldchain: '0.2',
xai: '20',

@ -12,7 +12,7 @@
"decimals": 9
},
"arbitrum": {
"amount": "0.01",
"amount": "0.123544",
"decimals": 9
},
"arbitrumnova": {
@ -24,7 +24,7 @@
"decimals": 9
},
"astarzkevm": {
"amount": "0.078",
"amount": "0.24",
"decimals": 9
},
"flame": {
@ -36,11 +36,11 @@
"decimals": 9
},
"b3": {
"amount": "0.001000254",
"amount": "0.001000252",
"decimals": 9
},
"base": {
"amount": "0.004893247",
"amount": "0.024525952",
"decimals": 9
},
"bitlayer": {
@ -48,17 +48,25 @@
"decimals": 9
},
"blast": {
"amount": "0.005018176",
"amount": "0.005892268",
"decimals": 9
},
"bob": {
"amount": "0.001000252",
"decimals": 9
},
"boba": {
"amount": "0.001000047",
"decimals": 9
},
"bsc": {
"amount": "1.0",
"decimals": 9
},
"bsquared": {
"amount": "0.001000252",
"decimals": 9
},
"celo": {
"amount": "10.0",
"decimals": 9
@ -87,6 +95,10 @@
"amount": "250.0",
"decimals": 9
},
"duckchain": {
"amount": "10.0",
"decimals": 9
},
"eclipsemainnet": {
"amount": "0.0000001",
"decimals": 1
@ -96,7 +108,7 @@
"decimals": 9
},
"ethereum": {
"amount": "15.0",
"amount": "30.088451558",
"decimals": 9
},
"everclear": {
@ -124,7 +136,7 @@
"decimals": 9
},
"gnosis": {
"amount": "1.500000007",
"amount": "1.500000008",
"decimals": 9
},
"gravity": {
@ -136,7 +148,7 @@
"decimals": 9
},
"immutablezkevmmainnet": {
"amount": "10.000000056",
"amount": "10.00000005",
"decimals": 9
},
"inevm": {
@ -156,7 +168,7 @@
"decimals": 9
},
"linea": {
"amount": "0.160485013",
"amount": "0.548523195",
"decimals": 9
},
"lisk": {
@ -172,7 +184,7 @@
"decimals": 9
},
"mantapacific": {
"amount": "0.003001158",
"amount": "0.0030005",
"decimals": 9
},
"mantle": {
@ -208,7 +220,7 @@
"decimals": 9
},
"morph": {
"amount": "0.002",
"amount": "0.014614332",
"decimals": 9
},
"neutron": {
@ -220,7 +232,7 @@
"decimals": 9
},
"optimism": {
"amount": "0.001010111",
"amount": "0.001065045",
"decimals": 9
},
"orderly": {
@ -232,11 +244,11 @@
"decimals": 1
},
"polygon": {
"amount": "47.07124319",
"amount": "260.197309239",
"decimals": 9
},
"polygonzkevm": {
"amount": "0.146",
"amount": "0.451",
"decimals": 9
},
"polynomialfi": {
@ -244,7 +256,7 @@
"decimals": 9
},
"prom": {
"amount": "13.1",
"amount": "75.2",
"decimals": 9
},
"proofofplay": {
@ -280,7 +292,7 @@
"decimals": 9
},
"shibarium": {
"amount": "0.542811448",
"amount": "3.89327567",
"decimals": 9
},
"snaxchain": {
@ -295,24 +307,36 @@
"amount": "0.005",
"decimals": 1
},
"superseed": {
"amount": "0.001000252",
"decimals": 9
},
"superpositionmainnet": {
"amount": "0.01",
"decimals": 9
},
"taiko": {
"amount": "0.1323",
"amount": "0.1243284",
"decimals": 9
},
"tangle": {
"amount": "1.0",
"decimals": 9
},
"unichain": {
"amount": "0.001000252",
"decimals": 9
},
"vana": {
"amount": "0.001000007",
"decimals": 9
},
"viction": {
"amount": "0.25",
"decimals": 9
},
"worldchain": {
"amount": "0.00100025",
"amount": "0.00100026",
"decimals": 9
},
"xai": {
@ -320,7 +344,7 @@
"decimals": 9
},
"xlayer": {
"amount": "7.04",
"amount": "23.05",
"decimals": 9
},
"zeronetwork": {
@ -340,7 +364,7 @@
"decimals": 9
},
"zoramainnet": {
"amount": "0.001000269",
"amount": "0.001000252",
"decimals": 9
}
}

@ -6916,5 +6916,521 @@
"constructorArguments": "",
"isProxy": true
}
],
"superseed": [
{
"name": "StaticMerkleRootMultisigIsmFactory",
"address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootMultisigIsm",
"address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdMultisigIsmFactory",
"address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdMultisigIsm",
"address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationIsmFactory",
"address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationIsm",
"address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationHookFactory",
"address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationHook",
"address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0",
"constructorArguments": "",
"isProxy": true
},
{
"name": "DomainRoutingIsmFactory",
"address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"constructorArguments": "",
"isProxy": false
},
{
"name": "DomaingRoutingIsm",
"address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMerkleRootWeightedMultisigIsmFactory",
"address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootWeightedMultisigIsm",
"address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdWeightedMultisigIsmFactory",
"address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdWeightedMultisigIsm",
"address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354",
"constructorArguments": "",
"isProxy": true
}
],
"unichain": [
{
"name": "StaticMerkleRootMultisigIsmFactory",
"address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootMultisigIsm",
"address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdMultisigIsmFactory",
"address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdMultisigIsm",
"address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationIsmFactory",
"address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationIsm",
"address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationHookFactory",
"address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationHook",
"address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0",
"constructorArguments": "",
"isProxy": true
},
{
"name": "DomainRoutingIsmFactory",
"address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"constructorArguments": "",
"isProxy": false
},
{
"name": "DomaingRoutingIsm",
"address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMerkleRootWeightedMultisigIsmFactory",
"address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootWeightedMultisigIsm",
"address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdWeightedMultisigIsmFactory",
"address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdWeightedMultisigIsm",
"address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354",
"constructorArguments": "",
"isProxy": true
}
],
"duckchain": [
{
"name": "StaticMerkleRootMultisigIsmFactory",
"address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootMultisigIsm",
"address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdMultisigIsmFactory",
"address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdMultisigIsm",
"address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationIsmFactory",
"address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationIsm",
"address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationHookFactory",
"address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationHook",
"address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0",
"constructorArguments": "",
"isProxy": true
},
{
"name": "DomainRoutingIsmFactory",
"address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"constructorArguments": "",
"isProxy": false
},
{
"name": "DomaingRoutingIsm",
"address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMerkleRootWeightedMultisigIsmFactory",
"address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootWeightedMultisigIsm",
"address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdWeightedMultisigIsmFactory",
"address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdWeightedMultisigIsm",
"address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354",
"constructorArguments": "",
"isProxy": true
}
],
"vana": [
{
"name": "StaticMerkleRootMultisigIsmFactory",
"address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootMultisigIsm",
"address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdMultisigIsmFactory",
"address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdMultisigIsm",
"address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationIsmFactory",
"address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationIsm",
"address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationHookFactory",
"address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationHook",
"address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0",
"constructorArguments": "",
"isProxy": true
},
{
"name": "DomainRoutingIsmFactory",
"address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"constructorArguments": "",
"isProxy": false
},
{
"name": "DomaingRoutingIsm",
"address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMerkleRootWeightedMultisigIsmFactory",
"address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootWeightedMultisigIsm",
"address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdWeightedMultisigIsmFactory",
"address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdWeightedMultisigIsm",
"address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354",
"constructorArguments": "",
"isProxy": true
}
],
"boba": [
{
"name": "StaticMerkleRootMultisigIsmFactory",
"address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootMultisigIsm",
"address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdMultisigIsmFactory",
"address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdMultisigIsm",
"address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationIsmFactory",
"address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationIsm",
"address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationHookFactory",
"address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationHook",
"address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0",
"constructorArguments": "",
"isProxy": true
},
{
"name": "DomainRoutingIsmFactory",
"address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"constructorArguments": "",
"isProxy": false
},
{
"name": "DomaingRoutingIsm",
"address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMerkleRootWeightedMultisigIsmFactory",
"address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootWeightedMultisigIsm",
"address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdWeightedMultisigIsmFactory",
"address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdWeightedMultisigIsm",
"address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354",
"constructorArguments": "",
"isProxy": true
}
],
"bsquared": [
{
"name": "StaticMerkleRootMultisigIsmFactory",
"address": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootMultisigIsm",
"address": "0x4725F7b8037513915aAf6D6CBDE2920E28540dDc",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdMultisigIsmFactory",
"address": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdMultisigIsm",
"address": "0xAF03386044373E2fe26C5b1dCedF5a7e854a7a3F",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationIsmFactory",
"address": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationIsm",
"address": "0x882CD0C5D50b6dD74b36Da4BDb059507fddEDdf2",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticAggregationHookFactory",
"address": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticAggregationHook",
"address": "0x19930232E9aFC4f4F09d09fe2375680fAc2100D0",
"constructorArguments": "",
"isProxy": true
},
{
"name": "DomainRoutingIsmFactory",
"address": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"constructorArguments": "",
"isProxy": false
},
{
"name": "DomaingRoutingIsm",
"address": "0x12Ed1BbA182CbC63692F813651BD493B7445C874",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMerkleRootWeightedMultisigIsmFactory",
"address": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMerkleRootWeightedMultisigIsm",
"address": "0x3b9f24fD2ecfed0d3A88fa7f0E4e5747671981D7",
"constructorArguments": "",
"isProxy": true
},
{
"name": "StaticMessageIdWeightedMultisigIsmFactory",
"address": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"constructorArguments": "",
"isProxy": false
},
{
"name": "StaticMessageIdWeightedMultisigIsm",
"address": "0x71DCcD21B912F7d4f636af0C9eA5DC0C10617354",
"constructorArguments": "",
"isProxy": true
}
]
}

@ -1680,5 +1680,131 @@
"isProxy": true,
"expectedimplementation": "0x28846fCb579747E8ddad9E93b55BE51b0A1Bf1f3"
}
],
"superseed": [
{
"name": "InterchainAccountIsm",
"address": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "InterchainAccountRouter",
"address": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"constructorArguments": "0000000000000000000000000f9d4704e1fb25e416042524e594f1ceac6ff5970000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025eac2007b0d40e3f0af112fd346412321038719000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597"
}
],
"boba": [
{
"name": "InterchainAccountIsm",
"address": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "InterchainAccountRouter",
"address": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"constructorArguments": "0000000000000000000000000f9d4704e1fb25e416042524e594f1ceac6ff5970000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025eac2007b0d40e3f0af112fd346412321038719000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597"
}
],
"unichain": [
{
"name": "InterchainAccountIsm",
"address": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "InterchainAccountRouter",
"address": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"constructorArguments": "0000000000000000000000000f9d4704e1fb25e416042524e594f1ceac6ff5970000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025eac2007b0d40e3f0af112fd346412321038719000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597"
}
],
"duckchain": [
{
"name": "InterchainAccountIsm",
"address": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "InterchainAccountRouter",
"address": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"constructorArguments": "0000000000000000000000000f9d4704e1fb25e416042524e594f1ceac6ff5970000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025eac2007b0d40e3f0af112fd346412321038719000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597"
}
],
"vana": [
{
"name": "InterchainAccountIsm",
"address": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "InterchainAccountRouter",
"address": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"constructorArguments": "0000000000000000000000000f9d4704e1fb25e416042524e594f1ceac6ff5970000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025eac2007b0d40e3f0af112fd346412321038719000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x0F9d4704E1Fb25e416042524e594F1cEac6fF597"
}
],
"bsquared": [
{
"name": "InterchainAccountIsm",
"address": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "InterchainAccountRouter",
"address": "0x7CE76f5f0C469bBB4cd7Ea6EbabB54437A093127",
"constructorArguments": "0000000000000000000000003a464f746d23ab22155710f44db16dca53e0775e",
"isProxy": false
},
{
"name": "TransparentUpgradeableProxy",
"address": "0x4D50044335dc1d4D26c343AdeDf6E47808475Deb",
"constructorArguments": "0000000000000000000000007ce76f5f0c469bbb4cd7ea6ebabb54437a0931270000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff26696dcdb6bbfd27e959b847d4f1399d5bcf64000000000000000000000000a7eccdb9be08178f896c26b7bbd8c3d4e844d9ba00000000000000000000000000000000000000000000000000000000",
"isProxy": true,
"expectedimplementation": "0x7CE76f5f0C469bBB4cd7Ea6EbabB54437A093127"
}
]
}

@ -0,0 +1,20 @@
{
"everclear": {
"sender": "0xEFfAB7cCEBF63FbEFB4884964b12259d4374FaAa"
},
"ethereum": {
"sender": "0x9ADA72CCbAfe94248aFaDE6B604D1bEAacc899A7"
},
"optimism": {
"sender": "0x9ADA72CCbAfe94248aFaDE6B604D1bEAacc899A7"
},
"bsc": {
"sender": "0x9ADA72CCbAfe94248aFaDE6B604D1bEAacc899A7"
},
"base": {
"sender": "0x9ADA72CCbAfe94248aFaDE6B604D1bEAacc899A7"
},
"arbitrum": {
"sender": "0x9ADA72CCbAfe94248aFaDE6B604D1bEAacc899A7"
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save