Merge branch 'main' of github.com:hyperlane-xyz/hyperlane-monorepo into xeno/warp-deploy-apply-ownership-fixes

pull/4726/head
xeno097 1 month ago
commit a8f4683784
  1. 5
      .changeset/dirty-clocks-repeat.md
  2. 5
      .changeset/dirty-months-buy.md
  3. 6
      .changeset/dry-foxes-battle.md
  4. 5
      .changeset/few-goats-add.md
  5. 5
      .changeset/fluffy-ducks-buy.md
  6. 6
      .changeset/grumpy-ears-relate.md
  7. 5
      .changeset/itchy-bananas-know.md
  8. 5
      .changeset/itchy-singers-hang.md
  9. 5
      .changeset/long-swans-drive.md
  10. 5
      .changeset/perfect-dryers-destroy.md
  11. 6
      .changeset/plenty-chicken-clean.md
  12. 7
      .changeset/poor-coins-accept.md
  13. 5
      .changeset/red-actors-shop.md
  14. 5
      .changeset/shiny-baboons-hunt.md
  15. 5
      .changeset/silver-dancers-rhyme.md
  16. 5
      .changeset/sweet-humans-argue.md
  17. 5
      .changeset/tender-spiders-deny.md
  18. 5
      .changeset/tidy-hornets-beam.md
  19. 5
      .changeset/tricky-mangos-sin.md
  20. 5
      .changeset/wise-camels-repair.md
  21. 16
      .github/actions/yarn-build-with-cache/action.yml
  22. 26
      .github/workflows/test.yml
  23. 2
      .registryrc
  24. 8
      rust/main/agents/scraper/migration/src/m20230309_000001_create_table_domain.rs
  25. 12
      rust/main/agents/validator/src/settings.rs
  26. 26
      rust/main/agents/validator/src/submit.rs
  27. 17
      rust/main/agents/validator/src/validator.rs
  28. 9
      rust/main/chains/hyperlane-cosmos/src/mailbox/contract.rs
  29. 22
      rust/main/chains/hyperlane-cosmos/src/merkle_tree_hook.rs
  30. 25
      rust/main/chains/hyperlane-cosmos/src/utils.rs
  31. 54
      rust/main/chains/hyperlane-ethereum/src/config.rs
  32. 28
      rust/main/chains/hyperlane-ethereum/src/contracts/interchain_gas.rs
  33. 37
      rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs
  34. 51
      rust/main/chains/hyperlane-ethereum/src/contracts/merkle_tree_hook.rs
  35. 2
      rust/main/chains/hyperlane-ethereum/src/contracts/mod.rs
  36. 35
      rust/main/chains/hyperlane-ethereum/src/contracts/utils.rs
  37. 24
      rust/main/chains/hyperlane-ethereum/src/tx.rs
  38. 9
      rust/main/chains/hyperlane-fuel/src/mailbox.rs
  39. 10
      rust/main/chains/hyperlane-sealevel/src/mailbox.rs
  40. 18
      rust/main/chains/hyperlane-sealevel/src/merkle_tree_hook.rs
  41. 212
      rust/main/config/mainnet_config.json
  42. 17
      rust/main/hyperlane-base/src/contract_sync/mod.rs
  43. 42
      rust/main/hyperlane-base/src/settings/chains.rs
  44. 8
      rust/main/hyperlane-base/src/settings/checkpoint_syncer.rs
  45. 10
      rust/main/hyperlane-base/src/settings/parser/mod.rs
  46. 116
      rust/main/hyperlane-core/src/chain.rs
  47. 9
      rust/main/hyperlane-core/src/error.rs
  48. 7
      rust/main/hyperlane-core/src/traits/mailbox.rs
  49. 14
      rust/main/hyperlane-core/src/traits/merkle_tree_hook.rs
  50. 6
      rust/main/hyperlane-core/src/types/reorg.rs
  51. 12
      rust/main/hyperlane-test/src/mocks/mailbox.rs
  52. 14
      solidity/CHANGELOG.md
  53. 2
      solidity/contracts/PackageVersioned.sol
  54. 16
      solidity/contracts/client/GasRouter.sol
  55. 4
      solidity/contracts/libs/TypeCasts.sol
  56. 16
      solidity/contracts/token/HypERC20Collateral.sol
  57. 16
      solidity/contracts/token/extensions/HypERC4626Collateral.sol
  58. 113
      solidity/contracts/token/extensions/WHypERC4626.sol
  59. 4
      solidity/package.json
  60. 2
      solidity/test/GasRouter.t.sol
  61. 2
      solidity/test/isms/RateLimitedIsm.t.sol
  62. 5
      solidity/test/token/HypERC20.t.sol
  63. 68
      solidity/test/token/HypERC4626Test.t.sol
  64. 116
      solidity/test/token/WHypERC4626.t.sol
  65. 2
      typescript/ccip-server/CHANGELOG.md
  66. 2
      typescript/ccip-server/package.json
  67. 8
      typescript/cli/.mocharc-e2e.json
  68. 2
      typescript/cli/.mocharc.json
  69. 33
      typescript/cli/CHANGELOG.md
  70. 9
      typescript/cli/package.json
  71. 12
      typescript/cli/scripts/run-e2e-test.sh
  72. 105
      typescript/cli/src/commands/core.ts
  73. 2
      typescript/cli/src/commands/options.ts
  74. 22
      typescript/cli/src/config/chain.ts
  75. 36
      typescript/cli/src/read/core.ts
  76. 2
      typescript/cli/src/version.ts
  77. 2
      typescript/github-proxy/CHANGELOG.md
  78. 2
      typescript/github-proxy/package.json
  79. 22
      typescript/helloworld/CHANGELOG.md
  80. 6
      typescript/helloworld/package.json
  81. 26
      typescript/infra/CHANGELOG.md
  82. 9
      typescript/infra/config/environments/mainnet3/agent.ts
  83. 2
      typescript/infra/config/environments/mainnet3/funding.ts
  84. 4
      typescript/infra/config/environments/mainnet3/gasPrices.json
  85. 1
      typescript/infra/config/environments/mainnet3/supportedChainNames.ts
  86. 1
      typescript/infra/config/environments/mainnet3/tokenPrices.json
  87. 28
      typescript/infra/config/environments/mainnet3/warp/AMPHRETH-deployments.yaml
  88. 55
      typescript/infra/config/environments/mainnet3/warp/configGetters/getArbitrumEthereumZircuitAmphrETHWarpConfig.ts
  89. 1
      typescript/infra/config/environments/mainnet3/warp/warpIds.ts
  90. 2
      typescript/infra/config/registry.ts
  91. 3
      typescript/infra/config/warp.ts
  92. 8
      typescript/infra/package.json
  93. 4
      typescript/infra/src/config/agent/validator.ts
  94. 1
      typescript/infra/src/config/warp.ts
  95. 24
      typescript/infra/src/govern/HyperlaneAppGovernor.ts
  96. 2
      typescript/infra/src/warp/helm.ts
  97. 26
      typescript/sdk/CHANGELOG.md
  98. 6
      typescript/sdk/package.json
  99. 32
      typescript/sdk/src/contracts/contracts.ts
  100. 76
      typescript/sdk/src/hook/EvmHookReader.ts
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/utils': patch
---
Fix objMerge implementation

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/sdk': minor
---
Deploy to odysseytestnet

@ -1,6 +0,0 @@
---
'@hyperlane-xyz/cli': minor
---
Add strategyUrl detect and validation in the beginning of `warp apply`
Remove yaml transactions print from `warp apply`

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/sdk': minor
---
Enroll new validators. Add tx overrides when deploying ICA accounts. Core checker now surfaces owner violations for defaultHook and requiredHook. App checker temporarily ignores bytecode mismatch violations.

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/sdk': minor
---
Add override to some transactions to fix warp apply

@ -1,6 +0,0 @@
---
'@hyperlane-xyz/cli': minor
'@hyperlane-xyz/sdk': minor
---
Adds the warp check command to compare warp routes config files with on chain warp route deployments

@ -0,0 +1,5 @@
---
'@hyperlane-xyz/core': patch
---
Add wrapped HypERC4626 for easy defi use

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/core': patch
---
Patched OPL2ToL1Ism to check for correct messageId for external call in verify

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/cli': minor
---
Add prompt in `warp init` command to choose if a trusted relayer should be used instead of making the choice by default for the user and enable the `--yes` flag to default to a trusted ISM

@ -0,0 +1,5 @@
---
'@hyperlane-xyz/core': minor
---
Minor token related changes like adding custom hook to 4626 collateral, checking for ERC20 as valid contract in HypERC20Collateral, etc.

@ -1,6 +0,0 @@
---
'@hyperlane-xyz/cli': minor
'@hyperlane-xyz/sdk': minor
---
Add rebasing yield route support into CLI/SDK

@ -1,7 +0,0 @@
---
'@hyperlane-xyz/helloworld': patch
'@hyperlane-xyz/widgets': patch
'@hyperlane-xyz/cli': patch
---
Update registry to v4.7.0

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/core': patch
---
Added nonce to HypERC4626

@ -0,0 +1,5 @@
---
'@hyperlane-xyz/core': minor
---
Added WHypERC4626 as a wrapper for rebasing HypERC4626

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/infra': minor
---
Updates the warpIds for Renzo's latest deployment to Sei and Taiko to be used by the Checker

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/core': minor
---
Added PRECISION and rateUpdateNonce to ensure compatibility of HypERC4626

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/cli': minor
---
Update `warp apply` such that it updates in place AND extends in a single call

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/sdk': minor
---
Add deployments for mainnets: flow, metall2, polynomial

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/cli': minor
---
updates the multi chain selection prompt by adding search functionality and an optional confirmation prompt for the current selection

@ -1,5 +0,0 @@
---
'@hyperlane-xyz/sdk': patch
---
Set transaction overrides and add 10% gas limit buffer when sending message through HyperlaneCore.

@ -11,12 +11,26 @@ runs:
steps:
- name: Cache
uses: buildjet/cache@v4
id: cache
with:
path: |
**/node_modules
.yarn
key: ${{ runner.os }}-yarn-cache-${{ hashFiles('./yarn.lock') }}
fail-on-cache-miss: true
# Typically, the cache will be hit, but if there's a network error when
# restoring the cache, let's run the install step ourselves.
- name: Install dependencies
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
run: |
yarn install
CHANGES=$(git status -s --ignore-submodules)
if [[ ! -z $CHANGES ]]; then
echo "Changes found: $CHANGES"
git diff
exit 1
fi
- name: Build
shell: bash

@ -109,6 +109,30 @@ jobs:
- name: Unit Tests
run: yarn test:ci
cli-e2e:
runs-on: ubuntu-latest
needs: [yarn-install]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
submodules: recursive
fetch-depth: 0
- name: foundry-install
uses: foundry-rs/foundry-toolchain@v1
- name: yarn-build
uses: ./.github/actions/yarn-build-with-cache
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Checkout registry
uses: ./.github/actions/checkout-registry
- name: CLI e2e tests
run: yarn --cwd typescript/cli test:e2e
agent-configs:
runs-on: ubuntu-latest
needs: [yarn-install]
@ -218,7 +242,7 @@ jobs:
run: |
if [[ -n "$(git diff ${{ github.event.pull_request.head.sha || github.sha }} ${{ github.event.pull_request.base.sha }} -- ./rust)" ]]; then
echo "rust_changes=true" >> $GITHUB_OUTPUT
echo "$(git diff ${{ github.event.pull_request.head.sha || github.sha }} ${{ github.event.pull_request.base.sha }} -- ./rust)"
echo "$(git diff ${{ github.event.pull_request.head.sha || github.sha }} ${{ github.event.pull_request.base.sha }} -- ./rust)"
else
echo "rust_changes=false" >> $GITHUB_OUTPUT
fi

@ -1 +1 @@
8583d0841615313c8c880e765eba760378e061cd
dee58183e51f4eb43e84dbac0e595a4b389dbe80

@ -438,6 +438,14 @@ const DOMAINS: &[RawDomain] = &[
is_test_net: false,
is_deprecated: false,
},
RawDomain {
name: "stride",
token: "STRD",
domain: 745,
chain_id: 745,
is_test_net: false,
is_deprecated: false,
},
RawDomain {
name: "cosmostest99990",
token: "OSMO",

@ -15,7 +15,9 @@ use hyperlane_base::{
CheckpointSyncerConf, Settings, SignerConf,
},
};
use hyperlane_core::{cfg_unwrap_all, config::*, HyperlaneDomain, HyperlaneDomainProtocol};
use hyperlane_core::{
cfg_unwrap_all, config::*, HyperlaneDomain, HyperlaneDomainProtocol, ReorgPeriod,
};
use serde::Deserialize;
use serde_json::Value;
@ -36,8 +38,8 @@ pub struct ValidatorSettings {
pub validator: SignerConf,
/// The checkpoint syncer configuration
pub checkpoint_syncer: CheckpointSyncerConf,
/// The reorg_period in blocks
pub reorg_period: u64,
/// The reorg configuration
pub reorg_period: ReorgPeriod,
/// How frequently to check for new checkpoints
pub interval: Duration,
}
@ -122,8 +124,8 @@ impl FromRawConf<RawValidatorSettings> for ValidatorSettings {
.get_key(origin_chain_name)
.get_opt_key("blocks")
.get_opt_key("reorgPeriod")
.parse_u64()
.unwrap_or(1);
.parse_value("Invalid reorgPeriod")
.unwrap_or(ReorgPeriod::from_blocks(1));
cfg_unwrap_all!(cwp, err: [base, origin_chain, validator, checkpoint_syncer]);

@ -1,4 +1,3 @@
use std::num::NonZeroU64;
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::vec;
@ -14,13 +13,13 @@ use hyperlane_core::{
accumulator::incremental::IncrementalMerkle, Checkpoint, CheckpointWithMessageId,
HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneSignerExt,
};
use hyperlane_core::{ChainResult, MerkleTreeHook, ReorgEvent};
use hyperlane_core::{ChainResult, MerkleTreeHook, ReorgEvent, ReorgPeriod};
use hyperlane_ethereum::SingletonSignerHandle;
#[derive(Clone)]
pub(crate) struct ValidatorSubmitter {
interval: Duration,
reorg_period: Option<NonZeroU64>,
reorg_period: ReorgPeriod,
signer: SingletonSignerHandle,
merkle_tree_hook: Arc<dyn MerkleTreeHook>,
checkpoint_syncer: Arc<dyn CheckpointSyncer>,
@ -31,7 +30,7 @@ pub(crate) struct ValidatorSubmitter {
impl ValidatorSubmitter {
pub(crate) fn new(
interval: Duration,
reorg_period: u64,
reorg_period: ReorgPeriod,
merkle_tree_hook: Arc<dyn MerkleTreeHook>,
signer: SingletonSignerHandle,
checkpoint_syncer: Arc<dyn CheckpointSyncer>,
@ -39,7 +38,7 @@ impl ValidatorSubmitter {
metrics: ValidatorSubmitterMetrics,
) -> Self {
Self {
reorg_period: NonZeroU64::new(reorg_period),
reorg_period,
interval,
merkle_tree_hook,
signer,
@ -94,7 +93,8 @@ impl ValidatorSubmitter {
// Lag by reorg period because this is our correctness checkpoint.
let latest_checkpoint = call_and_retry_indefinitely(|| {
let merkle_tree_hook = self.merkle_tree_hook.clone();
Box::pin(async move { merkle_tree_hook.latest_checkpoint(self.reorg_period).await })
let reorg_period = self.reorg_period.clone();
Box::pin(async move { merkle_tree_hook.latest_checkpoint(&reorg_period).await })
})
.await;
@ -211,7 +211,7 @@ impl ValidatorSubmitter {
correctness_checkpoint.root,
checkpoint.index,
chrono::Utc::now().timestamp() as u64,
self.reorg_period.map(|x| x.get()).unwrap_or(0),
self.reorg_period.clone(),
);
error!(
?checkpoint,
@ -486,9 +486,9 @@ mod test {
#[async_trait]
impl MerkleTreeHook for MerkleTreeHook {
async fn tree(&self, lag: Option<NonZeroU64>) -> ChainResult<IncrementalMerkle>;
async fn count(&self, lag: Option<NonZeroU64>) -> ChainResult<u32>;
async fn latest_checkpoint(&self, lag: Option<NonZeroU64>) -> ChainResult<Checkpoint>;
async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult<IncrementalMerkle>;
async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32>;
async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult<Checkpoint>;
}
}
@ -532,7 +532,7 @@ mod test {
expected_local_merkle_tree: &IncrementalMerkle,
mock_onchain_merkle_tree: &IncrementalMerkle,
unix_timestamp: u64,
expected_reorg_period: u64,
expected_reorg_period: ReorgPeriod,
) {
assert_eq!(
reorg_event.canonical_merkle_root,
@ -617,7 +617,7 @@ mod test {
&expected_local_merkle_tree,
&mock_onchain_merkle_tree_clone,
unix_timestamp,
expected_reorg_period,
ReorgPeriod::from_blocks(expected_reorg_period),
);
Ok(())
});
@ -625,7 +625,7 @@ mod test {
// instantiate the validator submitter
let validator_submitter = ValidatorSubmitter::new(
Duration::from_secs(1),
expected_reorg_period,
ReorgPeriod::from_blocks(expected_reorg_period),
Arc::new(mock_merkle_tree_hook),
dummy_singleton_handle(),
Arc::new(mock_checkpoint_syncer),

@ -1,4 +1,4 @@
use std::{num::NonZeroU64, sync::Arc, time::Duration};
use std::{sync::Arc, time::Duration};
use crate::server as validator_server;
use async_trait::async_trait;
@ -19,8 +19,8 @@ use hyperlane_base::{
use hyperlane_core::{
Announcement, ChainResult, HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneSigner,
HyperlaneSignerExt, Mailbox, MerkleTreeHook, MerkleTreeInsertion, TxOutcome, ValidatorAnnounce,
H256, U256,
HyperlaneSignerExt, Mailbox, MerkleTreeHook, MerkleTreeInsertion, ReorgPeriod, TxOutcome,
ValidatorAnnounce, H256, U256,
};
use hyperlane_ethereum::{SingletonSigner, SingletonSignerHandle};
@ -44,7 +44,7 @@ pub struct Validator {
signer: SingletonSignerHandle,
// temporary holder until `run` is called
signer_instance: Option<Box<SingletonSigner>>,
reorg_period: u64,
reorg_period: ReorgPeriod,
interval: Duration,
checkpoint_syncer: Arc<dyn CheckpointSyncer>,
core_metrics: Arc<CoreMetrics>,
@ -184,12 +184,10 @@ impl BaseAgent for Validator {
// announce the validator after spawning the signer task
self.announce().await.expect("Failed to announce validator");
let reorg_period = NonZeroU64::new(self.reorg_period);
// Ensure that the merkle tree hook has count > 0 before we begin indexing
// messages or submitting checkpoints.
loop {
match self.merkle_tree_hook.count(reorg_period).await {
match self.merkle_tree_hook.count(&self.reorg_period).await {
Ok(0) => {
info!("Waiting for first message in merkle tree hook");
sleep(self.interval).await;
@ -241,7 +239,7 @@ impl Validator {
async fn run_checkpoint_submitters(&self) -> Vec<Instrumented<JoinHandle<()>>> {
let submitter = ValidatorSubmitter::new(
self.interval,
self.reorg_period,
self.reorg_period.clone(),
self.merkle_tree_hook.clone(),
self.signer.clone(),
self.checkpoint_syncer.clone(),
@ -249,10 +247,9 @@ impl Validator {
ValidatorSubmitterMetrics::new(&self.core.metrics, &self.origin_chain),
);
let reorg_period = NonZeroU64::new(self.reorg_period);
let tip_tree = self
.merkle_tree_hook
.tree(reorg_period)
.tree(&self.reorg_period)
.await
.expect("failed to get merkle tree");
// This function is only called after we have already checked that the

@ -8,7 +8,7 @@ use tracing::instrument;
use hyperlane_core::{
utils::bytes_to_hex, ChainResult, ContractLocator, HyperlaneChain, HyperlaneContract,
HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, Mailbox, RawHyperlaneMessage,
TxCostEstimate, TxOutcome, H256, U256,
ReorgPeriod, TxCostEstimate, TxOutcome, H256, U256,
};
use crate::grpc::WasmProvider;
@ -17,7 +17,7 @@ use crate::payloads::mailbox::{
GeneralMailboxQuery, ProcessMessageRequest, ProcessMessageRequestInner,
};
use crate::types::tx_response_to_outcome;
use crate::utils::get_block_height_for_lag;
use crate::utils::get_block_height_for_reorg_period;
use crate::{payloads, ConnectionConf, CosmosAddress, CosmosProvider, Signer};
#[derive(Clone, Debug)]
@ -82,8 +82,9 @@ impl HyperlaneChain for CosmosMailbox {
impl Mailbox for CosmosMailbox {
#[instrument(level = "debug", err, ret, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
async fn count(&self, lag: Option<NonZeroU64>) -> ChainResult<u32> {
let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?;
async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32> {
let block_height =
get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?;
self.nonce_at_block(block_height).await
}

@ -10,15 +10,15 @@ use hyperlane_core::accumulator::incremental::IncrementalMerkle;
use hyperlane_core::{
ChainCommunicationError, ChainResult, Checkpoint, ContractLocator, HyperlaneChain,
HyperlaneContract, HyperlaneDomain, HyperlaneProvider, Indexed, Indexer, LogMeta,
MerkleTreeHook, MerkleTreeInsertion, SequenceAwareIndexer, H256, H512,
MerkleTreeHook, MerkleTreeInsertion, ReorgPeriod, SequenceAwareIndexer, H256, H512,
};
use crate::grpc::WasmProvider;
use crate::payloads::{general, merkle_tree_hook};
use crate::rpc::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider};
use crate::utils::{
execute_and_parse_log_futures, get_block_height_for_lag, parse_logs_in_range, parse_logs_in_tx,
CONTRACT_ADDRESS_ATTRIBUTE_KEY, CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64,
execute_and_parse_log_futures, get_block_height_for_reorg_period, parse_logs_in_range,
parse_logs_in_tx, CONTRACT_ADDRESS_ATTRIBUTE_KEY, CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64,
};
use crate::{ConnectionConf, CosmosProvider, HyperlaneCosmosError, Signer};
@ -76,12 +76,13 @@ impl MerkleTreeHook for CosmosMerkleTreeHook {
/// Return the incremental merkle tree in storage
#[instrument(level = "debug", err, ret, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
async fn tree(&self, lag: Option<NonZeroU64>) -> ChainResult<IncrementalMerkle> {
async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult<IncrementalMerkle> {
let payload = merkle_tree_hook::MerkleTreeRequest {
tree: general::EmptyStruct {},
};
let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?;
let block_height =
get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?;
let data = self
.provider
@ -110,23 +111,26 @@ impl MerkleTreeHook for CosmosMerkleTreeHook {
}
/// Gets the current leaf count of the merkle tree
async fn count(&self, lag: Option<NonZeroU64>) -> ChainResult<u32> {
async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32> {
let payload = merkle_tree_hook::MerkleTreeCountRequest {
count: general::EmptyStruct {},
};
let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?;
let block_height =
get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?;
self.count_at_block(block_height).await
}
#[instrument(level = "debug", err, ret, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
async fn latest_checkpoint(&self, lag: Option<NonZeroU64>) -> ChainResult<Checkpoint> {
async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult<Checkpoint> {
let payload = merkle_tree_hook::CheckPointRequest {
check_point: general::EmptyStruct {},
};
let block_height = get_block_height_for_lag(self.provider.grpc(), lag).await?;
let block_height =
get_block_height_for_reorg_period(self.provider.grpc(), reorg_period).await?;
let data = self
.provider

@ -11,7 +11,7 @@ use tendermint::Hash;
use tokio::task::JoinHandle;
use tracing::warn;
use hyperlane_core::{ChainCommunicationError, ChainResult, Indexed, LogMeta, H256};
use hyperlane_core::{ChainCommunicationError, ChainResult, Indexed, LogMeta, ReorgPeriod, H256};
use crate::grpc::{WasmGrpcProvider, WasmProvider};
use crate::rpc::{CosmosWasmRpcProvider, ParsedEvent, WasmRpcProvider};
@ -24,20 +24,25 @@ pub(crate) const CONTRACT_ADDRESS_ATTRIBUTE_KEY: &str = "_contract_address";
pub(crate) static CONTRACT_ADDRESS_ATTRIBUTE_KEY_BASE64: Lazy<String> =
Lazy::new(|| BASE64.encode(CONTRACT_ADDRESS_ATTRIBUTE_KEY));
/// Given a lag, returns the block height at the moment.
/// If the lag is None, a block height of None is given, indicating that the
/// tip directly can be used.
pub(crate) async fn get_block_height_for_lag(
/// Given a `reorg_period`, returns the block height at the moment.
/// If the `reorg_period` is None, a block height of None is given,
/// indicating that the tip directly can be used.
pub(crate) async fn get_block_height_for_reorg_period(
provider: &WasmGrpcProvider,
lag: Option<NonZeroU64>,
reorg_period: &ReorgPeriod,
) -> ChainResult<Option<u64>> {
let block_height = match lag {
Some(lag) => {
let block_height = match reorg_period {
ReorgPeriod::Blocks(blocks) => {
let tip = provider.latest_block_height().await?;
let block_height = tip - lag.get();
let block_height = tip - blocks.get() as u64;
Some(block_height)
}
None => None,
ReorgPeriod::None => None,
ReorgPeriod::Tag(_) => {
return Err(ChainCommunicationError::InvalidReorgPeriod(
reorg_period.clone(),
))
}
};
Ok(block_height)

@ -1,4 +1,8 @@
use hyperlane_core::{config::OperationBatchConfig, U256};
use ethers::providers::Middleware;
use ethers_core::types::{BlockId, BlockNumber};
use hyperlane_core::{
config::OperationBatchConfig, ChainCommunicationError, ChainResult, ReorgPeriod, U256,
};
use url::Url;
/// Ethereum RPC connection configuration
@ -52,3 +56,51 @@ pub struct TransactionOverrides {
/// Max priority fee per gas to use for EIP-1559 transactions.
pub max_priority_fee_per_gas: Option<U256>,
}
/// Ethereum reorg period
#[derive(Copy, Clone, Debug)]
pub enum EthereumReorgPeriod {
/// Number of blocks
Blocks(u32),
/// A block tag
Tag(BlockId),
}
impl TryFrom<&ReorgPeriod> for EthereumReorgPeriod {
type Error = ChainCommunicationError;
fn try_from(value: &ReorgPeriod) -> Result<Self, Self::Error> {
match value {
ReorgPeriod::None => Ok(EthereumReorgPeriod::Blocks(0)),
ReorgPeriod::Blocks(blocks) => Ok(EthereumReorgPeriod::Blocks(blocks.get())),
ReorgPeriod::Tag(tag) => {
let tag = match tag.as_str() {
"latest" => BlockNumber::Latest,
"finalized" => BlockNumber::Finalized,
"safe" => BlockNumber::Safe,
"earliest" => BlockNumber::Earliest,
"pending" => BlockNumber::Pending,
_ => return Err(ChainCommunicationError::InvalidReorgPeriod(value.clone())),
};
Ok(EthereumReorgPeriod::Tag(tag.into()))
}
}
}
}
impl EthereumReorgPeriod {
/// Converts the reorg period into a block id
pub async fn into_block_id<M: Middleware + 'static>(
&self,
provider: &M,
) -> ChainResult<BlockId> {
let block_id = match self {
EthereumReorgPeriod::Blocks(_) => {
(crate::get_finalized_block_number(provider, self).await? as u64).into()
}
// no need to fetch the block number for the `tag`
EthereumReorgPeriod::Tag(tag) => *tag,
};
Ok(block_id)
}
}

@ -9,18 +9,18 @@ use async_trait::async_trait;
use ethers::prelude::Middleware;
use hyperlane_core::rpc_clients::call_and_retry_indefinitely;
use hyperlane_core::{
ChainCommunicationError, ChainResult, ContractLocator, HyperlaneAbi, HyperlaneChain,
HyperlaneContract, HyperlaneDomain, HyperlaneProvider, Indexed, Indexer,
InterchainGasPaymaster, InterchainGasPayment, LogMeta, SequenceAwareIndexer, H160, H256, H512,
ChainResult, ContractLocator, HyperlaneAbi, HyperlaneChain, HyperlaneContract, HyperlaneDomain,
HyperlaneProvider, Indexed, Indexer, InterchainGasPaymaster, InterchainGasPayment, LogMeta,
SequenceAwareIndexer, H160, H256, H512,
};
use tracing::instrument;
use super::utils::fetch_raw_logs_and_meta;
use super::utils::{fetch_raw_logs_and_meta, get_finalized_block_number};
use crate::interfaces::i_interchain_gas_paymaster::{
GasPaymentFilter, IInterchainGasPaymaster as EthereumInterchainGasPaymasterInternal,
IINTERCHAINGASPAYMASTER_ABI,
};
use crate::{BuildableWithProvider, ConnectionConf, EthereumProvider};
use crate::{BuildableWithProvider, ConnectionConf, EthereumProvider, EthereumReorgPeriod};
impl<M> Display for EthereumInterchainGasPaymasterInternal<M>
where
@ -33,7 +33,7 @@ where
pub struct InterchainGasPaymasterIndexerBuilder {
pub mailbox_address: H160,
pub reorg_period: u32,
pub reorg_period: EthereumReorgPeriod,
}
#[async_trait]
@ -63,7 +63,7 @@ where
{
contract: Arc<EthereumInterchainGasPaymasterInternal<M>>,
provider: Arc<M>,
reorg_period: u32,
reorg_period: EthereumReorgPeriod,
}
impl<M> EthereumInterchainGasPaymasterIndexer<M>
@ -71,7 +71,11 @@ where
M: Middleware + 'static,
{
/// Create new EthereumInterchainGasPaymasterIndexer
pub fn new(provider: Arc<M>, locator: &ContractLocator, reorg_period: u32) -> Self {
pub fn new(
provider: Arc<M>,
locator: &ContractLocator,
reorg_period: EthereumReorgPeriod,
) -> Self {
Self {
contract: Arc::new(EthereumInterchainGasPaymasterInternal::new(
locator.address,
@ -122,13 +126,7 @@ where
#[instrument(level = "debug", err, ret, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
async fn get_finalized_block_number(&self) -> ChainResult<u32> {
Ok(self
.provider
.get_block_number()
.await
.map_err(ChainCommunicationError::from_other)?
.as_u32()
.saturating_sub(self.reorg_period))
get_finalized_block_number(&self.provider, &self.reorg_period).await
}
async fn fetch_logs_by_tx_hash(

@ -2,7 +2,6 @@
#![allow(missing_docs)]
use std::collections::HashMap;
use std::num::NonZeroU64;
use std::ops::RangeInclusive;
use std::sync::Arc;
@ -14,7 +13,7 @@ use ethers_contract::builders::ContractCall;
use ethers_contract::{Multicall, MulticallResult};
use futures_util::future::join_all;
use hyperlane_core::rpc_clients::call_and_retry_indefinitely;
use hyperlane_core::{BatchResult, QueueOperation, H512};
use hyperlane_core::{BatchResult, QueueOperation, ReorgPeriod, H512};
use itertools::Itertools;
use tracing::instrument;
@ -31,11 +30,14 @@ use crate::interfaces::i_mailbox::{
IMailbox as EthereumMailboxInternal, ProcessCall, IMAILBOX_ABI,
};
use crate::interfaces::mailbox::DispatchFilter;
use crate::tx::{call_with_lag, fill_tx_gas_params, report_tx};
use crate::{BuildableWithProvider, ConnectionConf, EthereumProvider, TransactionOverrides};
use crate::tx::{call_with_reorg_period, fill_tx_gas_params, report_tx};
use crate::{
BuildableWithProvider, ConnectionConf, EthereumProvider, EthereumReorgPeriod,
TransactionOverrides,
};
use super::multicall::{self, build_multicall};
use super::utils::fetch_raw_logs_and_meta;
use super::utils::{fetch_raw_logs_and_meta, get_finalized_block_number};
impl<M> std::fmt::Display for EthereumMailboxInternal<M>
where
@ -47,7 +49,7 @@ where
}
pub struct SequenceIndexerBuilder {
pub reorg_period: u32,
pub reorg_period: EthereumReorgPeriod,
}
#[async_trait]
@ -70,7 +72,7 @@ impl BuildableWithProvider for SequenceIndexerBuilder {
}
pub struct DeliveryIndexerBuilder {
pub reorg_period: u32,
pub reorg_period: EthereumReorgPeriod,
}
#[async_trait]
@ -100,7 +102,7 @@ where
{
contract: Arc<EthereumMailboxInternal<M>>,
provider: Arc<M>,
reorg_period: u32,
reorg_period: EthereumReorgPeriod,
}
impl<M> EthereumMailboxIndexer<M>
@ -108,7 +110,11 @@ where
M: Middleware + 'static,
{
/// Create new EthereumMailboxIndexer
pub fn new(provider: Arc<M>, locator: &ContractLocator, reorg_period: u32) -> Self {
pub fn new(
provider: Arc<M>,
locator: &ContractLocator,
reorg_period: EthereumReorgPeriod,
) -> Self {
let contract = Arc::new(EthereumMailboxInternal::new(
locator.address,
provider.clone(),
@ -122,13 +128,7 @@ where
#[instrument(level = "debug", err, ret, skip(self))]
async fn get_finalized_block_number(&self) -> ChainResult<u32> {
Ok(self
.provider
.get_block_number()
.await
.map_err(ChainCommunicationError::from_other)?
.as_u32()
.saturating_sub(self.reorg_period))
get_finalized_block_number(&self.provider, &self.reorg_period).await
}
}
@ -460,8 +460,9 @@ where
M: Middleware + 'static,
{
#[instrument(skip(self))]
async fn count(&self, maybe_lag: Option<NonZeroU64>) -> ChainResult<u32> {
let call = call_with_lag(self.contract.nonce(), &self.provider, maybe_lag).await?;
async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32> {
let call =
call_with_reorg_period(self.contract.nonce(), &self.provider, reorg_period).await?;
let nonce = call.call().await?;
Ok(nonce)
}

@ -1,5 +1,4 @@
#![allow(missing_docs)]
use std::num::NonZeroU64;
use std::ops::RangeInclusive;
use std::sync::Arc;
@ -10,18 +9,18 @@ use hyperlane_core::rpc_clients::call_and_retry_indefinitely;
use tracing::instrument;
use hyperlane_core::{
ChainCommunicationError, ChainResult, Checkpoint, ContractLocator, HyperlaneChain,
HyperlaneContract, HyperlaneDomain, HyperlaneProvider, Indexed, Indexer, LogMeta,
MerkleTreeHook, MerkleTreeInsertion, SequenceAwareIndexer, H256, H512,
ChainResult, Checkpoint, ContractLocator, HyperlaneChain, HyperlaneContract, HyperlaneDomain,
HyperlaneProvider, Indexed, Indexer, LogMeta, MerkleTreeHook, MerkleTreeInsertion, ReorgPeriod,
SequenceAwareIndexer, H256, H512,
};
use crate::interfaces::merkle_tree_hook::{
InsertedIntoTreeFilter, MerkleTreeHook as MerkleTreeHookContract, Tree,
};
use crate::tx::call_with_lag;
use crate::{BuildableWithProvider, ConnectionConf, EthereumProvider};
use crate::tx::call_with_reorg_period;
use crate::{BuildableWithProvider, ConnectionConf, EthereumProvider, EthereumReorgPeriod};
use super::utils::fetch_raw_logs_and_meta;
use super::utils::{fetch_raw_logs_and_meta, get_finalized_block_number};
// We don't need the reverse of this impl, so it's ok to disable the clippy lint
#[allow(clippy::from_over_into)]
@ -58,7 +57,7 @@ impl BuildableWithProvider for MerkleTreeHookBuilder {
}
pub struct MerkleTreeHookIndexerBuilder {
pub reorg_period: u32,
pub reorg_period: EthereumReorgPeriod,
}
#[async_trait]
@ -88,7 +87,7 @@ where
{
contract: Arc<MerkleTreeHookContract<M>>,
provider: Arc<M>,
reorg_period: u32,
reorg_period: EthereumReorgPeriod,
}
impl<M> EthereumMerkleTreeHookIndexer<M>
@ -96,7 +95,11 @@ where
M: Middleware + 'static,
{
/// Create new EthereumMerkleTreeHookIndexer
pub fn new(provider: Arc<M>, locator: &ContractLocator, reorg_period: u32) -> Self {
pub fn new(
provider: Arc<M>,
locator: &ContractLocator,
reorg_period: EthereumReorgPeriod,
) -> Self {
Self {
contract: Arc::new(MerkleTreeHookContract::new(
locator.address,
@ -143,13 +146,7 @@ where
#[instrument(level = "debug", err, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
async fn get_finalized_block_number(&self) -> ChainResult<u32> {
Ok(self
.provider
.get_block_number()
.await
.map_err(ChainCommunicationError::from_other)?
.as_u32()
.saturating_sub(self.reorg_period))
get_finalized_block_number(&self.provider, &self.reorg_period).await
}
async fn fetch_logs_by_tx_hash(
@ -253,9 +250,13 @@ where
M: Middleware + 'static,
{
#[instrument(skip(self))]
async fn latest_checkpoint(&self, maybe_lag: Option<NonZeroU64>) -> ChainResult<Checkpoint> {
let call =
call_with_lag(self.contract.latest_checkpoint(), &self.provider, maybe_lag).await?;
async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult<Checkpoint> {
let call = call_with_reorg_period(
self.contract.latest_checkpoint(),
&self.provider,
reorg_period,
)
.await?;
let (root, index) = call.call().await?;
Ok(Checkpoint {
@ -268,15 +269,17 @@ where
#[instrument(skip(self))]
#[allow(clippy::needless_range_loop)]
async fn tree(&self, maybe_lag: Option<NonZeroU64>) -> ChainResult<IncrementalMerkle> {
let call = call_with_lag(self.contract.tree(), &self.provider, maybe_lag).await?;
async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult<IncrementalMerkle> {
let call =
call_with_reorg_period(self.contract.tree(), &self.provider, reorg_period).await?;
Ok(call.call().await?.into())
}
#[instrument(skip(self))]
async fn count(&self, maybe_lag: Option<NonZeroU64>) -> ChainResult<u32> {
let call = call_with_lag(self.contract.count(), &self.provider, maybe_lag).await?;
async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32> {
let call =
call_with_reorg_period(self.contract.count(), &self.provider, reorg_period).await?;
let count = call.call().await?;
Ok(count)
}

@ -1,5 +1,7 @@
pub use {interchain_gas::*, mailbox::*, merkle_tree_hook::*, validator_announce::*};
pub(crate) use utils::get_finalized_block_number;
mod interchain_gas;
mod mailbox;
mod merkle_tree_hook;

@ -6,7 +6,10 @@ use ethers::{
types::{H160 as EthersH160, H256 as EthersH256},
};
use ethers_contract::{ContractError, EthEvent, LogMeta as EthersLogMeta};
use hyperlane_core::{ChainResult, LogMeta, H512};
use hyperlane_core::{ChainCommunicationError, ChainResult, LogMeta, H512};
use tracing::instrument;
use crate::EthereumReorgPeriod;
pub async fn fetch_raw_logs_and_meta<T: EthEvent, M>(
tx_hash: H512,
@ -44,3 +47,33 @@ where
.collect();
Ok(logs)
}
#[instrument(level = "trace", err, ret, skip(provider))]
pub async fn get_finalized_block_number<M>(
provider: &M,
reorg_period: &EthereumReorgPeriod,
) -> ChainResult<u32>
where
M: Middleware + 'static,
{
let number = match *reorg_period {
EthereumReorgPeriod::Blocks(blocks) => provider
.get_block_number()
.await
.map_err(ChainCommunicationError::from_other)?
.as_u32()
.saturating_sub(blocks),
EthereumReorgPeriod::Tag(tag) => provider
.get_block(tag)
.await
.map_err(ChainCommunicationError::from_other)?
.and_then(|block| block.number)
.ok_or(ChainCommunicationError::CustomError(
"Unable to get finalized block number".into(),
))?
.as_u32(),
};
Ok(number)
}

@ -1,4 +1,3 @@
use std::num::NonZeroU64;
use std::sync::Arc;
use std::time::Duration;
@ -16,10 +15,12 @@ use ethers_core::{
EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE,
},
};
use hyperlane_core::{utils::bytes_to_hex, ChainCommunicationError, ChainResult, H256, U256};
use hyperlane_core::{
utils::bytes_to_hex, ChainCommunicationError, ChainResult, ReorgPeriod, H256, U256,
};
use tracing::{debug, error, info, warn};
use crate::{Middleware, TransactionOverrides};
use crate::{EthereumReorgPeriod, Middleware, TransactionOverrides};
/// An amount of gas to add to the estimated gas
pub const GAS_ESTIMATE_BUFFER: u32 = 75_000;
@ -216,23 +217,20 @@ where
Ok((base_fee_per_gas, max_fee_per_gas, max_priority_fee_per_gas))
}
pub(crate) async fn call_with_lag<M, T>(
pub(crate) async fn call_with_reorg_period<M, T>(
call: ethers::contract::builders::ContractCall<M, T>,
provider: &M,
maybe_lag: Option<NonZeroU64>,
reorg_period: &ReorgPeriod,
) -> ChainResult<ethers::contract::builders::ContractCall<M, T>>
where
M: Middleware + 'static,
T: Detokenize,
{
if let Some(lag) = maybe_lag {
let fixed_block_number: BlockNumber = provider
.get_block_number()
.await
.map_err(ChainCommunicationError::from_other)?
.saturating_sub(lag.get().into())
.into();
Ok(call.block(fixed_block_number))
if !reorg_period.is_none() {
let block_id = EthereumReorgPeriod::try_from(reorg_period)?
.into_block_id(provider)
.await?;
Ok(call.block(block_id))
} else {
Ok(call)
}

@ -10,13 +10,12 @@ use fuels::{
use hyperlane_core::{
utils::bytes_to_hex, ChainCommunicationError, ChainResult, ContractLocator, HyperlaneAbi,
HyperlaneChain, HyperlaneContract, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider,
Indexed, Indexer, LogMeta, Mailbox, RawHyperlaneMessage, SequenceAwareIndexer, TxCostEstimate,
TxOutcome, H256, H512, U256,
Indexed, Indexer, LogMeta, Mailbox, RawHyperlaneMessage, ReorgPeriod, SequenceAwareIndexer,
TxCostEstimate, TxOutcome, H256, H512, U256,
};
use std::{
collections::HashMap,
fmt::{Debug, Formatter},
num::NonZeroU64,
ops::RangeInclusive,
};
use tracing::{instrument, warn};
@ -74,9 +73,9 @@ impl Debug for FuelMailbox {
impl Mailbox for FuelMailbox {
#[instrument(level = "debug", err, ret, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
async fn count(&self, lag: Option<NonZeroU64>) -> ChainResult<u32> {
async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32> {
assert!(
lag.is_none(),
reorg_period.is_none(),
"Fuel does not support querying point-in-time"
);
self.contract

@ -12,8 +12,8 @@ use hyperlane_core::{
ChainCommunicationError::ContractError, ChainResult, Checkpoint, ContractLocator, Decode as _,
Encode as _, FixedPointNumber, HyperlaneAbi, HyperlaneChain, HyperlaneContract,
HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, Indexed, Indexer, KnownHyperlaneDomain,
LogMeta, Mailbox, MerkleTreeHook, SequenceAwareIndexer, TxCostEstimate, TxOutcome, H256, H512,
U256,
LogMeta, Mailbox, MerkleTreeHook, ReorgPeriod, SequenceAwareIndexer, TxCostEstimate, TxOutcome,
H256, H512, U256,
};
use hyperlane_sealevel_interchain_security_module_interface::{
InterchainSecurityModuleInstruction, VerifyInstruction,
@ -416,8 +416,8 @@ impl std::fmt::Debug for SealevelMailbox {
#[async_trait]
impl Mailbox for SealevelMailbox {
#[instrument(err, ret, skip(self))]
async fn count(&self, _maybe_lag: Option<NonZeroU64>) -> ChainResult<u32> {
<Self as MerkleTreeHook>::count(self, _maybe_lag).await
async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32> {
<Self as MerkleTreeHook>::count(self, reorg_period).await
}
#[instrument(err, ret, skip(self))]
@ -755,7 +755,7 @@ impl SequenceAwareIndexer<HyperlaneMessage> for SealevelMailboxIndexer {
async fn latest_sequence_count_and_tip(&self) -> ChainResult<(Option<u32>, u32)> {
let tip = Indexer::<HyperlaneMessage>::get_finalized_block_number(self).await?;
// TODO: need to make sure the call and tip are at the same height?
let count = Mailbox::count(&self.mailbox, None).await?;
let count = Mailbox::count(&self.mailbox, &ReorgPeriod::None).await?;
Ok((Some(count), tip))
}
}

@ -1,11 +1,11 @@
use std::{num::NonZeroU64, ops::RangeInclusive};
use std::ops::RangeInclusive;
use async_trait::async_trait;
use derive_new::new;
use hyperlane_core::{
accumulator::incremental::IncrementalMerkle, ChainCommunicationError, ChainResult, Checkpoint,
HyperlaneChain, HyperlaneMessage, Indexed, Indexer, LogMeta, MerkleTreeHook,
MerkleTreeInsertion, SequenceAwareIndexer,
MerkleTreeInsertion, ReorgPeriod, SequenceAwareIndexer,
};
use hyperlane_sealevel_mailbox::accounts::OutboxAccount;
use tracing::instrument;
@ -16,9 +16,9 @@ use crate::{SealevelMailbox, SealevelMailboxIndexer};
impl MerkleTreeHook for SealevelMailbox {
#[instrument(err, ret, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
async fn tree(&self, lag: Option<NonZeroU64>) -> ChainResult<IncrementalMerkle> {
async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult<IncrementalMerkle> {
assert!(
lag.is_none(),
reorg_period.is_none(),
"Sealevel does not support querying point-in-time"
);
@ -35,13 +35,13 @@ impl MerkleTreeHook for SealevelMailbox {
#[instrument(err, ret, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
async fn latest_checkpoint(&self, lag: Option<NonZeroU64>) -> ChainResult<Checkpoint> {
async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult<Checkpoint> {
assert!(
lag.is_none(),
reorg_period.is_none(),
"Sealevel does not support querying point-in-time"
);
let tree = self.tree(lag).await?;
let tree = self.tree(reorg_period).await?;
let root = tree.root();
let count: u32 = tree
@ -64,8 +64,8 @@ impl MerkleTreeHook for SealevelMailbox {
#[instrument(err, ret, skip(self))]
#[allow(clippy::blocks_in_conditions)] // TODO: `rustc` 1.80.1 clippy issue
async fn count(&self, _maybe_lag: Option<NonZeroU64>) -> ChainResult<u32> {
let tree = self.tree(_maybe_lag).await?;
async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32> {
let tree = self.tree(reorg_period).await?;
tree.count()
.try_into()

@ -34,7 +34,7 @@
"interchainAccountIsm": "0xd766e7C7517f2d0D92754b2fe4aE7AdEf7bDEC3e",
"interchainAccountRouter": "0x25C87e735021F72d8728438C2130b02E3141f2cb",
"interchainGasPaymaster": "0x8F1E22d309baa69D398a03cc88E9b46037e988AA",
"interchainSecurityModule": "0x565C280Cdb56095Cf6BF23b5fF140180208CBa9e",
"interchainSecurityModule": "0x4e1d2cdB48A2C2912b11801Eb1F1d5007474cA43",
"isTestnet": false,
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x811808Dd29ba8B0FC6C0ec0b5537035E59745162",
@ -100,7 +100,7 @@
"interchainAccountIsm": "0x2A7574358Ec53522CE2452887661AB4c86F7d400",
"interchainAccountRouter": "0x91874Dbed74925dFe6059B90385EEb90DdE0B2E6",
"interchainGasPaymaster": "0x3b6044acd6767f017e99318AA6Ef93b7B06A5a22",
"interchainSecurityModule": "0x3d0BE14dFbB1Eb736303260c1724B6ea270c8Dc4",
"interchainSecurityModule": "0x50d0b0E27B8B93119618f053A623886116dd3b6d",
"mailbox": "0x979Ca5202784112f4738403dBec5D0F3B9daabB9",
"merkleTreeHook": "0x748040afB89B8FdBb992799808215419d36A0930",
"name": "arbitrum",
@ -172,7 +172,7 @@
"interchainAccountIsm": "0x27a3233c05C1Df7c163123301D14bE9349E3Cb48",
"interchainAccountRouter": "0xa82a0227e6d6db53AF4B264A852bfF91C6504a51",
"interchainGasPaymaster": "0x95519ba800BBd0d34eeAE026fEc620AD978176C0",
"interchainSecurityModule": "0x6723A49c12FE37ccBD08512dd586C8471743676f",
"interchainSecurityModule": "0xbc803Da34A88E5f6B50dfc0CC9D924d9865c91C5",
"mailbox": "0xFf06aFcaABaDDd1fb08371f9ccA15D73D51FeBD6",
"merkleTreeHook": "0x84eea61D679F42D92145fA052C89900CBAccE95A",
"name": "avalanche",
@ -245,7 +245,7 @@
"interchainAccountIsm": "0x223F7D3f27E6272266AE4B5B91Fd5C7A2d798cD8",
"interchainAccountRouter": "0x4767D22117bBeeb295413000B620B93FD8522d53",
"interchainGasPaymaster": "0xc3F23848Ed2e04C0c6d41bd7804fa8f89F940B94",
"interchainSecurityModule": "0xaeEf8f7D049C03181E0B5f2746CA2Db4d25C0B82",
"interchainSecurityModule": "0xB7fcb4665ace2B0d36fd92D26b4a8B516c0bFe5F",
"mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"merkleTreeHook": "0x19dc38aeae620380430C200a6E990D5Af5480117",
"name": "base",
@ -316,7 +316,7 @@
"interchainAccountIsm": "0xe93f2f409ad8B5000431D234472973fe848dcBEC",
"interchainAccountRouter": "0x2f4Eb04189e11Af642237Da62d163Ab714614498",
"interchainGasPaymaster": "0xB3fCcD379ad66CED0c91028520C64226611A48c9",
"interchainSecurityModule": "0xbCe3469E8C270e04ea9ccd20Efdeed2b90c9d57C",
"interchainSecurityModule": "0xECa4a584E91867a72cd036DB7Db22Ad894a197B7",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0xC9B8ea6230d6687a4b13fD3C0b8f0Ec607B26465",
"name": "blast",
@ -384,7 +384,7 @@
"interchainAccountIsm": "0x451dF8AB0936D85526D816f0b4dCaDD934A034A4",
"interchainAccountRouter": "0x5C02157068a52cEcfc98EDb6115DE6134EcB4764",
"interchainGasPaymaster": "0x62B7592C1B6D1E43f4630B8e37f4377097840C05",
"interchainSecurityModule": "0x26eA240CB4cABd7B75A9F17E7f4e224170270Ee3",
"interchainSecurityModule": "0x93E3e6CA295803417212421785606B1F7dDeaD8f",
"mailbox": "0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147",
"merkleTreeHook": "0x781bE492F1232E66990d83a9D3AC3Ec26f56DAfB",
"name": "bob",
@ -450,7 +450,7 @@
"interchainAccountIsm": "0x9e22945bE593946618383B108CC5bce09eBA4C26",
"interchainAccountRouter": "0x32A07c1B7a7fe8D4A0e44B0181873aB9d64C16c1",
"interchainGasPaymaster": "0x78E25e7f84416e69b9339B0A6336EB6EFfF6b451",
"interchainSecurityModule": "0x0A7cE15E3cc638abC3B5FfA7Fc8F3295Ae3595D1",
"interchainSecurityModule": "0xA0506B5b12770494740A4a7cc86C9A36Dc1Fc6Dc",
"mailbox": "0x2971b9Aec44bE4eb673DF1B88cDB57b96eefe8a4",
"merkleTreeHook": "0xFDb9Cd5f9daAA2E4474019405A328a88E7484f26",
"name": "bsc",
@ -531,7 +531,7 @@
"interchainAccountIsm": "0xB732c83aeE29596E3163Da2260710eAB67Bc0B29",
"interchainAccountRouter": "0x27a6cAe33378bB6A6663b382070427A01fc9cB37",
"interchainGasPaymaster": "0x571f1435613381208477ac5d6974310d88AC7cB7",
"interchainSecurityModule": "0x33BC62504248F4cb43813532067ccAEd46a5e61C",
"interchainSecurityModule": "0xa6f4835940dbA46E295076D0CD0411349C33789f",
"mailbox": "0x50da3B3907A08a24fe4999F4Dcf337E8dC7954bb",
"merkleTreeHook": "0x04dB778f05854f26E67e0a66b740BBbE9070D366",
"name": "celo",
@ -596,7 +596,7 @@
"interchainAccountIsm": "0x4Eb82Ee35b0a1c1d776E3a3B547f9A9bA6FCC9f2",
"interchainAccountRouter": "0xEF9A332Ec1fD233Bf9344A58be56ff9E104B4f60",
"interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503",
"interchainSecurityModule": "0xc1FF2bf7a4C315bE2a06941D236457EB02F93993",
"interchainSecurityModule": "0x05f6BAa16F1aCf7b19c4A09E019D856c10ab8355",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD",
"name": "cheesechain",
@ -659,7 +659,7 @@
"from": 4842212
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xEfFaEddFf4FFd6F8a6D714bf149b114fD34E5Fd4",
"interchainSecurityModule": "0x9A746C4BC2bE7E657A3469f0a0DAA1dE517b8514",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "cyber",
@ -726,7 +726,7 @@
"from": 23783929
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xB5e6AA45E117f9fD2a3F8e78432fCAfdB833d316",
"interchainSecurityModule": "0x168E9C1481F50E66Cc5F5E24b04eBf7071629c4E",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "degenchain",
@ -784,7 +784,8 @@
"gasCurrencyCoinGeckoId": "ethereum",
"index": {
"from": 1,
"mode": "sequence"
"mode": "sequence",
"chunk": 100
},
"interchainGasPaymaster": "ABb3i11z7wKoGCfeRQNQbVYWjAm7jG7HzZnDLV4RKRbK",
"mailbox": "EitxJuv2iBjsg2d7jVy2LDC1e2zBrx4GB5Y9h2Ko3A9Y",
@ -838,7 +839,7 @@
"interchainAccountIsm": "0xCeafc098e5c3c7768b9229Be2FEC275862A81Abd",
"interchainAccountRouter": "0xed9a722c543883FB7e07E78F3879762DE09eA7D5",
"interchainGasPaymaster": "0xB30EAB08aa87138D57168D0e236850A530f49921",
"interchainSecurityModule": "0xC0737f1EA1d0aF287c2804090370b1715c593385",
"interchainSecurityModule": "0x094120BaC576aD7D88ec6893C9B220a0e64923E9",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xC831271c1fB212012811a91Dd43e5926C1020563",
"name": "endurance",
@ -909,7 +910,7 @@
"interchainAccountIsm": "0x292C614ED53DaaDBf971521bc2C652d1ca51cB47",
"interchainAccountRouter": "0x5E532F7B610618eE73C2B462978e94CB1F7995Ce",
"interchainGasPaymaster": "0x9e6B1022bE9BBF5aFd152483DAD9b88911bC8611",
"interchainSecurityModule": "0xFc440a9c946Bf4840623E4adf49646089361584a",
"interchainSecurityModule": "0x23d160e4474Ce011829c71Bf1bCaA40F0b5612D5",
"mailbox": "0xc005dc82818d67AF737725bD4bf75435d065D239",
"merkleTreeHook": "0x48e6c30B97748d1e2e03bf3e9FbE3890ca5f8CCA",
"name": "ethereum",
@ -978,7 +979,7 @@
"interchainAccountIsm": "0x7C012DCA02C42cfA3Fd7Da3B0ED7234B52AE68eF",
"interchainAccountRouter": "0xbed53B5C5BCE9433f25A2A702e6df13E22d84Ae9",
"interchainGasPaymaster": "0x2Fca7f6eC3d4A0408900f2BB30004d4616eE985E",
"interchainSecurityModule": "0x2bed66bbfE45f1d73928179e72B73e5eCF7B9900",
"interchainSecurityModule": "0x8B497dff421844Bb0882E0C495d0851D4461675C",
"mailbox": "0x2f9DB5616fa3fAd1aB06cB2C906830BA63d135e3",
"merkleTreeHook": "0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147",
"name": "fraxtal",
@ -1046,7 +1047,7 @@
"interchainAccountIsm": "0x9629c28990F11c31735765A6FD59E1E1bC197DbD",
"interchainAccountRouter": "0x2351FBe24C1212F253b7a300ff0cBCFd97952a19",
"interchainGasPaymaster": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainSecurityModule": "0x1E12bdb6a33442102FEF2ab766b93c863653B4bE",
"interchainSecurityModule": "0x69b33D67B9C51D45E23d22E727FF186DD6298ECA",
"mailbox": "0x3071D4DA6020C956Fe15Bfd0a9Ca8D4574f16696",
"merkleTreeHook": "0xfBc08389224d23b79cb21cDc16c5d42F0ad0F57f",
"name": "fusemainnet",
@ -1120,7 +1121,7 @@
"interchainAccountIsm": "0x07E2062A1bC66a2C1d05cb5C3870a4AF86e0056E",
"interchainAccountRouter": "0xBE70Ab882D1F7E37e04a70CDd9Ec23b37a234064",
"interchainGasPaymaster": "0xDd260B99d302f0A3fF885728c086f729c06f227f",
"interchainSecurityModule": "0x996Be332325DA49Ea590A9772a515d62dD90C74c",
"interchainSecurityModule": "0x00533a5F14B3a0632C86f99E4e20a10b73C4AE0D",
"mailbox": "0xaD09d78f4c6b9dA2Ae82b1D34107802d380Bb74f",
"merkleTreeHook": "0x2684C6F89E901987E1FdB7649dC5Be0c57C61645",
"name": "gnosis",
@ -1183,7 +1184,7 @@
"domainId": 2525,
"domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730",
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xA376b27212D608324808923Add679A2c9FAFe9Da",
"fallbackRoutingHook": "0xf8dba46ff9d8ef650052c89ca2df793fabc375f9",
"gasCurrencyCoinGeckoId": "injective-protocol",
"index": {
"from": 37
@ -1191,7 +1192,7 @@
"interchainAccountIsm": "0x708E002637792FDC031E6B62f23DD60014AC976a",
"interchainAccountRouter": "0xfB8cea1c7F45608Da30655b50bbF355D123A4358",
"interchainGasPaymaster": "0x19dc38aeae620380430C200a6E990D5Af5480117",
"interchainSecurityModule": "0x1Bff27a1c1319b0704348895b67426a4Eb1b629e",
"interchainSecurityModule": "0xB8F85B879775adF156Dd4AFa43e97DeB880d99D4",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x0972954923a1e2b2aAb04Fa0c4a0797e5989Cd65",
"name": "inevm",
@ -1228,7 +1229,14 @@
},
"injective": {
"bech32Prefix": "inj",
"blockExplorers": [],
"blockExplorers": [
{
"apiUrl": "https://www.mintscan.io/injective",
"family": "other",
"name": "Mintscan",
"url": "https://www.mintscan.io/injective"
}
],
"blocks": {
"confirmations": 1,
"estimateBlockTime": 1,
@ -1312,7 +1320,7 @@
"from": 14616307
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xcaE599dD2142CD8F09a68bAC89b4d809A038d2E9",
"interchainSecurityModule": "0xE2968dAb74541184Ad95651b1e5Cf34Ab1bBEc97",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "kroma",
@ -1385,7 +1393,7 @@
"interchainAccountIsm": "0xdcA646C56E7768DD11654956adE24bfFf9Ba4893",
"interchainAccountRouter": "0xD59dA396F162Ed93a41252Cebb8d5DD4F093238C",
"interchainGasPaymaster": "0x8105a095368f1a184CceA86cCe21318B5Ee5BE28",
"interchainSecurityModule": "0x916e612358dA3F7E8e19f51ba2Cf7af3285a6793",
"interchainSecurityModule": "0x0EEF1e64646EE01DeED4850074Cd4B97C0A630a9",
"mailbox": "0x02d16BC51af6BfD153d67CA61754cF912E82C4d9",
"merkleTreeHook": "0xC077A0Cc408173349b1c9870C667B40FE3C01dd7",
"name": "linea",
@ -1456,7 +1464,7 @@
"from": 4195553
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xa660FA2047105E0341b356393218586ED2191d14",
"interchainSecurityModule": "0x63Bb509b9CA644609B15Ea55E56f0Acbbb9dB02E",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "lisk",
@ -1520,7 +1528,7 @@
"from": 3088760
},
"interchainGasPaymaster": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"interchainSecurityModule": "0x391BD8dD2709F77d39dab4fB3bf4BCAfd5EC3248",
"interchainSecurityModule": "0x609ad94304896607A6D81DB00d882245045B79da",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x062200d92dF6bB7bA89Ce4D6800110450f94784e",
"name": "lukso",
@ -1594,7 +1602,7 @@
"interchainAccountIsm": "0x8Ea50255C282F89d1A14ad3F159437EE5EF0507f",
"interchainAccountRouter": "0x693A4cE39d99e46B04cb562329e3F0141cA17331",
"interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4",
"interchainSecurityModule": "0xBcB96842301c659B575c40C3f93F7311D09c93d9",
"interchainSecurityModule": "0xC012e8E3cBeB6295E1E4837FBA5DB8E077EBc549",
"isTestnet": false,
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112",
@ -1664,7 +1672,7 @@
"interchainAccountIsm": "0xe039DA3A0071BEd087A12660D7b03cf669c7776E",
"interchainAccountRouter": "0x45285463352c53a481e882cD5E2AF2E25BBdAd0D",
"interchainGasPaymaster": "0x8105a095368f1a184CceA86cCe21318B5Ee5BE28",
"interchainSecurityModule": "0xe542Ed13B5782aF0AFAe7f232bB867FB0208Ab7B",
"interchainSecurityModule": "0x8722328A5Ed815965F9B5eBAA21d04f0F9BFDd35",
"mailbox": "0x398633D19f4371e1DB5a8EFE90468eB70B1176AA",
"merkleTreeHook": "0x5332D1AC0A626D265298c14ff681c0A8D28dB86d",
"name": "mantle",
@ -1726,7 +1734,7 @@
"from": 13523607
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0x5725a9Bf3bdaF104Ce1A0098308DD974F6395365",
"interchainSecurityModule": "0xE8176Fc70f129255aA83d3db242C2246Ad77Af7D",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "merlin",
@ -1793,7 +1801,7 @@
"from": 17966274
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xfd810678075502F76A6ef79cedffe58cff6Cc410",
"interchainSecurityModule": "0xA9309228762699D5c81A4b0BAfd06Da21589746b",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "metis",
@ -1858,7 +1866,7 @@
"from": 3752032
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xfd810678075502F76A6ef79cedffe58cff6Cc410",
"interchainSecurityModule": "0xA9309228762699D5c81A4b0BAfd06Da21589746b",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "mint",
@ -1925,7 +1933,7 @@
"interchainAccountIsm": "0xa377b8269e0A47cdd2fD5AAeAe860b45623c6d82",
"interchainAccountRouter": "0x6e1B9f776bd415d7cC3C7458A5f0d801016918f8",
"interchainGasPaymaster": "0x931dFCc8c1141D6F532FD023bd87DAe0080c835d",
"interchainSecurityModule": "0x1ab6985E0e15d293e71d01510fa6B57311C69718",
"interchainSecurityModule": "0x0777dFffcEd18EE416e35401E0e5e0413b7D43be",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xE2ee936bEa8e42671c400aC96dE198E06F2bA2A6",
"name": "mode",
@ -1993,7 +2001,7 @@
"interchainAccountIsm": "0x79b3730CE3685f65802aF1771319992bA960EB9D",
"interchainAccountRouter": "0xc4482f66191754a8629D35289043C4EB0285F10E",
"interchainGasPaymaster": "0x14760E32C0746094cF14D97124865BC7F0F7368F",
"interchainSecurityModule": "0x105215D46F45a88B3793B798Fb87AF231Ad9f611",
"interchainSecurityModule": "0xad1Ad827035eDe500aFd0ff122c53f6eA607Eb5C",
"mailbox": "0x094d03E751f49908080EFf000Dd6FD177fd44CC3",
"merkleTreeHook": "0x87403b85f6f316e7ba91ba1fa6C3Fb7dD4095547",
"name": "moonbeam",
@ -2135,7 +2143,7 @@
"interchainAccountIsm": "0x2c46BF14641d00549ECa4779BF5CBf91602C1DEd",
"interchainAccountRouter": "0x03D6cC17d45E9EA27ED757A8214d1F07F7D901aD",
"interchainGasPaymaster": "0xD8A76C4D91fCbB7Cc8eA795DFDF870E48368995C",
"interchainSecurityModule": "0x1E491c93Ab56A298bBC34B4Fca8A4cE68E8d540a",
"interchainSecurityModule": "0x3878aB31B2426A92E8a1E0AE758d848879F7F5E8",
"mailbox": "0xd4C1905BB1D26BC93DAC913e13CaCC278CdCC80D",
"merkleTreeHook": "0x68eE9bec9B4dbB61f69D9D293Ae26a5AACb2e28f",
"name": "optimism",
@ -2270,7 +2278,7 @@
"interchainAccountIsm": "0xBAC4529cdfE7CCe9E858BF706e41F8Ed096C1BAd",
"interchainAccountRouter": "0xF163949AD9F88977ebF649D0461398Ca752E64B9",
"interchainGasPaymaster": "0x0071740Bf129b05C4684abfbBeD248D80971cce2",
"interchainSecurityModule": "0x0D408EF040ca0E7a75f03c41Aa46cAc904770D45",
"interchainSecurityModule": "0x9fFC02BfB5C7260C985b005C0cF40d7EC601aac2",
"mailbox": "0x5d934f4e2f797775e53561bB72aca21ba36B96BB",
"merkleTreeHook": "0x73FbD25c3e817DC4B4Cd9d00eff6D83dcde2DfF6",
"name": "polygon",
@ -2347,7 +2355,7 @@
"interchainAccountIsm": "0xc1198e241DAe48BF5AEDE5DCE49Fe4A6064cF7a7",
"interchainAccountRouter": "0x20a0A32a110362920597F72974E1E0d7e25cA20a",
"interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4",
"interchainSecurityModule": "0x5C622f40365F57D06b5e7132B1483fcbc9566560",
"interchainSecurityModule": "0xc6c475184F197FA65f233dFc22FA6bD4cE48B4fE",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112",
"name": "polygonzkevm",
@ -2415,7 +2423,7 @@
"from": 32018468
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0x336306ADB3c510A318107c01D109D2072c7abB6B",
"interchainSecurityModule": "0x70e8beCE806914959c1B5D8F75d2217058D31437",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "proofofplay",
@ -2479,7 +2487,7 @@
"from": 363159
},
"interchainGasPaymaster": "0x3071D4DA6020C956Fe15Bfd0a9Ca8D4574f16696",
"interchainSecurityModule": "0x06567d07b49ad922A821A641F1C962569a255dbB",
"interchainSecurityModule": "0x43346a54445BBdf8241062904E8A13AA62842a02",
"mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"merkleTreeHook": "0x55E4F0bc6b7Bb493D50839A8592e7ad8d5e93cf7",
"name": "real",
@ -2546,7 +2554,7 @@
"interchainAccountIsm": "0x5DA60220C5dDe35b7aE91c042ff5979047FA0785",
"interchainAccountRouter": "0x7a4d31a686A36285d68e14EDD53631417eB19603",
"interchainGasPaymaster": "0x2Fa570E83009eaEef3a1cbd496a9a30F05266634",
"interchainSecurityModule": "0x5a3bB91853CfDaDb1bC95D2E061B50d433fbe3E8",
"interchainSecurityModule": "0xd8b6B632526834D8192860e6B6CE47165Fd02a42",
"mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"merkleTreeHook": "0x8F1E22d309baa69D398a03cc88E9b46037e988AA",
"name": "redstone",
@ -2608,7 +2616,7 @@
"from": 937117
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xA76F4620ac1e97d273B2C9Ca71805c8afD792098",
"interchainSecurityModule": "0x6A2748201F66647ad6D164CB3340A893881A4bb2",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "sanko",
@ -2676,7 +2684,7 @@
"interchainAccountIsm": "0x32af5Df81fEd5E26119F6640FBB13f3d63a94CDe",
"interchainAccountRouter": "0x0B48a744698ba8dFa514742dFEB6728f52fD66f7",
"interchainGasPaymaster": "0xBF12ef4B9f307463D3FB59c3604F294dDCe287E2",
"interchainSecurityModule": "0x37e17723b665A9F95F4aecEEc40D9eF39624764e",
"interchainSecurityModule": "0xAd1a987BfE0D6fbD92089628daC7C7e4bA9a6AAF",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x6119E37Bd66406A1Db74920aC79C15fB8411Ba76",
"name": "scroll",
@ -2744,7 +2752,7 @@
"interchainAccountIsm": "0xf35dc7B9eE4Ebf0cd3546Bd6EE3b403dE2b9F5D6",
"interchainAccountRouter": "0xBcaedE97a98573A88242B3b0CB0A255F3f90d4d5",
"interchainGasPaymaster": "0xFC62DeF1f08793aBf0E67f69257c6be258194F72",
"interchainSecurityModule": "0x26184898fA27D3471B50BD956AB5b3E9Aa14763C",
"interchainSecurityModule": "0x494028EA206642e4c60Ec3d12e96B4549E5e1800",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xca1b69fA4c4a7c7fD839bC50867c589592bcfe49",
"name": "sei",
@ -2804,7 +2812,8 @@
"gasCurrencyCoinGeckoId": "solana",
"index": {
"from": 1,
"mode": "sequence"
"mode": "sequence",
"chunk": 100
},
"interchainGasPaymaster": "JAvHW21tYXE9dtdG83DReqU2b4LUexFuCbtJT5tF8X6M",
"mailbox": "E588QtVUvresuXq2KoNEwAmoifCzYGpRBdHByN9KQMbi",
@ -2858,7 +2867,7 @@
"interchainAccountIsm": "0xAE557e108b3336130370aC74836f1356B4b30Cf2",
"interchainAccountRouter": "0x1F8CF09F060A2AE962c0Bb1F92e209a1E7b0E10B",
"interchainGasPaymaster": "0x273Bc6b01D9E88c064b6E5e409BdF998246AEF42",
"interchainSecurityModule": "0x478D0e5d221C8d7CA1A6353315fac6FA88Ff1B97",
"interchainSecurityModule": "0xC93F2796A17Ee4580c039aeB7b0c923b10ce79C2",
"mailbox": "0x28EFBCadA00A7ed6772b3666F3898d276e88CAe3",
"merkleTreeHook": "0x6A55822cf11f9fcBc4c75BC2638AfE8Eb942cAdd",
"name": "taiko",
@ -2920,7 +2929,7 @@
"from": 1678063
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0x336306ADB3c510A318107c01D109D2072c7abB6B",
"interchainSecurityModule": "0x70e8beCE806914959c1B5D8F75d2217058D31437",
"isTestnet": false,
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
@ -2988,7 +2997,7 @@
"interchainAccountIsm": "0x551BbEc45FD665a8C95ca8731CbC32b7653Bc59B",
"interchainAccountRouter": "0xc11f8Cf2343d3788405582F65B8af6A4F7a6FfC8",
"interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4",
"interchainSecurityModule": "0x5542503cBde841c336Afef014FE80b0F1c9d716d",
"interchainSecurityModule": "0x3465AccC39AE5e6C344184013a57cDCe546834d6",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112",
"name": "viction",
@ -3056,7 +3065,7 @@
"interchainAccountIsm": "0xCB9f90EE5d83Ea52ABd922BD70898f0155D54798",
"interchainAccountRouter": "0x473884010F0C1742DA8Ad01E7E295624B931076b",
"interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503",
"interchainSecurityModule": "0xc1FF2bf7a4C315bE2a06941D236457EB02F93993",
"interchainSecurityModule": "0x05f6BAa16F1aCf7b19c4A09E019D856c10ab8355",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD",
"name": "worldchain",
@ -3118,7 +3127,7 @@
"from": 24395308
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xC630ef37e03534721557026FeC397Ec05f85584C",
"interchainSecurityModule": "0x4886ed96bcdba2ad85Bf518C3171C39e256ac840",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "xai",
@ -3186,7 +3195,7 @@
"interchainAccountIsm": "0x29B37088724B745C0ABcE591449Cf042772160C2",
"interchainAccountRouter": "0x03cF708E42C89623bd83B281A56935cB562b9258",
"interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503",
"interchainSecurityModule": "0x0811C6250965E7Ba1A872A12249B1b2300d85CFD",
"interchainSecurityModule": "0x59B0ec92522F164b72c9BE473382197c564B92dc",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD",
"name": "xlayer",
@ -3254,7 +3263,7 @@
"interchainAccountIsm": "0x2b6d3F7d28B5EC8C3C028fBCAdcf774D9709Dd29",
"interchainAccountRouter": "0x3AdCBc94ab8C48EC52D06dc65Bb787fD1981E3d5",
"interchainGasPaymaster": "0x931dFCc8c1141D6F532FD023bd87DAe0080c835d",
"interchainSecurityModule": "0x858a077945bCC4afA40DaE5a75faB9237e899b30",
"interchainSecurityModule": "0xd32353Ae5719ac4f8f24AeD81A2A6898d2632D26",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xE2ee936bEa8e42671c400aC96dE198E06F2bA2A6",
"name": "zetachain",
@ -3320,7 +3329,7 @@
"from": 1511458
},
"interchainGasPaymaster": "0x03cF708E42C89623bd83B281A56935cB562b9258",
"interchainSecurityModule": "0xb04DE6Cbc6E258E8f2D2B00EBdcD2Ea901791EAA",
"interchainSecurityModule": "0xFFec270FE3D0e3B9348B3664BE73A5d4906BA620",
"mailbox": "0xc2FbB9411186AB3b1a6AFCCA702D1a80B48b197c",
"merkleTreeHook": "0x4C97D35c668EE5194a13c8DE8Afc18cce40C9F28",
"name": "zircuit",
@ -3393,7 +3402,7 @@
"interchainAccountIsm": "0xb2674E213019972f937CCFc5e23BF963D915809e",
"interchainAccountRouter": "0x11b76D93a9D39Eb51F54eBf5566308640cDe882b",
"interchainGasPaymaster": "0x18B0688990720103dB63559a3563f7E8d0f63EDb",
"interchainSecurityModule": "0xDede6e50E548460FB6a939320F707214CFfC701C",
"interchainSecurityModule": "0xED5fD1715A0885a3C7B908BAd5c8C64Ba5166265",
"mailbox": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"merkleTreeHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F",
"name": "zoramainnet",
@ -3464,7 +3473,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3531,7 +3540,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"interchainSecurityModule": "0xa18979d2e5b8A64f62E0f9e9523d28E934F1104c",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3601,7 +3610,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3677,7 +3686,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3741,7 +3750,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3814,7 +3823,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3882,7 +3891,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x2b19CEB3ef3B1D7428b0788d44401E44E381B62B",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3945,7 +3954,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x12C8cfA5B97Df96AaB2795a4186675dA49938968",
"interchainSecurityModule": "0xf08b7F859966ed27286Fe7d924A42b40e2DB80Bd",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -4015,7 +4024,7 @@
"interchainAccountIsm": "0xcd9D3744512F07AE844c40E27912092d7c503565",
"interchainAccountRouter": "0x92cdbF0Ccdf8E93467FA858fb986fa650A02f2A8",
"interchainGasPaymaster": "0xb58257cc81E47EC72fD38aE16297048de23163b4",
"interchainSecurityModule": "0xA16954f5040ba7fE2286569aD107a22a46FffDC6",
"interchainSecurityModule": "0xcC5C35a6214982d9018B95e9684D5b4dA626237e",
"mailbox": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39",
"merkleTreeHook": "0xCC3D1659D50461d27a2F025dDb2c9B06B584B7e1",
"pausableHook": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
@ -4075,7 +4084,7 @@
"interchainAccountIsm": "0xc23BaF5Eb5848D19701BbE7f139645e6bd58a319",
"interchainAccountRouter": "0x7c58Cadcc2b60ACF794eE1843488d6f5703f76BE",
"interchainGasPaymaster": "0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86",
"interchainSecurityModule": "0x128432015A0E08d490e0FD6b4dE4EAbe30f617a3",
"interchainSecurityModule": "0x50B5Edd94A1C7ad18Fa2CA667A30Dc051a695aEe",
"mailbox": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594",
"merkleTreeHook": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59",
"pausableHook": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2",
@ -4147,7 +4156,7 @@
"interchainAccountIsm": "0x783EC5e105234a570eB90f314284E5dBe53bdd90",
"interchainAccountRouter": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563",
"interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2",
"interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6",
"interchainSecurityModule": "0x58D6fb4aADd3ae83ec529d3d0f42Ae904207a336",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6",
"pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c",
@ -4210,7 +4219,7 @@
"interchainAccountIsm": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"interchainAccountRouter": "0xbb0AE51BCa526cF313b6a95BfaB020794af6C394",
"interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2",
"interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6",
"interchainSecurityModule": "0x58D6fb4aADd3ae83ec529d3d0f42Ae904207a336",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6",
"pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c",
@ -4280,7 +4289,7 @@
"interchainAccountIsm": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451",
"interchainAccountRouter": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2",
"interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6",
"interchainSecurityModule": "0x58D6fb4aADd3ae83ec529d3d0f42Ae904207a336",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6",
"pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c",
@ -4351,7 +4360,7 @@
"interchainAccountIsm": "0x25EAC2007b0D40E3f0AF112FD346412321038719",
"interchainAccountRouter": "0xfF26696DcDb6BbFD27e959b847D4f1399D5BcF64",
"interchainGasPaymaster": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E",
"interchainSecurityModule": "0x8750ac24C3bE28b406fBCD664AbabF676d3aCB29",
"interchainSecurityModule": "0x9dccF81bB9f419425b0a6584E8800556B92209Cc",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912",
"pausableHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19",
@ -4419,7 +4428,7 @@
"interchainAccountIsm": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8",
"interchainAccountRouter": "0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE",
"interchainGasPaymaster": "0xe8d5590F2e969F9d21f0132f2b596273f8a03Ef2",
"interchainSecurityModule": "0xe274f228f87c0D72241CF9aAC15d91e3630aE6f6",
"interchainSecurityModule": "0x58D6fb4aADd3ae83ec529d3d0f42Ae904207a336",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0xDab56C5A1EffFdd23f6BD1243E457B1575984Bc6",
"pausableHook": "0x73db9c7430548f399e335f3424e8d56080e9010c",
@ -4485,7 +4494,7 @@
"interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451",
"interchainGasPaymaster": "0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56",
"interchainSecurityModule": "0x01031eCa87184c84938016E1444150472Da35b3a",
"interchainSecurityModule": "0x81EC949b07e033b0346E60C2098464d115F0a997",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19",
"pausableHook": "0x2d5918c3602F17937Ff982F7Bb7110774D3A24AD",
@ -4556,7 +4565,7 @@
"interchainAccountIsm": "0x9eb56085DdbDA60aDf7d2B533AFeD90e38fC9666",
"interchainAccountRouter": "0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de",
"interchainGasPaymaster": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E",
"interchainSecurityModule": "0x8750ac24C3bE28b406fBCD664AbabF676d3aCB29",
"interchainSecurityModule": "0x9dccF81bB9f419425b0a6584E8800556B92209Cc",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0x9c44E6b8F0dB517C2c3a0478caaC5349b614F912",
"pausableHook": "0x53e912b41125d6094590a7DBEf1360d3d56EEa19",
@ -4617,7 +4626,7 @@
"interchainAccountIsm": "0x61374178e45F65fF9D6252d017Cd580FC60B7654",
"interchainAccountRouter": "0x783EC5e105234a570eB90f314284E5dBe53bdd90",
"interchainGasPaymaster": "0xE56Da9D48E698eB70F56aeCC0BC25Ff1710EEA76",
"interchainSecurityModule": "0xE89fF24e1979F6AbD6b71b733cc62d1289d193c4",
"interchainSecurityModule": "0x9d1481A1fc2515aeE0Bf4eEeDDB75893DfAF0752",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x4757Bdd68Bba8a6d901cEC82E61E184fF2986918",
"pausableHook": "0x9024A3902B542C87a5C4A2b3e15d60B2f087Dc3E",
@ -4681,7 +4690,7 @@
"interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451",
"interchainGasPaymaster": "0x168DFF0Ad2b180F3801883Fe5Ae56d7E7d91D5f4",
"interchainSecurityModule": "0xFF16628ff85F145Ce6d1712014D46DcFB52da75A",
"interchainSecurityModule": "0x8f93c32C19986B891beA2bF317686Aa2336b3854",
"mailbox": "0x02d16BC51af6BfD153d67CA61754cF912E82C4d9",
"merkleTreeHook": "0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56",
"pausableHook": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594",
@ -4746,7 +4755,7 @@
"interchainAccountIsm": "0xb5668713E9BA8bC96f97D691663E70b54CE90b0A",
"interchainAccountRouter": "0xc5068BB6803ADbe5600DE5189fe27A4dAcE31170",
"interchainGasPaymaster": "0xA1Df6B70044029a2D1eDDC50EfDE2813e478140a",
"interchainSecurityModule": "0x729E790E70902429873c23BaA73eE39aCEEfc461",
"interchainSecurityModule": "0x01180E7B92A4fEA1e250C92E32A02Df1cA058Fe0",
"mailbox": "0x783EC5e105234a570eB90f314284E5dBe53bdd90",
"merkleTreeHook": "0x25d668D37f20E6f396cB5DF1DFf5A3f2F568e707",
"pausableHook": "0xC9ab9Dc82F05eA118F266611f4c474529d43b599",
@ -4771,6 +4780,69 @@
"transactionOverrides": {
"gasPrice": 100000000
}
},
"stride": {
"bech32Prefix": "stride",
"blockExplorers": [
{
"apiUrl": "https://www.mintscan.io/stride",
"family": "other",
"name": "Mintscan",
"url": "https://www.mintscan.io/stride"
}
],
"blocks": {
"confirmations": 1,
"estimateBlockTime": 5,
"reorgPeriod": 1
},
"chainId": "stride-1",
"deployer": {
"name": "Stride Labs",
"url": "https://www.stride.zone"
},
"displayName": "Stride",
"domainId": 745,
"gasCurrencyCoinGeckoId": "stride",
"grpcUrls": [
{
"http": "https://stride-grpc.publicnode.com:443"
}
],
"isTestnet": false,
"name": "stride",
"nativeToken": {
"decimals": 6,
"denom": "ustrd",
"name": "Stride",
"symbol": "STRD"
},
"protocol": "cosmos",
"restUrls": [
{
"http": "https://stride-api.polkachu.com"
}
],
"rpcUrls": [
{
"http": "https://stride-rpc.polkachu.com"
}
],
"slip44": 118,
"interchainGasPaymaster": "0x0000000000000000000000000000000000000000000000000000000000000000",
"mailbox": "0x89945750e089d84581f194e1947a58480b335f18386ad4f761f05feebf5e2454",
"merkleTreeHook": "0x7ab4a8c3ba5371e34cd8d5dc584e0d924504fc21c3cbf41c3f64d436176bf007",
"validatorAnnounce": "0xf57d954bf3ddb5f1032a0e020a99e931215cf83ceb4de987c781488065aaae0d",
"gasPrice": {
"denom": "ustrd",
"amount": "0.005"
},
"canonicalAsset": "ustrd",
"contractAddressBytes": 32,
"index": {
"from": 9152000,
"chunk": 5
}
}
},
"defaultRpcConsensusType": "fallback"

@ -170,7 +170,7 @@ where
Ok(logs) => logs,
Err(err) => {
warn!(?err, ?range, "Error fetching logs in range");
break SLEEP_DURATION;
break Some(SLEEP_DURATION);
}
};
@ -196,13 +196,20 @@ where
// Update cursor
if let Err(err) = cursor.update(logs, range).await {
warn!(?err, "Error updating cursor");
break SLEEP_DURATION;
break Some(SLEEP_DURATION);
};
break Default::default();
break None;
},
CursorAction::Sleep(duration) => duration,
CursorAction::Sleep(duration) => Some(duration),
};
sleep(sleep_duration).await
if let Some(sleep_duration) = sleep_duration {
debug!(
cursor = ?cursor,
?sleep_duration,
"Cursor can't make progress, sleeping",
);
sleep(sleep_duration).await
}
}
async fn dedupe_and_store_logs(

@ -10,13 +10,13 @@ use hyperlane_core::{
config::OperationBatchConfig, AggregationIsm, CcipReadIsm, ContractLocator, HyperlaneAbi,
HyperlaneDomain, HyperlaneDomainProtocol, HyperlaneMessage, HyperlaneProvider, IndexMode,
InterchainGasPaymaster, InterchainGasPayment, InterchainSecurityModule, Mailbox,
MerkleTreeHook, MerkleTreeInsertion, MultisigIsm, RoutingIsm, SequenceAwareIndexer,
ValidatorAnnounce, H256,
MerkleTreeHook, MerkleTreeInsertion, MultisigIsm, ReorgPeriod, RoutingIsm,
SequenceAwareIndexer, ValidatorAnnounce, H256,
};
use hyperlane_cosmos as h_cosmos;
use hyperlane_ethereum::{
self as h_eth, BuildableWithProvider, EthereumInterchainGasPaymasterAbi, EthereumMailboxAbi,
EthereumValidatorAnnounceAbi,
EthereumReorgPeriod, EthereumValidatorAnnounceAbi,
};
use hyperlane_fuel as h_fuel;
use hyperlane_sealevel as h_sealevel;
@ -45,7 +45,7 @@ pub struct ChainConf {
/// Signer configuration for this chain
pub signer: Option<SignerConf>,
/// The reorg period of the chain, i.e. the number of blocks until finality
pub reorg_period: u32,
pub reorg_period: ReorgPeriod,
/// Addresses of contracts on the chain
pub addresses: CoreContractAddresses,
/// The chain connection details
@ -272,13 +272,13 @@ impl ChainConf {
match &self.connection {
ChainConnectionConf::Ethereum(conf) => {
let reorg_period =
EthereumReorgPeriod::try_from(&self.reorg_period).context(ctx)?;
self.build_ethereum(
conf,
&locator,
metrics,
h_eth::SequenceIndexerBuilder {
reorg_period: self.reorg_period,
},
h_eth::SequenceIndexerBuilder { reorg_period },
)
.await
}
@ -289,11 +289,12 @@ impl ChainConf {
}
ChainConnectionConf::Cosmos(conf) => {
let signer = self.cosmos_signer().await.context(ctx)?;
let reorg_period = self.reorg_period.as_blocks().context(ctx)?;
let indexer = Box::new(h_cosmos::CosmosMailboxDispatchIndexer::new(
conf.clone(),
locator,
signer,
self.reorg_period,
reorg_period,
)?);
Ok(indexer as Box<dyn SequenceAwareIndexer<HyperlaneMessage>>)
}
@ -311,13 +312,13 @@ impl ChainConf {
match &self.connection {
ChainConnectionConf::Ethereum(conf) => {
let reorg_period =
EthereumReorgPeriod::try_from(&self.reorg_period).context(ctx)?;
self.build_ethereum(
conf,
&locator,
metrics,
h_eth::DeliveryIndexerBuilder {
reorg_period: self.reorg_period,
},
h_eth::DeliveryIndexerBuilder { reorg_period },
)
.await
}
@ -328,11 +329,12 @@ impl ChainConf {
}
ChainConnectionConf::Cosmos(conf) => {
let signer = self.cosmos_signer().await.context(ctx)?;
let reorg_period = self.reorg_period.as_blocks().context(ctx)?;
let indexer = Box::new(h_cosmos::CosmosMailboxDeliveryIndexer::new(
conf.clone(),
locator,
signer,
self.reorg_period,
reorg_period,
)?);
Ok(indexer as Box<dyn SequenceAwareIndexer<H256>>)
}
@ -389,13 +391,15 @@ impl ChainConf {
match &self.connection {
ChainConnectionConf::Ethereum(conf) => {
let reorg_period =
EthereumReorgPeriod::try_from(&self.reorg_period).context(ctx)?;
self.build_ethereum(
conf,
&locator,
metrics,
h_eth::InterchainGasPaymasterIndexerBuilder {
mailbox_address: self.addresses.mailbox.into(),
reorg_period: self.reorg_period,
reorg_period,
},
)
.await
@ -408,10 +412,11 @@ impl ChainConf {
Ok(indexer as Box<dyn SequenceAwareIndexer<InterchainGasPayment>>)
}
ChainConnectionConf::Cosmos(conf) => {
let reorg_period = self.reorg_period.as_blocks().context(ctx)?;
let indexer = Box::new(h_cosmos::CosmosInterchainGasPaymasterIndexer::new(
conf.clone(),
locator,
self.reorg_period,
reorg_period,
)?);
Ok(indexer as Box<dyn SequenceAwareIndexer<InterchainGasPayment>>)
}
@ -429,13 +434,13 @@ impl ChainConf {
match &self.connection {
ChainConnectionConf::Ethereum(conf) => {
let reorg_period =
EthereumReorgPeriod::try_from(&self.reorg_period).context(ctx)?;
self.build_ethereum(
conf,
&locator,
metrics,
h_eth::MerkleTreeHookIndexerBuilder {
reorg_period: self.reorg_period,
},
h_eth::MerkleTreeHookIndexerBuilder { reorg_period },
)
.await
}
@ -450,12 +455,13 @@ impl ChainConf {
}
ChainConnectionConf::Cosmos(conf) => {
let signer = self.cosmos_signer().await.context(ctx)?;
let reorg_period = self.reorg_period.as_blocks().context(ctx)?;
let indexer = Box::new(h_cosmos::CosmosMerkleTreeHookIndexer::new(
conf.clone(),
locator,
// TODO: remove signer requirement entirely
signer,
self.reorg_period,
reorg_period,
)?);
Ok(indexer as Box<dyn SequenceAwareIndexer<MerkleTreeInsertion>>)
}

@ -180,7 +180,7 @@ mod test {
use std::panic::AssertUnwindSafe;
use futures_util::FutureExt;
use hyperlane_core::{ReorgEvent, H256};
use hyperlane_core::{ReorgEvent, ReorgPeriod, H256};
#[tokio::test]
async fn test_build_and_validate() {
@ -209,7 +209,7 @@ mod test {
.unwrap();
let dummy_checkpoint_index = 56;
let unix_timestamp = 1620000000;
let reorg_period = 5;
let reorg_period = ReorgPeriod::from_blocks(5);
let dummy_reorg_event = ReorgEvent {
local_merkle_root: dummy_local_merkle_root,
canonical_merkle_root: dummy_canonical_merkle_root,
@ -237,7 +237,9 @@ mod test {
canonical_merkle_root: 0xb437b888332ef12f7260c7f679aad3c96b91ab81c2dc7242f8b290f0b6bba92b,
checkpoint_index: 56,
unix_timestamp: 1620000000,
reorg_period: 5,
reorg_period: Blocks(
5,
),
}. Please resolve the reorg to continue."#
);
} else {

@ -19,7 +19,7 @@ use url::Url;
use h_cosmos::RawCosmosAmount;
use hyperlane_core::{
cfg_unwrap_all, config::*, HyperlaneDomain, HyperlaneDomainProtocol,
HyperlaneDomainTechnicalStack, IndexMode,
HyperlaneDomainTechnicalStack, IndexMode, ReorgPeriod,
};
use crate::settings::{
@ -34,6 +34,8 @@ pub use self::json_value_parser::ValueParser;
mod connection_parser;
mod json_value_parser;
const DEFAULT_CHUNK_SIZE: u32 = 1999;
/// The base agent config
#[derive(Debug, Deserialize)]
#[serde(transparent)]
@ -136,8 +138,8 @@ fn parse_chain(
.chain(&mut err)
.get_opt_key("blocks")
.get_key("reorgPeriod")
.parse_u32()
.unwrap_or(1);
.parse_value("Invalid reorgPeriod")
.unwrap_or(ReorgPeriod::from_blocks(1));
let rpcs = parse_base_and_override_urls(&chain, "rpcUrls", "customRpcUrls", "http", &mut err);
@ -152,7 +154,7 @@ fn parse_chain(
.get_opt_key("index")
.get_opt_key("chunk")
.parse_u32()
.unwrap_or(1999);
.unwrap_or(DEFAULT_CHUNK_SIZE);
let mode = chain
.chain(&mut err)
.get_opt_key("index")

@ -3,16 +3,20 @@
use std::{
fmt::{Debug, Formatter},
hash::{Hash, Hasher},
num::NonZeroU32,
};
use derive_new::new;
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
use serde::Serialize;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "strum")]
use strum::{EnumIter, EnumString, IntoStaticStr};
use crate::{utils::many_to_one, HyperlaneProtocolError, IndexMode, H160, H256};
use crate::{
utils::many_to_one, ChainCommunicationError, HyperlaneProtocolError, IndexMode, H160, H256,
};
#[derive(Debug, Clone)]
pub struct Address(pub bytes::Bytes);
@ -39,6 +43,80 @@ impl<'a> std::fmt::Display for ContractLocator<'a> {
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub enum ReorgPeriod {
#[default]
None,
Blocks(NonZeroU32),
Tag(String),
}
impl ReorgPeriod {
pub fn from_blocks(blocks: u32) -> Self {
NonZeroU32::try_from(blocks)
.map(ReorgPeriod::Blocks)
.unwrap_or(ReorgPeriod::None)
}
pub fn as_blocks(&self) -> Result<u32, ChainCommunicationError> {
match self {
ReorgPeriod::None => Ok(0),
ReorgPeriod::Blocks(blocks) => Ok(blocks.get()),
ReorgPeriod::Tag(_) => Err(ChainCommunicationError::InvalidReorgPeriod(self.clone())),
}
}
pub fn is_none(&self) -> bool {
matches!(self, ReorgPeriod::None)
}
}
impl Serialize for ReorgPeriod {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
ReorgPeriod::None => serializer.serialize_u32(0),
ReorgPeriod::Blocks(blocks) => serializer.serialize_u32(blocks.get()),
ReorgPeriod::Tag(tag) => serializer.serialize_str(tag),
}
}
}
impl<'de> Deserialize<'de> for ReorgPeriod {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
use serde::de;
struct ReorgPeriodVisitor;
impl<'de> de::Visitor<'de> for ReorgPeriodVisitor {
type Value = ReorgPeriod;
fn expecting(&self, f: &mut Formatter) -> std::fmt::Result {
f.write_str("reorgPeriod as a number or string")
}
fn visit_u64<E: de::Error>(self, v: u64) -> Result<Self::Value, E> {
let v = v.try_into().map_err(de::Error::custom)?;
Ok(ReorgPeriod::from_blocks(v))
}
fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
match v.parse::<u32>() {
Ok(v) => self.visit_u32(v),
Err(_) => Ok(ReorgPeriod::Tag(v.to_string())),
}
}
}
deserializer.deserialize_any(ReorgPeriodVisitor)
}
}
/// All domains supported by Hyperlane.
#[derive(FromPrimitive, PartialEq, Eq, Debug, Clone, Copy, Hash, Serialize)]
#[cfg_attr(
@ -221,6 +299,7 @@ pub enum HyperlaneDomainTechnicalStack {
OpStack,
PolygonCDK,
PolkadotSubstrate,
ZkSync,
#[default]
Other,
}
@ -304,6 +383,7 @@ impl KnownHyperlaneDomain {
HyperlaneDomainTechnicalStack::PolkadotSubstrate: [
Moonbeam, Tangle
],
HyperlaneDomainTechnicalStack::ZkSync: [],
HyperlaneDomainTechnicalStack::Other: [
Avalanche, BinanceSmartChain, Celo, EclipseMainnet, Endurance, Ethereum,
FuseMainnet, Gnosis, Injective, Linea, Lukso, Neutron, Osmosis, Polygon,
@ -505,9 +585,9 @@ impl HyperlaneDomain {
#[cfg(test)]
#[cfg(feature = "strum")]
mod tests {
use std::str::FromStr;
use std::{num::NonZeroU32, str::FromStr};
use crate::KnownHyperlaneDomain;
use crate::{KnownHyperlaneDomain, ReorgPeriod};
#[test]
fn domain_strings() {
@ -560,4 +640,32 @@ mod tests {
);
assert!("foo".parse::<KnownHyperlaneDomain>().is_err());
}
#[test]
fn parse_reorg_period() {
assert_eq!(
serde_json::from_value::<ReorgPeriod>(0.into()).unwrap(),
ReorgPeriod::None
);
assert_eq!(
serde_json::from_value::<ReorgPeriod>("0".into()).unwrap(),
ReorgPeriod::None
);
assert_eq!(
serde_json::from_value::<ReorgPeriod>(12.into()).unwrap(),
ReorgPeriod::Blocks(NonZeroU32::new(12).unwrap())
);
assert_eq!(
serde_json::from_value::<ReorgPeriod>("12".into()).unwrap(),
ReorgPeriod::Blocks(NonZeroU32::new(12).unwrap())
);
assert_eq!(
serde_json::from_value::<ReorgPeriod>("finalized".into()).unwrap(),
ReorgPeriod::Tag("finalized".into())
);
}
}

@ -10,8 +10,10 @@ use crate::config::StrOrIntParseError;
use crate::rpc_clients::RpcClientError;
use std::string::FromUtf8Error;
use crate::HyperlaneProviderError;
use crate::{Error as PrimitiveTypeError, HyperlaneSignerError, H256, U256};
use crate::{
Error as PrimitiveTypeError, HyperlaneProviderError, HyperlaneSignerError, ReorgPeriod, H256,
U256,
};
/// The result of interacting with a chain.
pub type ChainResult<T> = Result<T, ChainCommunicationError>;
@ -157,6 +159,9 @@ pub enum ChainCommunicationError {
/// Hyperlane signer error
#[error("{0}")]
HyperlaneSignerError(#[from] HyperlaneSignerError),
/// Invalid reorg period
#[error("Invalid reorg period: {0:?}")]
InvalidReorgPeriod(ReorgPeriod),
}
impl ChainCommunicationError {

@ -1,12 +1,11 @@
use std::fmt::Debug;
use std::num::NonZeroU64;
use async_trait::async_trait;
use derive_new::new;
use crate::{
traits::TxOutcome, utils::domain_hash, BatchItem, ChainCommunicationError, ChainResult,
HyperlaneContract, HyperlaneMessage, QueueOperation, TxCostEstimate, H256, U256,
HyperlaneContract, HyperlaneMessage, QueueOperation, ReorgPeriod, TxCostEstimate, H256, U256,
};
/// Interface for the Mailbox chain contract. Allows abstraction over different
@ -20,9 +19,9 @@ pub trait Mailbox: HyperlaneContract + Send + Sync + Debug {
/// Gets the current leaf count of the merkle tree
///
/// - `lag` is how far behind the current block to query, if not specified
/// - `reorg_period` is how far behind the current block to query, if not specified
/// it will query at the latest block.
async fn count(&self, lag: Option<NonZeroU64>) -> ChainResult<u32>;
async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32>;
/// Fetch the status of a message
async fn delivered(&self, id: H256) -> ChainResult<bool>;

@ -1,11 +1,11 @@
use std::fmt::Debug;
use std::num::NonZeroU64;
use async_trait::async_trait;
use auto_impl::auto_impl;
use crate::{
accumulator::incremental::IncrementalMerkle, ChainResult, Checkpoint, HyperlaneContract,
ReorgPeriod,
};
/// Interface for the MerkleTreeHook chain contract. Allows abstraction over different
@ -15,19 +15,19 @@ use crate::{
pub trait MerkleTreeHook: HyperlaneContract + Send + Sync + Debug {
/// Return the incremental merkle tree in storage
///
/// - `lag` is how far behind the current block to query, if not specified
/// - `reorg_period` is how far behind the current block to query, if not specified
/// it will query at the latest block.
async fn tree(&self, lag: Option<NonZeroU64>) -> ChainResult<IncrementalMerkle>;
async fn tree(&self, reorg_period: &ReorgPeriod) -> ChainResult<IncrementalMerkle>;
/// Gets the current leaf count of the merkle tree
///
/// - `lag` is how far behind the current block to query, if not specified
/// - `reorg_period` is how far behind the current block to query, if not specified
/// it will query at the latest block.
async fn count(&self, lag: Option<NonZeroU64>) -> ChainResult<u32>;
async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32>;
/// Get the latest checkpoint.
///
/// - `lag` is how far behind the current block to query, if not specified
/// - `reorg_period` is how far behind the current block to query, if not specified
/// it will query at the latest block.
async fn latest_checkpoint(&self, lag: Option<NonZeroU64>) -> ChainResult<Checkpoint>;
async fn latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult<Checkpoint>;
}

@ -1,7 +1,7 @@
use derive_new::new;
use serde::{Deserialize, Serialize};
use crate::H256;
use crate::{ReorgPeriod, H256};
/// Details about a detected chain reorg, from an agent's perspective
#[derive(Debug, Clone, Serialize, Deserialize, new)]
@ -15,6 +15,6 @@ pub struct ReorgEvent {
pub checkpoint_index: u32,
/// the timestamp when the reorg was detected, in seconds since the Unix epoch
pub unix_timestamp: u64,
/// the reorg period configured for the agent, in blocks
pub reorg_period: u64,
/// the reorg period configured for the agent
pub reorg_period: ReorgPeriod,
}

@ -1,7 +1,5 @@
#![allow(non_snake_case)]
use std::num::NonZeroU64;
use async_trait::async_trait;
use mockall::*;
@ -28,11 +26,11 @@ mock! {
nonce: usize,
) -> ChainResult<Option<H256>> {}
pub fn _tree(&self, maybe_lag: Option<NonZeroU64>) -> ChainResult<IncrementalMerkle> {}
pub fn _tree(&self, reorg_period: &ReorgPeriod) -> ChainResult<IncrementalMerkle> {}
pub fn _count(&self, maybe_lag: Option<NonZeroU64>) -> ChainResult<u32> {}
pub fn _count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32> {}
pub fn _latest_checkpoint(&self, maybe_lag: Option<NonZeroU64>) -> ChainResult<Checkpoint> {}
pub fn _latest_checkpoint(&self, reorg_period: &ReorgPeriod) -> ChainResult<Checkpoint> {}
pub fn _default_ism(&self) -> ChainResult<H256> {}
pub fn _recipient_ism(&self, recipient: H256) -> ChainResult<H256> {}
@ -68,8 +66,8 @@ impl std::fmt::Debug for MockMailboxContract {
#[async_trait]
impl Mailbox for MockMailboxContract {
async fn count(&self, maybe_lag: Option<NonZeroU64>) -> ChainResult<u32> {
self._count(maybe_lag)
async fn count(&self, reorg_period: &ReorgPeriod) -> ChainResult<u32> {
self._count(reorg_period)
}
async fn default_ism(&self) -> ChainResult<H256> {

@ -1,5 +1,19 @@
# @hyperlane-xyz/core
## 5.5.0
### Minor Changes
- 72c23c0d6: Added PRECISION and rateUpdateNonce to ensure compatibility of HypERC4626
### Patch Changes
- c9085afd9: Patched OPL2ToL1Ism to check for correct messageId for external call in verify
- ec6b874b1: Added nonce to HypERC4626
- Updated dependencies [f1712deb7]
- Updated dependencies [29341950e]
- @hyperlane-xyz/utils@5.6.0
## 5.4.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.4.1";
string public constant PACKAGE_VERSION = "5.5.0";
}

@ -1,10 +1,25 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.6.11;
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
// ============ Internal Imports ============
import {Router} from "./Router.sol";
import {StandardHookMetadata} from "../hooks/libs/StandardHookMetadata.sol";
abstract contract GasRouter is Router {
event GasSet(uint32 domain, uint256 gas);
// ============ Mutable Storage ============
mapping(uint32 => uint256) public destinationGas;
@ -56,6 +71,7 @@ abstract contract GasRouter is Router {
function _setDestinationGas(uint32 domain, uint256 gas) internal {
destinationGas[domain] = gas;
emit GasSet(domain, gas);
}
function _GasRouter_dispatch(

@ -9,6 +9,10 @@ library TypeCasts {
// alignment preserving cast
function bytes32ToAddress(bytes32 _buf) internal pure returns (address) {
require(
uint256(_buf) <= uint256(type(uint160).max),
"TypeCasts: bytes32ToAddress overflow"
);
return address(uint160(uint256(_buf)));
}
}

@ -1,10 +1,25 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
// ============ Internal Imports ============
import {TokenRouter} from "./libs/TokenRouter.sol";
import {TokenMessage} from "./libs/TokenMessage.sol";
import {MailboxClient} from "../client/MailboxClient.sol";
// ============ External Imports ============
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
@ -22,6 +37,7 @@ contract HypERC20Collateral is TokenRouter {
* @param erc20 Address of the token to keep as collateral
*/
constructor(address erc20, address _mailbox) TokenRouter(_mailbox) {
require(Address.isContract(erc20), "HypERC20Collateral: invalid token");
wrappedToken = IERC20(erc20);
}

@ -66,11 +66,7 @@ contract HypERC4626Collateral is HypERC20Collateral {
// Can't override _transferFromSender only because we need to pass shares in the token message
_transferFromSender(_amount);
uint256 _shares = _depositIntoVault(_amount);
uint256 _exchangeRate = PRECISION.mulDiv(
vault.totalAssets(),
vault.totalSupply(),
Math.Rounding.Down
);
uint256 _exchangeRate = vault.convertToAssets(PRECISION);
rateUpdateNonce++;
bytes memory _tokenMetadata = abi.encode(
@ -121,15 +117,19 @@ contract HypERC4626Collateral is HypERC20Collateral {
* @dev Update the exchange rate on the synthetic token by accounting for additional yield accrued to the underlying vault
* @param _destinationDomain domain of the vault
*/
function rebase(uint32 _destinationDomain) public payable {
function rebase(
uint32 _destinationDomain,
bytes calldata _hookMetadata,
address _hook
) public payable {
// force a rebase with an empty transfer to 0x1
_transferRemote(
_destinationDomain,
NULL_RECIPIENT,
0,
msg.value,
bytes(""),
address(0)
_hookMetadata,
_hook
);
}
}

@ -0,0 +1,113 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {HypERC4626} from "./HypERC4626.sol";
import {PackageVersioned} from "../../PackageVersioned.sol";
/*@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@ HYPERLANE @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@@
@@@@@@@@@ @@@@@@@@*/
/**
* @title WHypERC4626
* @author Abacus Works
* @notice A wrapper for HypERC4626 that allows for wrapping and unwrapping of underlying rebasing tokens
*/
contract WHypERC4626 is ERC20, PackageVersioned {
HypERC4626 public immutable underlying;
constructor(
HypERC4626 _underlying,
string memory name,
string memory symbol
) ERC20(name, symbol) {
underlying = _underlying;
}
/*
* @notice Wraps an amount of underlying tokens into wrapped tokens
* @param _underlyingAmount The amount of underlying tokens to wrap
* @return The amount of wrapped tokens
*/
function wrap(uint256 _underlyingAmount) external returns (uint256) {
require(
_underlyingAmount > 0,
"WHypERC4626: wrap amount must be greater than 0"
);
uint256 wrappedAmount = underlying.assetsToShares(_underlyingAmount);
_mint(msg.sender, wrappedAmount);
underlying.transferFrom(msg.sender, address(this), _underlyingAmount);
return wrappedAmount;
}
/*
* @notice Unwraps an amount of wrapped tokens into underlying tokens
* @param _wrappedAmount The amount of wrapped tokens to unwrap
* @return The amount of underlying tokens
*/
function unwrap(uint256 _wrappedAmount) external returns (uint256) {
require(
_wrappedAmount > 0,
"WHypERC4626: unwrap amount must be greater than 0"
);
uint256 underlyingAmount = underlying.sharesToAssets(_wrappedAmount);
_burn(msg.sender, _wrappedAmount);
underlying.transfer(msg.sender, underlyingAmount);
return underlyingAmount;
}
/*
* @notice Gets the amount of wrapped tokens for a given amount of underlying tokens
* @param _underlyingAmount The amount of underlying tokens
* @return The amount of wrapped tokens
*/
function getWrappedAmount(
uint256 _underlyingAmount
) external view returns (uint256) {
return underlying.assetsToShares(_underlyingAmount);
}
/*
* @notice Gets the amount of underlying tokens for a given amount of wrapped tokens
* @param _wrappedAmount The amount of wrapped tokens
* @return The amount of underlying tokens
*/
function getUnderlyingAmount(
uint256 _wrappedAmount
) external view returns (uint256) {
return underlying.sharesToAssets(_wrappedAmount);
}
/*
* @notice Gets the amount of wrapped tokens for 1 unit of underlying tokens
* @return The amount of wrapped tokens
*/
function wrappedPerUnderlying() external view returns (uint256) {
return underlying.assetsToShares(1 * 10 ** underlying.decimals());
}
/*
* @notice Gets the amount of underlying tokens for 1 unit of wrapped tokens
* @return The amount of underlying tokens
*/
function underlyingPerWrapped() external view returns (uint256) {
return underlying.sharesToAssets(1 * 10 ** decimals());
}
/*
* @notice Gets the decimals of the wrapped token
* @return The decimals of the wrapped token
*/
function decimals() public view override returns (uint8) {
return underlying.decimals();
}
}

@ -1,11 +1,11 @@
{
"name": "@hyperlane-xyz/core",
"description": "Core solidity contracts for Hyperlane",
"version": "5.4.1",
"version": "5.5.0",
"dependencies": {
"@arbitrum/nitro-contracts": "^1.2.1",
"@eth-optimism/contracts": "^0.6.0",
"@hyperlane-xyz/utils": "5.5.0",
"@hyperlane-xyz/utils": "5.6.0",
"@layerzerolabs/lz-evm-oapp-v2": "2.0.2",
"@openzeppelin/contracts": "^4.9.3",
"@openzeppelin/contracts-upgradeable": "^v4.9.3",

@ -68,6 +68,8 @@ contract GasRouterTest is Test {
}
function testSetDestinationGas(uint256 gas) public {
vm.expectEmit(true, true, true, true);
emit GasRouter.GasSet(originDomain, gas);
setDestinationGas(remoteRouter, originDomain, gas);
assertEq(remoteRouter.destinationGas(originDomain), gas);

@ -75,7 +75,7 @@ contract RateLimitedIsmTest is Test {
TokenMessage.format(bytes32(""), _amount, bytes(""))
);
vm.expectRevert("InvalidRecipient");
vm.expectRevert("TypeCasts: bytes32ToAddress overflow");
rateLimitedIsm.verify(bytes(""), _message);
}

@ -406,6 +406,11 @@ contract HypERC20CollateralTest is HypTokenTest {
_enrollRemoteTokenRouter();
}
function test_constructor_revert_ifInvalidToken() public {
vm.expectRevert("HypERC20Collateral: invalid token");
new HypERC20Collateral(address(0), address(localMailbox));
}
function testInitialize_revert_ifAlreadyInitialized() public {}
function testRemoteTransfer() public {

@ -24,7 +24,9 @@ import {MockMailbox} from "../../contracts/mock/MockMailbox.sol";
import {HypERC20} from "../../contracts/token/HypERC20.sol";
import {HypERC4626Collateral} from "../../contracts/token/extensions/HypERC4626Collateral.sol";
import {HypERC4626} from "../../contracts/token/extensions/HypERC4626.sol";
import {StandardHookMetadata} from "../../contracts/hooks/libs/StandardHookMetadata.sol";
import "../../contracts/test/ERC4626/ERC4626Test.sol";
import {ProtocolFee} from "../../contracts/hooks/ProtocolFee.sol";
contract HypERC4626CollateralTest is HypTokenTest {
using TypeCasts for address;
@ -124,14 +126,38 @@ contract HypERC4626CollateralTest is HypTokenTest {
_accrueYield();
localRebasingToken.rebase(DESTINATION);
localRebasingToken.rebase(DESTINATION, bytes(""), address(0));
remoteMailbox.processNextInboundMessage();
assertEq(
assertApproxEqRelDecimal(
remoteToken.balanceOf(BOB),
transferAmount + _discountedYield()
transferAmount + _discountedYield(),
1e14,
0
);
}
function testRemoteTransfer_rebaseWithCustomHook() public {
_performRemoteTransferWithoutExpectation(0, transferAmount);
assertEq(remoteToken.balanceOf(BOB), transferAmount);
_accrueYield();
uint256 FEE = 1e18;
ProtocolFee customHook = new ProtocolFee(
FEE,
FEE,
address(this),
address(this)
);
localRebasingToken.rebase{value: FEE}(
DESTINATION,
StandardHookMetadata.overrideMsgValue(FEE),
address(customHook)
);
assertEq(address(customHook).balance, FEE);
}
function testRebaseWithTransfer() public {
_performRemoteTransferWithoutExpectation(0, transferAmount);
assertEq(remoteToken.balanceOf(BOB), transferAmount);
@ -275,7 +301,7 @@ contract HypERC4626CollateralTest is HypTokenTest {
_accrueYield();
localRebasingToken.rebase(DESTINATION);
localRebasingToken.rebase(DESTINATION, bytes(""), address(0));
remoteMailbox.processNextInboundMessage();
// Use balance here since it might be off by <1bp
@ -314,7 +340,7 @@ contract HypERC4626CollateralTest is HypTokenTest {
_accrueYield();
_accrueYield(); // earning 2x yield to be split
localRebasingToken.rebase(DESTINATION);
localRebasingToken.rebase(DESTINATION, bytes(""), address(0));
vm.prank(CAROL);
remoteToken.transferRemote(
@ -352,7 +378,7 @@ contract HypERC4626CollateralTest is HypTokenTest {
// decrease collateral in vault by 10%
uint256 drawdown = 5e18;
primaryToken.burnFrom(address(vault), drawdown);
localRebasingToken.rebase(DESTINATION);
localRebasingToken.rebase(DESTINATION, bytes(""), address(0));
remoteMailbox.processNextInboundMessage();
// Use balance here since it might be off by <1bp
@ -378,7 +404,7 @@ contract HypERC4626CollateralTest is HypTokenTest {
_accrueYield();
localRebasingToken.rebase(DESTINATION);
localRebasingToken.rebase(DESTINATION, bytes(""), address(0));
remoteMailbox.processNextInboundMessage();
vm.prank(BOB);
@ -389,13 +415,23 @@ contract HypERC4626CollateralTest is HypTokenTest {
);
peerMailbox.processNextInboundMessage();
assertEq(remoteRebasingToken.exchangeRate(), 1045e7); // 5 * 0.9 = 4.5% yield
assertApproxEqRelDecimal(
remoteRebasingToken.exchangeRate(),
1045e7,
1e14,
0
); // 5 * 0.9 = 4.5% yield
assertEq(peerRebasingToken.exchangeRate(), 1e10); // assertingthat transfers by the synthetic variant don't impact the exchang rate
localRebasingToken.rebase(PEER_DESTINATION);
localRebasingToken.rebase(PEER_DESTINATION, bytes(""), address(0));
peerMailbox.processNextInboundMessage();
assertEq(peerRebasingToken.exchangeRate(), 1045e7); // asserting that the exchange rate is set finally by the collateral variant
assertApproxEqRelDecimal(
peerRebasingToken.exchangeRate(),
1045e7,
1e14,
0
); // asserting that the exchange rate is set finally by the collateral variant
}
function test_cyclicTransfers() public {
@ -405,7 +441,7 @@ contract HypERC4626CollateralTest is HypTokenTest {
_accrueYield();
localRebasingToken.rebase(DESTINATION); // yield is added
localRebasingToken.rebase(DESTINATION, bytes(""), address(0)); // yield is added
remoteMailbox.processNextInboundMessage();
// BOB: remote -> peer(BOB) (yield is leftover)
@ -417,7 +453,7 @@ contract HypERC4626CollateralTest is HypTokenTest {
);
peerMailbox.processNextInboundMessage();
localRebasingToken.rebase(PEER_DESTINATION);
localRebasingToken.rebase(PEER_DESTINATION, bytes(""), address(0));
peerMailbox.processNextInboundMessage();
// BOB: peer -> local(CAROL)
@ -457,11 +493,13 @@ contract HypERC4626CollateralTest is HypTokenTest {
_accrueYield();
localRebasingToken.rebase(DESTINATION);
localRebasingToken.rebase(DESTINATION, bytes(""), address(0));
remoteMailbox.processNextInboundMessage();
assertEq(
assertApproxEqRelDecimal(
remoteToken.balanceOf(BOB),
transferAmount + _discountedYield()
transferAmount + _discountedYield(),
1e14,
0
);
vm.prank(address(localMailbox));

@ -0,0 +1,116 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.13;
import {Test} from "forge-std/Test.sol";
import {MockMailbox} from "../../contracts/mock/MockMailbox.sol";
import {WHypERC4626} from "../../contracts/token/extensions/WHypERC4626.sol";
import {HypERC4626} from "../../contracts/token/extensions/HypERC4626.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MockHypERC4626 is HypERC4626 {
constructor(address _mailbox) HypERC4626(18, _mailbox, 2) {}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
}
contract WHypERC4626Test is Test {
WHypERC4626 public wHypERC4626;
MockHypERC4626 public underlyingToken;
address public alice = address(0x1);
address public bob = address(0x2);
function setUp() public {
MockMailbox mailbox = new MockMailbox(1);
underlyingToken = new MockHypERC4626(address(mailbox));
wHypERC4626 = new WHypERC4626(
underlyingToken,
"Wrapped Rebasing Token",
"WRT"
);
underlyingToken.mint(alice, 1000 * 10 ** 18);
underlyingToken.mint(bob, 1000 * 10 ** 18);
}
function test_wrap() public {
uint256 amount = 100 * 10 ** 18;
vm.startPrank(alice);
underlyingToken.approve(address(wHypERC4626), amount);
uint256 wrappedAmount = wHypERC4626.wrap(amount);
assertEq(wHypERC4626.balanceOf(alice), wrappedAmount);
assertEq(underlyingToken.balanceOf(alice), 900 * 10 ** 18);
vm.stopPrank();
}
function test_wrap_revertsWhen_zeroAmount() public {
vm.startPrank(alice);
underlyingToken.approve(address(wHypERC4626), 0);
vm.expectRevert("WHypERC4626: wrap amount must be greater than 0");
wHypERC4626.wrap(0);
vm.stopPrank();
}
function test_unwrap() public {
uint256 amount = 100 * 10 ** 18;
vm.startPrank(alice);
underlyingToken.approve(address(wHypERC4626), amount);
uint256 wrappedAmount = wHypERC4626.wrap(amount);
uint256 unwrappedAmount = wHypERC4626.unwrap(wrappedAmount);
assertEq(wHypERC4626.balanceOf(alice), 0);
assertEq(underlyingToken.balanceOf(alice), 1000 * 10 ** 18);
assertEq(unwrappedAmount, amount);
vm.stopPrank();
}
function test_unwrap_revertsWhen_zeroAmount() public {
vm.startPrank(alice);
vm.expectRevert("WHypERC4626: unwrap amount must be greater than 0");
wHypERC4626.unwrap(0);
vm.stopPrank();
}
function test_getWrappedAmount() public view {
uint256 amount = 100 * 10 ** 18;
uint256 wrappedAmount = wHypERC4626.getWrappedAmount(amount);
assertEq(wrappedAmount, underlyingToken.assetsToShares(amount));
}
function test_getUnderlyingAmount() public view {
uint256 amount = 100 * 10 ** 18;
uint256 underlyingAmount = wHypERC4626.getUnderlyingAmount(amount);
assertEq(underlyingAmount, underlyingToken.sharesToAssets(amount));
}
function test_wrappedPerUnderlying() public view {
uint256 wrappedPerUnderlying = wHypERC4626.wrappedPerUnderlying();
assertEq(
wrappedPerUnderlying,
underlyingToken.assetsToShares(1 * 10 ** underlyingToken.decimals())
);
}
function test_underlyingPerWrapped() public view {
uint256 underlyingPerWrapped = wHypERC4626.underlyingPerWrapped();
assertEq(
underlyingPerWrapped,
underlyingToken.sharesToAssets(1 * 10 ** underlyingToken.decimals())
);
}
function test_decimals() public view {
uint8 decimals = wHypERC4626.decimals();
assertEq(decimals, underlyingToken.decimals());
}
}

@ -1,5 +1,7 @@
# @hyperlane-xyz/ccip-server
## 5.6.0
## 5.5.0
## 5.4.0

@ -1,6 +1,6 @@
{
"name": "@hyperlane-xyz/ccip-server",
"version": "5.5.0",
"version": "5.6.0",
"description": "CCIP server",
"typings": "dist/index.d.ts",
"typedocMain": "src/index.ts",

@ -0,0 +1,8 @@
{
"extensions": ["ts"],
"spec": ["src/**/*.e2e-test.ts"],
"node-option": [
"experimental-specifier-resolution=node",
"loader=ts-node/esm"
]
}

@ -1,6 +1,6 @@
{
"extensions": ["ts"],
"spec": ["src/**/*.test.*", "src/**/*.e2e-test.ts"],
"spec": ["src/**/*.test.*"],
"node-option": [
"experimental-specifier-resolution=node",
"loader=ts-node/esm"

@ -1,5 +1,38 @@
# @hyperlane-xyz/cli
## 5.6.0
### Minor Changes
- 41035aac8: Add strategyUrl detect and validation in the beginning of `warp apply`
Remove yaml transactions print from `warp apply`
- 29341950e: Adds new `core check` command to compare local configuration and on chain deployments. Adds memoization to the EvmHookReader to avoid repeating configuration derivation
- 32d0a67c2: Adds the warp check command to compare warp routes config files with on chain warp route deployments
- 3662297fc: Add prompt in `warp init` command to choose if a trusted relayer should be used instead of making the choice by default for the user and enable the `--yes` flag to default to a trusted ISM
- b1ff48bd1: Add rebasing yield route support into CLI/SDK
- d41aa6928: Add `EthJsonRpcBlockParameterTag` enum for validating reorgPeriod
- c3e9268f1: Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block.
- a4d5d692f: Update `warp apply` such that it updates in place AND extends in a single call
- 01e7070eb: updates the multi chain selection prompt by adding search functionality and an optional confirmation prompt for the current selection
### Patch Changes
- e89f9e35d: Update registry to v4.7.0
- Updated dependencies [f1712deb7]
- Updated dependencies [46044a2e9]
- Updated dependencies [02a5b92ba]
- Updated dependencies [29341950e]
- Updated dependencies [8001bbbd6]
- Updated dependencies [32d0a67c2]
- Updated dependencies [b1ff48bd1]
- Updated dependencies [d41aa6928]
- Updated dependencies [c3e9268f1]
- Updated dependencies [7d7bcc1a3]
- Updated dependencies [7f3e0669d]
- Updated dependencies [2317eca3c]
- @hyperlane-xyz/utils@5.6.0
- @hyperlane-xyz/sdk@5.6.0
## 5.5.0
### Patch Changes

@ -1,13 +1,13 @@
{
"name": "@hyperlane-xyz/cli",
"version": "5.5.0",
"version": "5.6.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": "4.7.0",
"@hyperlane-xyz/sdk": "5.5.0",
"@hyperlane-xyz/utils": "5.5.0",
"@hyperlane-xyz/sdk": "5.6.0",
"@hyperlane-xyz/utils": "5.6.0",
"@inquirer/prompts": "^3.0.0",
"ansi-escapes": "^7.0.0",
"asn1.js": "^5.4.1",
@ -47,7 +47,8 @@
"clean": "rm -rf ./dist",
"lint": "eslint . --ext .ts",
"prettier": "prettier --write ./src ./examples",
"test:ci": "./scripts/all-test.sh",
"test:ci": "yarn mocha --config .mocharc.json",
"test:e2e": "./scripts/run-e2e-test.sh",
"version:update": "echo \"export const VERSION = '$npm_package_version';\" > src/version.ts"
},
"files": [

@ -1,24 +1,24 @@
#!/usr/bin/env bash
function cleanup() {
set +e
set +e
pkill -f anvil
rm -rf /tmp/anvil2
rm -rf /tmp/anvil3
rm -f ./test-configs/anvil/chains/anvil2/addresses.yaml
rm -f ./test-configs/anvil/chains/anvil3/addresses.yaml
set -e
set -e
}
cleanup
echo "Starting anvil2 and anvil3 chain"
echo "Starting anvil2 and anvil3 chain for E2E tests"
anvil --chain-id 31338 -p 8555 --state /tmp/anvil2/state --gas-price 1 > /dev/null &
anvil --chain-id 31347 -p 8600 --state /tmp/anvil3/state --gas-price 1 > /dev/null &
echo "Running all tests"
yarn mocha --config .mocharc.json
echo "Running E2E tests"
yarn mocha --config .mocharc-e2e.json
cleanup
echo "Done all tests"
echo "Completed E2E tests"

@ -1,10 +1,13 @@
import { stringify as yamlStringify } from 'yaml';
import { CommandModule } from 'yargs';
import {
CoreConfig,
DeployedCoreAddresses,
DeployedCoreAddressesSchema,
EvmCoreReader,
normalizeConfig,
} from '@hyperlane-xyz/sdk';
import { diffObjMerge } from '@hyperlane-xyz/utils';
import {
createCoreDeployConfig,
@ -16,17 +19,21 @@ import {
} from '../context/types.js';
import { runCoreApply, runCoreDeploy } from '../deploy/core.js';
import { evaluateIfDryRunFailure } from '../deploy/dry-run.js';
import { errorRed, log, logGray, logGreen } from '../logger.js';
import { log, logCommandHeader, logGreen } from '../logger.js';
import { executeCoreRead } from '../read/core.js';
import {
logYamlIfUnderMaxLines,
readYamlOrJson,
writeYamlOrJson,
} from '../utils/files.js';
import { formatYamlViolationsOutput } from '../utils/output.js';
import {
DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH,
chainCommandOption,
dryRunCommandOption,
fromAddressCommandOption,
inputFileCommandOption,
outputFileCommandOption,
skipConfirmationOption,
} from './options.js';
@ -40,6 +47,7 @@ export const coreCommand: CommandModule = {
builder: (yargs) =>
yargs
.command(apply)
.command(check)
.command(deploy)
.command(init)
.command(read)
@ -47,6 +55,7 @@ export const coreCommand: CommandModule = {
.demandCommand(),
handler: () => log('Command required'),
};
export const apply: CommandModuleWithWriteContext<{
chain: string;
config: string;
@ -60,14 +69,13 @@ export const apply: CommandModuleWithWriteContext<{
demandOption: true,
},
config: outputFileCommandOption(
'./configs/core-config.yaml',
DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH,
true,
'The path to output a Core Config JSON or YAML file.',
),
},
handler: async ({ context, chain, config: configFilePath }) => {
logGray(`Hyperlane Core Apply`);
logGray('--------------------');
logCommandHeader(`Hyperlane Core Apply`);
const addresses = (await context.registry.getChainAddresses(
chain,
@ -103,7 +111,7 @@ export const deploy: CommandModuleWithWriteContext<{
builder: {
chain: chainCommandOption,
config: outputFileCommandOption(
'./configs/core-config.yaml',
DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH,
false,
'The path to a JSON or YAML file with a core deployment config.',
),
@ -112,8 +120,7 @@ export const deploy: CommandModuleWithWriteContext<{
'skip-confirmation': skipConfirmationOption,
},
handler: async ({ context, chain, config: configFilePath, dryRun }) => {
logGray(`Hyperlane Core deployment${dryRun ? ' dry-run' : ''}`);
logGray(`------------------------------------------------`);
logCommandHeader(`Hyperlane Core deployment${dryRun ? ' dry-run' : ''}`);
try {
await runCoreDeploy({
@ -142,14 +149,13 @@ export const init: CommandModuleWithContext<{
default: false,
},
config: outputFileCommandOption(
'./configs/core-config.yaml',
DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH,
false,
'The path to output a Core Config JSON or YAML file.',
),
},
handler: async ({ context, advanced, config: configFilePath }) => {
logGray('Hyperlane Core Configure');
logGray('------------------------');
logCommandHeader('Hyperlane Core Configure');
await createCoreDeployConfig({
context,
@ -178,39 +184,70 @@ export const read: CommandModuleWithContext<{
description: 'Mailbox address used to derive the core config',
},
config: outputFileCommandOption(
'./configs/core-config.yaml',
DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH,
false,
'The path to output a Core Config JSON or YAML file.',
),
},
handler: async ({ context, chain, mailbox, config: configFilePath }) => {
if (!mailbox) {
const addresses = await context.registry.getChainAddresses(chain);
mailbox = addresses?.mailbox;
if (!mailbox) {
throw new Error(
`${chain} mailbox not provided and none found in registry.`,
);
}
}
logCommandHeader('Hyperlane Core Read');
logGray('Hyperlane Core Read');
logGray('-------------------');
const coreConfig = await executeCoreRead({ context, chain, mailbox });
const evmCoreReader = new EvmCoreReader(context.multiProvider, chain);
try {
const coreConfig = await evmCoreReader.deriveCoreConfig(mailbox);
writeYamlOrJson(configFilePath, coreConfig, 'yaml');
logGreen(`✅ Core config written successfully to ${configFilePath}:\n`);
logYamlIfUnderMaxLines(coreConfig);
} catch (e: any) {
errorRed(
`❌ Failed to read core config for mailbox ${mailbox} on ${chain}:`,
e,
);
writeYamlOrJson(configFilePath, coreConfig, 'yaml');
logGreen(`✅ Core config written successfully to ${configFilePath}:\n`);
logYamlIfUnderMaxLines(coreConfig);
process.exit(0);
},
};
export const check: CommandModuleWithContext<{
chain: string;
config: string;
mailbox?: string;
}> = {
command: 'check',
describe:
'Reads onchain Core configuration for a given mailbox address and compares it with a provided file',
builder: {
chain: {
...chainCommandOption,
demandOption: true,
},
mailbox: {
type: 'string',
description:
'Mailbox address used to derive the core config. If not provided it will be inferred from the registry',
},
config: inputFileCommandOption({
defaultPath: DEFAULT_CORE_DEPLOYMENT_CONFIG_PATH,
description: 'The path to a a Core Config JSON or YAML file.',
demandOption: false,
}),
},
handler: async ({ context, chain, mailbox, config: configFilePath }) => {
logCommandHeader('Hyperlane Core Check');
const expectedCoreConfig: CoreConfig = await readYamlOrJson(configFilePath);
const onChainCoreConfig = await executeCoreRead({
context,
chain,
mailbox,
});
const { mergedObject, isInvalid } = diffObjMerge(
normalizeConfig(onChainCoreConfig),
normalizeConfig(expectedCoreConfig),
);
if (isInvalid) {
log(formatYamlViolationsOutput(yamlStringify(mergedObject, null, 2)));
process.exit(1);
}
logGreen(`No violations found`);
process.exit(0);
},
};

@ -94,6 +94,8 @@ export const hookCommandOption: Options = {
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 warpDeploymentConfigCommandOption: Options = {
type: 'string',
description:

@ -5,6 +5,7 @@ import { stringify as yamlStringify } from 'yaml';
import {
ChainMetadata,
ChainMetadataSchema,
EthJsonRpcBlockParameterTag,
ExplorerFamily,
ZChainName,
} from '@hyperlane-xyz/sdk';
@ -168,6 +169,13 @@ async function addBlockOrGasConfig(metadata: ChainMetadata): Promise<void> {
}
async function addBlockConfig(metadata: ChainMetadata): Promise<void> {
const parseReorgPeriod = (
value: string,
): number | EthJsonRpcBlockParameterTag => {
const parsed = parseInt(value, 10);
return isNaN(parsed) ? (value as EthJsonRpcBlockParameterTag) : parsed;
};
const wantBlockConfig = await confirm({
message: 'Do you want to add block config for this chain',
});
@ -179,8 +187,16 @@ async function addBlockConfig(metadata: ChainMetadata): Promise<void> {
});
const blockReorgPeriod = await input({
message:
'Enter no. of blocks before a transaction has a near-zero chance of reverting (0-500):',
validate: (value) => parseInt(value) >= 0 && parseInt(value) <= 500,
'Enter no. of blocks before a transaction has a near-zero chance of reverting (0-500) or block tag (earliest, latest, safe, finalized, pending):',
validate: (value) => {
const parsedInt = parseInt(value, 10);
return (
Object.values(EthJsonRpcBlockParameterTag).includes(
value as EthJsonRpcBlockParameterTag,
) ||
(!isNaN(parsedInt) && parsedInt >= 0 && parsedInt <= 500)
);
},
});
const blockTimeEstimate = await input({
message: 'Enter the rough estimate of time per block in seconds (0-20):',
@ -188,7 +204,7 @@ async function addBlockConfig(metadata: ChainMetadata): Promise<void> {
});
metadata.blocks = {
confirmations: parseInt(blockConfirmation, 10),
reorgPeriod: parseInt(blockReorgPeriod, 10),
reorgPeriod: parseReorgPeriod(blockReorgPeriod),
estimateBlockTime: parseInt(blockTimeEstimate, 10),
};
}

@ -0,0 +1,36 @@
import { ChainName, CoreConfig, EvmCoreReader } from '@hyperlane-xyz/sdk';
import { Address, assert } from '@hyperlane-xyz/utils';
import { CommandContext } from '../context/types.js';
import { errorRed } from '../logger.js';
export async function executeCoreRead({
context,
chain,
mailbox,
}: {
context: CommandContext;
chain: ChainName;
mailbox?: Address;
}): Promise<CoreConfig> {
if (!mailbox) {
const addresses = await context.registry.getChainAddresses(chain);
mailbox = addresses?.mailbox;
assert(
mailbox,
`${chain} mailbox not provided and none found in registry.`,
);
}
const evmCoreReader = new EvmCoreReader(context.multiProvider, chain);
try {
return evmCoreReader.deriveCoreConfig(mailbox);
} catch (e: any) {
errorRed(
`❌ Failed to read core config for mailbox ${mailbox} on ${chain}:`,
e,
);
process.exit(1);
}
}

@ -1 +1 @@
export const VERSION = '5.5.0';
export const VERSION = '5.6.0';

@ -1,5 +1,7 @@
# @hyperlane-xyz/github-proxy
## 5.6.0
## 5.5.0
## 5.4.0

@ -1,7 +1,7 @@
{
"name": "@hyperlane-xyz/github-proxy",
"description": "Github proxy that adds the API key to requests",
"version": "5.5.0",
"version": "5.6.0",
"private": true,
"scripts": {
"deploy": "wrangler deploy",

@ -1,5 +1,27 @@
# @hyperlane-xyz/helloworld
## 5.6.0
### Patch Changes
- e89f9e35d: Update registry to v4.7.0
- Updated dependencies [46044a2e9]
- Updated dependencies [02a5b92ba]
- Updated dependencies [29341950e]
- Updated dependencies [8001bbbd6]
- Updated dependencies [32d0a67c2]
- Updated dependencies [c9085afd9]
- Updated dependencies [b1ff48bd1]
- Updated dependencies [d41aa6928]
- Updated dependencies [ec6b874b1]
- Updated dependencies [c3e9268f1]
- Updated dependencies [72c23c0d6]
- Updated dependencies [7d7bcc1a3]
- Updated dependencies [7f3e0669d]
- Updated dependencies [2317eca3c]
- @hyperlane-xyz/sdk@5.6.0
- @hyperlane-xyz/core@5.5.0
## 5.5.0
### Patch Changes

@ -1,11 +1,11 @@
{
"name": "@hyperlane-xyz/helloworld",
"description": "A basic skeleton of an Hyperlane app",
"version": "5.5.0",
"version": "5.6.0",
"dependencies": {
"@hyperlane-xyz/core": "5.4.1",
"@hyperlane-xyz/core": "5.5.0",
"@hyperlane-xyz/registry": "4.7.0",
"@hyperlane-xyz/sdk": "5.5.0",
"@hyperlane-xyz/sdk": "5.6.0",
"@openzeppelin/contracts-upgradeable": "^4.9.3",
"ethers": "^5.7.2"
},

@ -1,5 +1,31 @@
# @hyperlane-xyz/infra
## 5.6.0
### Minor Changes
- b3495b205: Updates the warpIds for Renzo's latest deployment to Sei and Taiko to be used by the Checker
- c3e9268f1: Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block.
### Patch Changes
- Updated dependencies [f1712deb7]
- Updated dependencies [46044a2e9]
- Updated dependencies [02a5b92ba]
- Updated dependencies [29341950e]
- Updated dependencies [8001bbbd6]
- Updated dependencies [32d0a67c2]
- Updated dependencies [b1ff48bd1]
- Updated dependencies [e89f9e35d]
- Updated dependencies [d41aa6928]
- Updated dependencies [c3e9268f1]
- Updated dependencies [7d7bcc1a3]
- Updated dependencies [7f3e0669d]
- Updated dependencies [2317eca3c]
- @hyperlane-xyz/utils@5.6.0
- @hyperlane-xyz/sdk@5.6.0
- @hyperlane-xyz/helloworld@5.6.0
## 5.5.0
### Patch Changes

@ -115,6 +115,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
sei: true,
shibarium: true,
solanamainnet: true,
stride: false,
superposition: true,
taiko: true,
tangle: true,
@ -189,6 +190,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
sei: true,
shibarium: true,
solanamainnet: true,
stride: true,
superposition: true,
taiko: true,
tangle: true,
@ -264,6 +266,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig<
shibarium: true,
// Cannot scrape Sealevel chains
solanamainnet: false,
stride: true,
superposition: true,
taiko: true,
tangle: true,
@ -418,7 +421,7 @@ const hyperlane: RootAgentConfig = {
rpcConsensusType: RpcConsensusType.Fallback,
docker: {
repo,
tag: 'b1ff48b-20241016-183301',
tag: '42d6b50-20241021-155906',
},
gasPaymentEnforcement: gasPaymentEnforcement,
metricAppContexts,
@ -437,7 +440,7 @@ const hyperlane: RootAgentConfig = {
rpcConsensusType: RpcConsensusType.Fallback,
docker: {
repo,
tag: '9c0c4bb-20241018-113820',
tag: '42d6b50-20241021-155906',
},
resources: scraperResources,
},
@ -452,7 +455,7 @@ const releaseCandidate: RootAgentConfig = {
rpcConsensusType: RpcConsensusType.Fallback,
docker: {
repo,
tag: 'b1ff48b-20241016-183301',
tag: '42d6b50-20241021-155906',
},
// We're temporarily (ab)using the RC relayer as a way to increase
// message throughput.

@ -82,6 +82,8 @@ export const keyFunderConfig: KeyFunderConfig<
scroll: '0.5',
sei: '50',
shibarium: '50',
// ignore non-evm chains
stride: '0',
superposition: '0.05',
taiko: '0.2',
tangle: '2',

@ -243,6 +243,10 @@
"amount": "0.5",
"decimals": 1
},
"stride": {
"amount": "0.005",
"decimals": 1
},
"superposition": {
"amount": "0.01",
"decimals": 9

@ -62,6 +62,7 @@ export const mainnet3SupportedChainNames = [
'sei',
'shibarium',
'solanamainnet',
'stride',
'superposition',
'taiko',
'tangle',

@ -60,6 +60,7 @@
"sei": "0.447635",
"shibarium": "0.410927",
"solanamainnet": "155.35",
"stride": "0.840153",
"superposition": "2629.74",
"taiko": "2629.74",
"tangle": "1",

@ -0,0 +1,28 @@
# Configs and artifacts for the deployment of Hyperlane Warp Routes
description: Hyperlane Warp Route artifacts
timestamp: '2024-10-18T14:00:00.000Z'
deployer: Abacus Works (Hyperlane)
data:
config:
arbitrum:
protocolType: ethereum
type: synthetic
hypAddress: '0x6D251aADfc6Ff69031e01eA39bE3cb5BABf8438f'
name: Amphor Restaked ETH
symbol: AMPHRETH
decimals: 18
ethereum:
protocolType: ethereum
type: collateral
hypAddress: '0xdc89990a6fdC1C922b841f1d977835628A24Ed57'
tokenAddress: '0x5fD13359Ba15A84B76f7F87568309040176167cd'
name: Amphor Restaked ETH
symbol: AMPHRETH
decimals: 18
zircuit:
protocolType: ethereum
type: synthetic
hypAddress: '0x7D5a79539d7B1c9aE5e54d18EEE188840f1Fe4CC'
name: Amphor Restaked ETH
symbol: AMPHRETH
decimals: 18

@ -0,0 +1,55 @@
import { ethers } from 'ethers';
import {
ChainMap,
RouterConfig,
TokenRouterConfig,
TokenType,
} from '@hyperlane-xyz/sdk';
import { tokens } from '../../../../../src/config/warp.js';
const arbitrumOwner = '0x008615770B588633265cB01Abd19740fAe67d0B9';
const ethereumOwner = '0x008615770B588633265cB01Abd19740fAe67d0B9';
const zircuitOwner = '0xD0673e7F3FB4037CA79F53d2d311D0e017d39963';
export const getArbitrumEthereumZircuitAmphrETHWarpConfig = async (
routerConfig: ChainMap<RouterConfig>,
): Promise<ChainMap<TokenRouterConfig>> => {
const arbitrum: TokenRouterConfig = {
...routerConfig.arbitrum,
type: TokenType.synthetic,
interchainSecurityModule: ethers.constants.AddressZero,
owner: arbitrumOwner,
ownerOverrides: {
proxyAdmin: arbitrumOwner,
},
};
const ethereum: TokenRouterConfig = {
...routerConfig.ethereum,
type: TokenType.collateral,
token: tokens.ethereum.amphrETH,
owner: ethereumOwner,
interchainSecurityModule: ethers.constants.AddressZero,
ownerOverrides: {
proxyAdmin: ethereumOwner,
},
};
const zircuit: TokenRouterConfig = {
...routerConfig.zircuit,
type: TokenType.synthetic,
interchainSecurityModule: ethers.constants.AddressZero,
owner: zircuitOwner,
ownerOverrides: {
proxyAdmin: zircuitOwner,
},
};
return {
arbitrum,
ethereum,
zircuit,
};
};

@ -1,6 +1,7 @@
export enum WarpRouteIds {
Ancient8EthereumUSDC = 'USDC/ancient8-ethereum',
ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismSeiTaikoZircuitEZETH = 'EZETH/arbitrum-base-blast-bsc-ethereum-fraxtal-linea-mode-optimism-sei-taiko-zircuit',
ArbitrumEthereumZircuitAMPHRETH = 'AMPHRETH/arbitrum-ethereum-zircuit',
ArbitrumNeutronEclip = 'ECLIP/arbitrum-neutron',
ArbitrumNeutronTIA = 'TIA/arbitrum-neutron',
EclipseSolanaSOL = 'SOL/eclipsemainnet-solanamainnet',

@ -78,7 +78,7 @@ export function getDomainId(chainName: ChainName): number {
return resolveDomainId(chain);
}
export function getReorgPeriod(chainName: ChainName): number {
export function getReorgPeriod(chainName: ChainName): string | number {
const chain = getChain(chainName);
return resolveReorgPeriod(chain);
}

@ -9,6 +9,7 @@ import { getHyperlaneCore } from '../scripts/core-utils.js';
import { EnvironmentConfig } from '../src/config/environment.js';
import { getAncient8EthereumUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getAncient8EthereumUSDCWarpConfig.js';
import { getArbitrumEthereumZircuitAmphrETHWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumEthereumZircuitAmphrETHWarpConfig.js';
import { getArbitrumNeutronEclipWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronEclipWarpConfig.js';
import { getArbitrumNeutronTiaWarpConfig } from './environments/mainnet3/warp/configGetters/getArbitrumNeutronTiaWarpConfig.js';
import { getEthereumInevmUSDCWarpConfig } from './environments/mainnet3/warp/configGetters/getEthereumInevmUSDCWarpConfig.js';
@ -34,6 +35,8 @@ export const warpConfigGetterMap: Record<
WarpConfigGetterWithConfig | WarpConfigGetterWithoutConfig
> = {
[WarpRouteIds.Ancient8EthereumUSDC]: getAncient8EthereumUSDCWarpConfig,
[WarpRouteIds.ArbitrumEthereumZircuitAMPHRETH]:
getArbitrumEthereumZircuitAmphrETHWarpConfig,
[WarpRouteIds.EthereumInevmUSDC]: getEthereumInevmUSDCWarpConfig,
[WarpRouteIds.EthereumInevmUSDT]: getEthereumInevmUSDTWarpConfig,
[WarpRouteIds.ArbitrumNeutronEclip]: getArbitrumNeutronEclipWarpConfig,

@ -1,7 +1,7 @@
{
"name": "@hyperlane-xyz/infra",
"description": "Infrastructure utilities for the Hyperlane Network",
"version": "5.5.0",
"version": "5.6.0",
"dependencies": {
"@arbitrum/sdk": "^3.0.0",
"@aws-sdk/client-iam": "^3.74.0",
@ -13,10 +13,10 @@
"@ethersproject/hardware-wallets": "^5.7.0",
"@ethersproject/providers": "^5.7.2",
"@google-cloud/secret-manager": "^5.5.0",
"@hyperlane-xyz/helloworld": "5.5.0",
"@hyperlane-xyz/helloworld": "5.6.0",
"@hyperlane-xyz/registry": "4.7.0",
"@hyperlane-xyz/sdk": "5.5.0",
"@hyperlane-xyz/utils": "5.5.0",
"@hyperlane-xyz/sdk": "5.6.0",
"@hyperlane-xyz/utils": "5.6.0",
"@inquirer/prompts": "^5.3.8",
"@nomiclabs/hardhat-etherscan": "^3.0.3",
"@safe-global/api-kit": "1.3.0",

@ -26,8 +26,8 @@ export type ValidatorBaseChainConfigMap = ChainMap<ValidatorBaseChainConfig>;
export interface ValidatorBaseChainConfig {
// How frequently to check for new checkpoints
interval: number;
// The reorg_period in blocks; overrides chain metadata
reorgPeriod: number;
// The reorg_period in blocks or block tag; overrides chain metadata
reorgPeriod: string | number;
// Individual validator agents
validators: Array<ValidatorBaseConfig>;
}

@ -7,6 +7,7 @@ export const tokens: ChainMap<Record<string, Address>> = {
USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
USDT: '0xdac17f958d2ee523a2206206994597c13d831ec7',
deUSD: '0x15700B564Ca08D9439C58cA5053166E8317aa138',
amphrETH: '0x5fD13359Ba15A84B76f7F87568309040176167cd',
},
sei: {
fastUSD: '0x37a4dD9CED2b19Cfe8FAC251cd727b5787E45269',

@ -166,17 +166,23 @@ export abstract class HyperlaneAppGovernor<
// If calls are being submitted via a safe, we need to check for any safe owner changes first
if (submissionType === SubmissionType.SAFE) {
const { safeSdk } = await getSafeAndService(
chain,
this.checker.multiProvider,
(multiSend as SafeMultiSend).safeAddress,
);
const updateOwnerCalls = await updateSafeOwner(safeSdk);
callsForSubmissionType.push(...updateOwnerCalls, ...filteredCalls);
} else {
callsForSubmissionType.push(...filteredCalls);
try {
const { safeSdk } = await getSafeAndService(
chain,
this.checker.multiProvider,
(multiSend as SafeMultiSend).safeAddress,
);
const updateOwnerCalls = await updateSafeOwner(safeSdk);
callsForSubmissionType.push(...updateOwnerCalls);
} catch (error) {
// Catch but don't throw because we want to try submitting any remaining calls
console.error(`Error updating safe owner: ${error}`);
}
}
// Add the filtered calls to the calls for submission type
callsForSubmissionType.push(...filteredCalls);
if (callsForSubmissionType.length > 0) {
this.printSeparator();
const confirmed = await summarizeCalls(

@ -27,7 +27,7 @@ export class WarpRouteMonitorHelmManager extends HelmManager {
return {
image: {
repository: 'gcr.io/abacus-labs-dev/hyperlane-monorepo',
tag: 'd4d5501-20240925-222735',
tag: '6945b20-20241022-155935',
},
configFilePath: pathRelativeToMonorepoRoot,
fullnameOverride: this.helmReleaseName,

@ -1,5 +1,31 @@
# @hyperlane-xyz/sdk
## 5.6.0
### Minor Changes
- 46044a2e9: Deploy to odysseytestnet
- 02a5b92ba: Enroll new validators. Add tx overrides when deploying ICA accounts. Core checker now surfaces owner violations for defaultHook and requiredHook. App checker temporarily ignores bytecode mismatch violations.
- 29341950e: Adds new `core check` command to compare local configuration and on chain deployments. Adds memoization to the EvmHookReader to avoid repeating configuration derivation
- 8001bbbd6: Add override to some transactions to fix warp apply
- 32d0a67c2: Adds the warp check command to compare warp routes config files with on chain warp route deployments
- b1ff48bd1: Add rebasing yield route support into CLI/SDK
- d41aa6928: Add `EthJsonRpcBlockParameterTag` enum for validating reorgPeriod
- c3e9268f1: Add support for an arbitrary string in `reorgPeriod`, which is used as a block tag to get the finalized block.
- 7d7bcc1a3: Add deployments for mainnets: flow, metall2, polynomial
### Patch Changes
- 7f3e0669d: Fix filtering non-evm addresses in appFromAddressesMapHelper
- 2317eca3c: Set transaction overrides and add 10% gas limit buffer when sending message through HyperlaneCore.
- Updated dependencies [f1712deb7]
- Updated dependencies [29341950e]
- Updated dependencies [c9085afd9]
- Updated dependencies [ec6b874b1]
- Updated dependencies [72c23c0d6]
- @hyperlane-xyz/utils@5.6.0
- @hyperlane-xyz/core@5.5.0
## 5.5.0
### Minor Changes

@ -1,14 +1,14 @@
{
"name": "@hyperlane-xyz/sdk",
"description": "The official SDK for the Hyperlane Network",
"version": "5.5.0",
"version": "5.6.0",
"dependencies": {
"@arbitrum/sdk": "^4.0.0",
"@aws-sdk/client-s3": "^3.74.0",
"@cosmjs/cosmwasm-stargate": "^0.32.4",
"@cosmjs/stargate": "^0.32.4",
"@hyperlane-xyz/core": "5.4.1",
"@hyperlane-xyz/utils": "5.5.0",
"@hyperlane-xyz/core": "5.5.0",
"@hyperlane-xyz/utils": "5.6.0",
"@safe-global/api-kit": "1.3.0",
"@safe-global/protocol-kit": "1.3.0",
"@safe-global/safe-deployments": "1.37.8",

@ -1,4 +1,4 @@
import { Contract, ethers } from 'ethers';
import { Contract } from 'ethers';
import { Ownable } from '@hyperlane-xyz/core';
import {
@ -235,31 +235,15 @@ export function appFromAddressesMapHelper<F extends HyperlaneFactories>(
contractsMap: HyperlaneContractsMap<F>;
multiProvider: MultiProvider;
} {
// Hack to accommodate non-Ethereum artifacts, while still retaining their
// presence in the addressesMap so that they are included in the list of chains
// on the MultiProvider (needed for getting metadata). A non-Ethereum-style address
// from another execution environment will cause Ethers to throw if we try to attach
// it, so we just replace it with the zero address.
const addressesMapWithEthereumizedAddresses = objMap(
// Filter out non-Ethereum chains from the addressesMap
const ethereumAddressesMap = objFilter(
addressesMap,
(chain, addresses) => {
const metadata = multiProvider.getChainMetadata(chain);
if (metadata.protocol === ProtocolType.Ethereum) {
return addresses;
}
return objMap(
addresses,
(_key, _address) => ethers.constants.AddressZero,
);
},
(chain, _): _ is HyperlaneAddresses<F> =>
multiProvider.getProtocol(chain) === ProtocolType.Ethereum,
);
// Attaches contracts for each chain for which we have a complete set of
// addresses
const contractsMap = attachContractsMap(
addressesMapWithEthereumizedAddresses,
factories,
);
// Attaches contracts for each Ethereum chain for which we have a complete set of addresses
const contractsMap = attachContractsMap(ethereumAddressesMap, factories);
// Filters out providers for chains for which we don't have a complete set
// of addresses
@ -270,6 +254,6 @@ export function appFromAddressesMapHelper<F extends HyperlaneFactories>(
return {
contractsMap: filteredContractsMap,
multiProvider: multiProvider,
multiProvider,
};
}

@ -83,6 +83,12 @@ export interface HookReader {
export class EvmHookReader extends HyperlaneReader implements HookReader {
protected readonly logger = rootLogger.child({ module: 'EvmHookReader' });
/**
* HookConfig cache for already retrieved configs. Useful to avoid recomputing configs
* when they have already been retrieved in previous calls where `deriveHookConfig` was called by
* the specific hook methods.
*/
private _cache: Map<Address, any> = new Map();
constructor(
protected readonly multiProvider: MultiProvider,
@ -95,8 +101,23 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
}
async deriveHookConfig(address: Address): Promise<DerivedHookConfig> {
this.logger.debug('Deriving HookConfig:', { address });
const cachedValue = this._cache.get(address);
if (cachedValue) {
this.logger.debug(
`Cache hit for HookConfig on chain ${this.chain} at: ${address}`,
);
return cachedValue;
}
this.logger.debug(
`Cache miss for HookConfig on chain ${this.chain} at: ${address}`,
);
let onchainHookType: OnchainHookType | undefined = undefined;
let derivedHookConfig: DerivedHookConfig;
try {
const hook = IPostDispatchHook__factory.connect(address, this.provider);
this.logger.debug('Deriving HookConfig:', { address });
@ -168,10 +189,14 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
const hook = MerkleTreeHook__factory.connect(address, this.provider);
this.assertHookType(await hook.hookType(), OnchainHookType.MERKLE_TREE);
return {
const config: WithAddress<MerkleTreeHookConfig> = {
address,
type: HookType.MERKLE_TREE,
};
this._cache.set(address, config);
return config;
}
async deriveAggregationConfig(
@ -187,11 +212,15 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
(hook) => this.deriveHookConfig(hook),
);
return {
const config: WithAddress<AggregationHookConfig> = {
address,
type: HookType.AGGREGATION,
hooks: hookConfigs,
};
this._cache.set(address, config);
return config;
}
async deriveIgpConfig(address: Address): Promise<WithAddress<IgpHookConfig>> {
@ -259,7 +288,7 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
oracleKey = resolvedOracleKeys[0];
}
return {
const config: WithAddress<IgpHookConfig> = {
owner,
address,
type: HookType.INTERCHAIN_GAS_PAYMASTER,
@ -268,6 +297,10 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
overhead,
oracleConfig,
};
this._cache.set(address, config);
return config;
}
async deriveProtocolFeeConfig(
@ -281,7 +314,7 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
const protocolFee = await hook.protocolFee();
const beneficiary = await hook.beneficiary();
return {
const config: WithAddress<ProtocolFeeHookConfig> = {
owner,
address,
type: HookType.PROTOCOL_FEE,
@ -289,6 +322,10 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
protocolFee: protocolFee.toString(),
beneficiary,
};
this._cache.set(address, config);
return config;
}
async deriveOpStackConfig(
@ -303,13 +340,17 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
const destinationChainName =
this.multiProvider.getChainName(destinationDomain);
return {
const config: WithAddress<OpStackHookConfig> = {
owner,
address,
type: HookType.OP_STACK,
nativeBridge: messengerContract,
destinationChain: destinationChainName,
};
this._cache.set(address, config);
return config;
}
async deriveArbL2ToL1Config(
@ -321,12 +362,17 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
const destinationDomain = await hook.destinationDomain();
const destinationChainName =
this.multiProvider.getChainName(destinationDomain);
return {
const config: WithAddress<ArbL2ToL1HookConfig> = {
address,
type: HookType.ARB_L2_TO_L1,
destinationChain: destinationChainName,
arbSys,
};
this._cache.set(address, config);
return config;
}
async deriveDomainRoutingConfig(
@ -338,12 +384,16 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
const owner = await hook.owner();
const domainHooks = await this.fetchDomainHooks(hook);
return {
const config: WithAddress<DomainRoutingHookConfig> = {
owner,
address,
type: HookType.ROUTING,
domains: domainHooks,
};
this._cache.set(address, config);
return config;
}
async deriveFallbackRoutingConfig(
@ -364,13 +414,17 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
const fallbackHook = await hook.fallbackHook();
const fallbackHookConfig = await this.deriveHookConfig(fallbackHook);
return {
const config: WithAddress<FallbackRoutingHookConfig> = {
owner,
address,
type: HookType.FALLBACK_ROUTING,
domains: domainHooks,
fallback: fallbackHookConfig,
};
this._cache.set(address, config);
return config;
}
private async fetchDomainHooks(
@ -406,12 +460,16 @@ export class EvmHookReader extends HyperlaneReader implements HookReader {
const owner = await hook.owner();
const paused = await hook.paused();
return {
const config: WithAddress<PausableHookConfig> = {
owner,
address,
paused,
type: HookType.PAUSABLE,
};
this._cache.set(address, config);
return config;
}
assertHookType(

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

Loading…
Cancel
Save