diff --git a/.changeset/five-spoons-complain.md b/.changeset/five-spoons-complain.md deleted file mode 100644 index accb56482e..0000000000 --- a/.changeset/five-spoons-complain.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/infra': minor -'@hyperlane-xyz/sdk': minor ---- - -Redeploy Routing ISM Factories diff --git a/.changeset/many-apes-invite.md b/.changeset/many-apes-invite.md deleted file mode 100644 index ef6ce96c4b..0000000000 --- a/.changeset/many-apes-invite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/sdk': patch ---- - -Remove dead arbitrum goerli explorer link" diff --git a/.changeset/modern-guests-push.md b/.changeset/modern-guests-push.md new file mode 100644 index 0000000000..ca8e62df12 --- /dev/null +++ b/.changeset/modern-guests-push.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/sdk': minor +--- + +Add dsrv, staked and zeeprime as validators diff --git a/.changeset/tame-cougars-attack.md b/.changeset/tame-cougars-attack.md deleted file mode 100644 index f7bd08304f..0000000000 --- a/.changeset/tame-cougars-attack.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@hyperlane-xyz/infra': patch -'@hyperlane-xyz/sdk': patch ---- - -Adds Test Recipient addresses to the SDK artifacts diff --git a/.changeset/witty-jobs-sit.md b/.changeset/witty-jobs-sit.md deleted file mode 100644 index f748f0689e..0000000000 --- a/.changeset/witty-jobs-sit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@hyperlane-xyz/cli': patch ---- - -Skip mandatory balance check for remotes in send commands" diff --git a/rust/agents/relayer/src/msg/metadata/aggregation.rs b/rust/agents/relayer/src/msg/metadata/aggregation.rs index ffcde517df..fed501b622 100644 --- a/rust/agents/relayer/src/msg/metadata/aggregation.rs +++ b/rust/agents/relayer/src/msg/metadata/aggregation.rs @@ -9,7 +9,7 @@ use tracing::{info, instrument}; use hyperlane_core::{HyperlaneMessage, InterchainSecurityModule, ModuleType, H256, U256}; -use super::{BaseMetadataBuilder, MetadataBuilder}; +use super::{MessageMetadataBuilder, MetadataBuilder}; /// Bytes used to store one member of the (start, end) range tuple /// Copied from `AggregationIsmMetadata.sol` @@ -17,7 +17,7 @@ const METADATA_RANGE_SIZE: usize = 4; #[derive(Clone, Debug, new, Deref)] pub struct AggregationIsmMetadataBuilder { - base: BaseMetadataBuilder, + base: MessageMetadataBuilder, } #[derive(Clone, Debug, new, PartialEq, Eq)] diff --git a/rust/agents/relayer/src/msg/metadata/base.rs b/rust/agents/relayer/src/msg/metadata/base.rs index 054cd8574e..65dda6181f 100644 --- a/rust/agents/relayer/src/msg/metadata/base.rs +++ b/rust/agents/relayer/src/msg/metadata/base.rs @@ -1,4 +1,11 @@ -use std::{collections::HashMap, fmt::Debug, str::FromStr, sync::Arc}; +use std::{ + collections::HashMap, + fmt::Debug, + ops::Deref, + str::FromStr, + sync::Arc, + time::{Duration, Instant}, +}; use crate::{ merkle_tree::builder::MerkleTreeBuilder, @@ -7,6 +14,7 @@ use crate::{ AggregationIsmMetadataBuilder, CcipReadIsmMetadataBuilder, NullMetadataBuilder, RoutingIsmMetadataBuilder, }, + settings::matching_list::MatchingList, }; use async_trait::async_trait; use derive_new::new; @@ -18,9 +26,10 @@ use hyperlane_base::{ }; use hyperlane_core::{ accumulator::merkle::Proof, AggregationIsm, CcipReadIsm, Checkpoint, HyperlaneDomain, - HyperlaneMessage, InterchainSecurityModule, ModuleType, MultisigIsm, RoutingIsm, + HyperlaneMessage, InterchainSecurityModule, Mailbox, ModuleType, MultisigIsm, RoutingIsm, ValidatorAnnounce, H160, H256, }; + use tokio::sync::RwLock; use tracing::{debug, info, instrument, warn}; @@ -40,39 +49,129 @@ pub struct IsmWithMetadataAndType { #[async_trait] pub trait MetadataBuilder: Send + Sync { - #[allow(clippy::async_yields_async)] async fn build(&self, ism_address: H256, message: &HyperlaneMessage) -> Result>>; } -#[derive(Clone, new)] -pub struct BaseMetadataBuilder { - destination_chain_setup: ChainConf, - origin_prover_sync: Arc>, - origin_validator_announce: Arc, - allow_local_checkpoint_syncers: bool, - metrics: Arc, - db: HyperlaneRocksDB, +/// Allows fetching the default ISM, caching the value for a period of time +/// to avoid fetching it all the time. +/// TODO: make this generic +#[derive(Debug)] +pub struct DefaultIsmCache { + value: RwLock>, + mailbox: Arc, +} + +impl DefaultIsmCache { + /// Time to live for the cached default ISM. 10 mins. + const TTL: Duration = Duration::from_secs(60 * 10); + + pub fn new(mailbox: Arc) -> Self { + Self { + value: RwLock::new(None), + mailbox, + } + } + + /// Gets the default ISM, fetching it from onchain if the cached value + /// is stale. + /// TODO: this can and should be made generic eventually + pub async fn get(&self) -> Result { + // If the duration since the value was last updated does not + // exceed the TTL, return the cached value. + // This is in its own block to avoid holding the lock during the + // async operation to fetch the on-chain default ISM if + // the cached value is stale. + { + let value = self.value.read().await; + + if let Some(value) = *value { + if value.1.elapsed() < Self::TTL { + return Ok(value.0); + } + } + } + + let default_ism = self.mailbox.default_ism().await?; + // Update the cached value. + { + let mut value = self.value.write().await; + *value = Some((default_ism, Instant::now())); + } + + Ok(default_ism) + } +} + +/// Classifies messages into an app context if they have one. +#[derive(Debug)] +pub struct AppContextClassifier { + default_ism: DefaultIsmCache, + app_matching_lists: Vec<(MatchingList, String)>, +} + +impl AppContextClassifier { + pub fn new( + destination_mailbox: Arc, + app_matching_lists: Vec<(MatchingList, String)>, + ) -> Self { + Self { + default_ism: DefaultIsmCache::new(destination_mailbox), + app_matching_lists, + } + } + + /// Classifies messages into an app context if they have one, or None + /// if they don't. + /// An app context is a string that identifies the app that sent the message + /// and exists just for metrics. + /// An app context is chosen based on: + /// - the first element in `app_matching_lists` that matches the message + /// - if the message's ISM is the default ISM, the app context is "default_ism" + pub async fn get_app_context( + &self, + message: &HyperlaneMessage, + root_ism: H256, + ) -> Result> { + // Give priority to the matching list. If the app from the matching list happens + // to use the default ISM, it's preferable to use the app context from the matching + // list. + for (matching_list, app_context) in self.app_matching_lists.iter() { + if matching_list.msg_matches(message, false) { + return Ok(Some(app_context.clone())); + } + } + + let default_ism = self.default_ism.get().await?; + if root_ism == default_ism { + return Ok(Some("default_ism".to_string())); + } + + Ok(None) + } +} + +/// Builds metadata for a message. +#[derive(Debug, Clone)] +pub struct MessageMetadataBuilder { + pub base: Arc, /// ISMs can be structured recursively. We keep track of the depth /// of the recursion to avoid infinite loops. - #[new(default)] - depth: u32, - max_depth: u32, + pub depth: u32, + pub app_context: Option, } -impl Debug for BaseMetadataBuilder { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "MetadataBuilder {{ chain_setup: {:?}, validator_announce: {:?} }}", - self.destination_chain_setup, self.origin_validator_announce - ) +impl Deref for MessageMetadataBuilder { + type Target = BaseMetadataBuilder; + + fn deref(&self) -> &Self::Target { + &self.base } } #[async_trait] -impl MetadataBuilder for BaseMetadataBuilder { - #[instrument(err, skip(self), fields(domain=self.domain().name()))] +impl MetadataBuilder for MessageMetadataBuilder { + #[instrument(err, skip(self), fields(destination_domain=self.destination_domain().name()))] async fn build( &self, ism_address: H256, @@ -84,12 +183,24 @@ impl MetadataBuilder for BaseMetadataBuilder { } } -impl BaseMetadataBuilder { - pub fn domain(&self) -> &HyperlaneDomain { - &self.destination_chain_setup.domain +impl MessageMetadataBuilder { + pub async fn new( + ism_address: H256, + message: &HyperlaneMessage, + base: Arc, + ) -> Result { + let app_context = base + .app_context_classifier + .get_app_context(message, ism_address) + .await?; + Ok(Self { + base, + depth: 0, + app_context, + }) } - pub fn clone_with_incremented_depth(&self) -> Result { + fn clone_with_incremented_depth(&self) -> Result { let mut cloned = self.clone(); cloned.depth += 1; if cloned.depth > cloned.max_depth { @@ -99,6 +210,82 @@ impl BaseMetadataBuilder { } } + #[instrument(err, skip(self), fields(destination_domain=self.destination_domain().name()))] + pub async fn build_ism_and_metadata( + &self, + ism_address: H256, + message: &HyperlaneMessage, + ) -> Result { + let ism: Box = self + .build_ism(ism_address) + .await + .context("When building ISM")?; + + let module_type = ism + .module_type() + .await + .context("When fetching module type")?; + let cloned = self.clone_with_incremented_depth()?; + + let metadata_builder: Box = match module_type { + ModuleType::MerkleRootMultisig => { + Box::new(MerkleRootMultisigMetadataBuilder::new(cloned)) + } + ModuleType::MessageIdMultisig => { + Box::new(MessageIdMultisigMetadataBuilder::new(cloned)) + } + ModuleType::Routing => Box::new(RoutingIsmMetadataBuilder::new(cloned)), + ModuleType::Aggregation => Box::new(AggregationIsmMetadataBuilder::new(cloned)), + ModuleType::Null => Box::new(NullMetadataBuilder::new()), + ModuleType::CcipRead => Box::new(CcipReadIsmMetadataBuilder::new(cloned)), + _ => return Err(MetadataBuilderError::UnsupportedModuleType(module_type).into()), + }; + let meta = metadata_builder + .build(ism_address, message) + .await + .context("When building metadata"); + Ok(IsmWithMetadataAndType { + ism, + metadata: meta?, + module_type, + }) + } +} + +/// Base metadata builder with types used by higher level metadata builders. +#[allow(clippy::too_many_arguments)] +#[derive(new)] +pub struct BaseMetadataBuilder { + origin_domain: HyperlaneDomain, + destination_chain_setup: ChainConf, + origin_prover_sync: Arc>, + origin_validator_announce: Arc, + allow_local_checkpoint_syncers: bool, + metrics: Arc, + db: HyperlaneRocksDB, + max_depth: u32, + app_context_classifier: AppContextClassifier, +} + +impl Debug for BaseMetadataBuilder { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "BaseMetadataBuilder {{ origin_domain: {:?} destination_chain_setup: {:?}, validator_announce: {:?} }}", + self.origin_domain, self.destination_chain_setup, self.origin_validator_announce + ) + } +} + +impl BaseMetadataBuilder { + pub fn origin_domain(&self) -> &HyperlaneDomain { + &self.origin_domain + } + + pub fn destination_domain(&self) -> &HyperlaneDomain { + &self.destination_chain_setup.domain + } + pub async fn get_proof(&self, leaf_index: u32, checkpoint: Checkpoint) -> Result { const CTX: &str = "When fetching message proof"; let proof = self @@ -162,6 +349,7 @@ impl BaseMetadataBuilder { pub async fn build_checkpoint_syncer( &self, validators: &[H256], + app_context: Option, ) -> Result { let storage_locations = self .origin_validator_announce @@ -221,45 +409,10 @@ impl BaseMetadataBuilder { } } } - Ok(MultisigCheckpointSyncer::new(checkpoint_syncers)) - } - - #[instrument(err, skip(self), fields(domain=self.domain().name()))] - pub async fn build_ism_and_metadata( - &self, - ism_address: H256, - message: &HyperlaneMessage, - ) -> Result { - let ism: Box = self - .build_ism(ism_address) - .await - .context("When building ISM")?; - - let module_type = ism - .module_type() - .await - .context("When fetching module type")?; - let base = self.clone_with_incremented_depth()?; - - let metadata_builder: Box = match module_type { - ModuleType::MerkleRootMultisig => { - Box::new(MerkleRootMultisigMetadataBuilder::new(base)) - } - ModuleType::MessageIdMultisig => Box::new(MessageIdMultisigMetadataBuilder::new(base)), - ModuleType::Routing => Box::new(RoutingIsmMetadataBuilder::new(base)), - ModuleType::Aggregation => Box::new(AggregationIsmMetadataBuilder::new(base)), - ModuleType::Null => Box::new(NullMetadataBuilder::new()), - ModuleType::CcipRead => Box::new(CcipReadIsmMetadataBuilder::new(base)), - _ => return Err(MetadataBuilderError::UnsupportedModuleType(module_type).into()), - }; - let meta = metadata_builder - .build(ism_address, message) - .await - .context("When building metadata"); - Ok(IsmWithMetadataAndType { - ism, - metadata: meta?, - module_type, - }) + Ok(MultisigCheckpointSyncer::new( + checkpoint_syncers, + self.metrics.clone(), + app_context, + )) } } diff --git a/rust/agents/relayer/src/msg/metadata/ccip_read.rs b/rust/agents/relayer/src/msg/metadata/ccip_read.rs index 7bce48ce40..ea4cef3472 100644 --- a/rust/agents/relayer/src/msg/metadata/ccip_read.rs +++ b/rust/agents/relayer/src/msg/metadata/ccip_read.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; use serde_json::json; use tracing::{info, instrument}; -use super::{BaseMetadataBuilder, MetadataBuilder}; +use super::{base::MessageMetadataBuilder, MetadataBuilder}; #[derive(Serialize, Deserialize)] struct OffchainResponse { @@ -20,7 +20,7 @@ struct OffchainResponse { #[derive(Clone, Debug, new, Deref)] pub struct CcipReadIsmMetadataBuilder { - base: BaseMetadataBuilder, + base: MessageMetadataBuilder, } #[async_trait] diff --git a/rust/agents/relayer/src/msg/metadata/mod.rs b/rust/agents/relayer/src/msg/metadata/mod.rs index 258a10a74f..2b3c3bf3d7 100644 --- a/rust/agents/relayer/src/msg/metadata/mod.rs +++ b/rust/agents/relayer/src/msg/metadata/mod.rs @@ -6,8 +6,8 @@ mod null_metadata; mod routing; use aggregation::AggregationIsmMetadataBuilder; -pub(crate) use base::BaseMetadataBuilder; pub(crate) use base::MetadataBuilder; +pub(crate) use base::{AppContextClassifier, BaseMetadataBuilder, MessageMetadataBuilder}; use ccip_read::CcipReadIsmMetadataBuilder; use null_metadata::NullMetadataBuilder; use routing::RoutingIsmMetadataBuilder; diff --git a/rust/agents/relayer/src/msg/metadata/multisig/base.rs b/rust/agents/relayer/src/msg/metadata/multisig/base.rs index cbe6226158..328b8848ba 100644 --- a/rust/agents/relayer/src/msg/metadata/multisig/base.rs +++ b/rust/agents/relayer/src/msg/metadata/multisig/base.rs @@ -12,7 +12,8 @@ use hyperlane_core::{HyperlaneMessage, MultisigSignedCheckpoint, H256}; use strum::Display; use tracing::{debug, info}; -use crate::msg::metadata::BaseMetadataBuilder; +use crate::msg::metadata::base::MessageMetadataBuilder; + use crate::msg::metadata::MetadataBuilder; #[derive(new, AsRef, Deref)] @@ -36,7 +37,7 @@ pub enum MetadataToken { } #[async_trait] -pub trait MultisigIsmMetadataBuilder: AsRef + Send + Sync { +pub trait MultisigIsmMetadataBuilder: AsRef + Send + Sync { async fn fetch_metadata( &self, validators: &[H256], @@ -92,7 +93,6 @@ pub trait MultisigIsmMetadataBuilder: AsRef + Send + Sync { #[async_trait] impl MetadataBuilder for T { - #[allow(clippy::async_yields_async)] async fn build( &self, ism_address: H256, @@ -117,7 +117,7 @@ impl MetadataBuilder for T { let checkpoint_syncer = self .as_ref() - .build_checkpoint_syncer(&validators) + .build_checkpoint_syncer(&validators, self.as_ref().app_context.clone()) .await .context(CTX)?; diff --git a/rust/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs b/rust/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs index 125aa918d5..b8bcca0402 100644 --- a/rust/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs +++ b/rust/agents/relayer/src/msg/metadata/multisig/merkle_root_multisig.rs @@ -9,12 +9,12 @@ use hyperlane_base::MultisigCheckpointSyncer; use hyperlane_core::{unwrap_or_none_result, HyperlaneMessage, H256}; use tracing::debug; -use crate::msg::metadata::BaseMetadataBuilder; +use crate::msg::metadata::MessageMetadataBuilder; use super::base::{MetadataToken, MultisigIsmMetadataBuilder, MultisigMetadata}; #[derive(Debug, Clone, Deref, new, AsRef)] -pub struct MerkleRootMultisigMetadataBuilder(BaseMetadataBuilder); +pub struct MerkleRootMultisigMetadataBuilder(MessageMetadataBuilder); #[async_trait] impl MultisigIsmMetadataBuilder for MerkleRootMultisigMetadataBuilder { fn token_layout(&self) -> Vec { @@ -55,7 +55,9 @@ impl MultisigIsmMetadataBuilder for MerkleRootMultisigMetadataBuilder { validators, threshold as usize, leaf_index, - highest_leaf_index + highest_leaf_index, + self.origin_domain(), + self.destination_domain(), ) .await .context(CTX)?, diff --git a/rust/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs b/rust/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs index e5feffb85f..9866c98b07 100644 --- a/rust/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs +++ b/rust/agents/relayer/src/msg/metadata/multisig/message_id_multisig.rs @@ -9,12 +9,12 @@ use hyperlane_base::MultisigCheckpointSyncer; use hyperlane_core::{unwrap_or_none_result, HyperlaneMessage, H256}; use tracing::{debug, warn}; -use crate::msg::metadata::BaseMetadataBuilder; +use crate::msg::metadata::MessageMetadataBuilder; use super::base::{MetadataToken, MultisigIsmMetadataBuilder, MultisigMetadata}; #[derive(Debug, Clone, Deref, new, AsRef)] -pub struct MessageIdMultisigMetadataBuilder(BaseMetadataBuilder); +pub struct MessageIdMultisigMetadataBuilder(MessageMetadataBuilder); #[async_trait] impl MultisigIsmMetadataBuilder for MessageIdMultisigMetadataBuilder { @@ -46,6 +46,16 @@ impl MultisigIsmMetadataBuilder for MessageIdMultisigMetadataBuilder { "No merkle leaf found for message id, must have not been enqueued in the tree" ) ); + + // Update the validator latest checkpoint metrics. + let _ = checkpoint_syncer + .get_validator_latest_checkpoints_and_update_metrics( + validators, + self.origin_domain(), + self.destination_domain(), + ) + .await; + let quorum_checkpoint = unwrap_or_none_result!( checkpoint_syncer .fetch_checkpoint(validators, threshold as usize, leaf_index) diff --git a/rust/agents/relayer/src/msg/metadata/routing.rs b/rust/agents/relayer/src/msg/metadata/routing.rs index 0a55b137f1..c51cd69baf 100644 --- a/rust/agents/relayer/src/msg/metadata/routing.rs +++ b/rust/agents/relayer/src/msg/metadata/routing.rs @@ -5,11 +5,11 @@ use eyre::Context; use hyperlane_core::{HyperlaneMessage, H256}; use tracing::instrument; -use super::{BaseMetadataBuilder, MetadataBuilder}; +use super::{MessageMetadataBuilder, MetadataBuilder}; #[derive(Clone, Debug, new, Deref)] pub struct RoutingIsmMetadataBuilder { - base: BaseMetadataBuilder, + base: MessageMetadataBuilder, } #[async_trait] diff --git a/rust/agents/relayer/src/msg/pending_message.rs b/rust/agents/relayer/src/msg/pending_message.rs index 9836a47d78..dfd4d12ccf 100644 --- a/rust/agents/relayer/src/msg/pending_message.rs +++ b/rust/agents/relayer/src/msg/pending_message.rs @@ -14,7 +14,7 @@ use tracing::{debug, error, info, instrument, trace, warn}; use super::{ gas_payment::GasPaymentEnforcer, - metadata::{BaseMetadataBuilder, MetadataBuilder}, + metadata::{BaseMetadataBuilder, MessageMetadataBuilder, MetadataBuilder}, pending_operation::*, }; @@ -35,7 +35,7 @@ pub struct MessageContext { pub origin_db: HyperlaneRocksDB, /// Used to construct the ISM metadata needed to verify a message from the /// origin. - pub metadata_builder: BaseMetadataBuilder, + pub metadata_builder: Arc, /// Used to determine if messages from the origin have made sufficient gas /// payments. pub origin_gas_payment_enforcer: Arc, @@ -153,9 +153,18 @@ impl PendingOperation for PendingMessage { "fetching ISM address. Potentially malformed recipient ISM address." ); + let message_metadata_builder = op_try!( + MessageMetadataBuilder::new( + ism_address, + &self.message, + self.ctx.metadata_builder.clone() + ) + .await, + "getting the message metadata builder" + ); + let Some(metadata) = op_try!( - self.ctx - .metadata_builder + message_metadata_builder .build(ism_address, &self.message) .await, "building metadata" diff --git a/rust/agents/relayer/src/msg/processor.rs b/rust/agents/relayer/src/msg/processor.rs index 14584d0c42..d06bc6b192 100644 --- a/rust/agents/relayer/src/msg/processor.rs +++ b/rust/agents/relayer/src/msg/processor.rs @@ -183,7 +183,8 @@ mod test { use crate::{ merkle_tree::builder::MerkleTreeBuilder, msg::{ - gas_payment::GasPaymentEnforcer, metadata::BaseMetadataBuilder, + gas_payment::GasPaymentEnforcer, + metadata::{AppContextClassifier, BaseMetadataBuilder}, pending_operation::PendingOperation, }, processor::Processor, @@ -240,16 +241,23 @@ mod test { } fn dummy_metadata_builder( - domain: &HyperlaneDomain, + origin_domain: &HyperlaneDomain, + destination_domain: &HyperlaneDomain, db: &HyperlaneRocksDB, ) -> BaseMetadataBuilder { let mut settings = Settings::default(); - settings - .chains - .insert(domain.name().to_owned(), dummy_chain_conf(domain)); - let destination_chain_conf = settings.chain_setup(domain).unwrap(); + settings.chains.insert( + origin_domain.name().to_owned(), + dummy_chain_conf(origin_domain), + ); + settings.chains.insert( + destination_domain.name().to_owned(), + dummy_chain_conf(destination_domain), + ); + let destination_chain_conf = settings.chain_setup(destination_domain).unwrap(); let core_metrics = CoreMetrics::new("dummy_relayer", 37582, Registry::new()).unwrap(); BaseMetadataBuilder::new( + origin_domain.clone(), destination_chain_conf.clone(), Arc::new(RwLock::new(MerkleTreeBuilder::new())), Arc::new(MockValidatorAnnounceContract::default()), @@ -257,6 +265,7 @@ mod test { Arc::new(core_metrics), db.clone(), 5, + AppContextClassifier::new(Arc::new(MockMailboxContract::default()), vec![]), ) } @@ -268,11 +277,11 @@ mod test { MessageProcessor, UnboundedReceiver>, ) { - let base_metadata_builder = dummy_metadata_builder(origin_domain, db); + let base_metadata_builder = dummy_metadata_builder(origin_domain, destination_domain, db); let message_context = Arc::new(MessageContext { destination_mailbox: Arc::new(MockMailboxContract::default()), origin_db: db.clone(), - metadata_builder: base_metadata_builder, + metadata_builder: Arc::new(base_metadata_builder), origin_gas_payment_enforcer: Arc::new(GasPaymentEnforcer::new([], db.clone())), transaction_gas_limit: Default::default(), metrics: dummy_submission_metrics(), diff --git a/rust/agents/relayer/src/relayer.rs b/rust/agents/relayer/src/relayer.rs index ba4ac30cdb..c26c0b57a4 100644 --- a/rust/agents/relayer/src/relayer.rs +++ b/rust/agents/relayer/src/relayer.rs @@ -34,7 +34,7 @@ use crate::{ merkle_tree::builder::MerkleTreeBuilder, msg::{ gas_payment::GasPaymentEnforcer, - metadata::BaseMetadataBuilder, + metadata::{AppContextClassifier, BaseMetadataBuilder}, pending_message::{MessageContext, MessageSubmissionMetrics}, pending_operation::DynPendingOperation, processor::{MessageProcessor, MessageProcessorMetrics}, @@ -212,6 +212,7 @@ impl BaseAgent for Relayer { for origin in &settings.origin_chains { let db = dbs.get(origin).unwrap().clone(); let metadata_builder = BaseMetadataBuilder::new( + origin.clone(), destination_chain_setup.clone(), prover_syncs[origin].clone(), validator_announces[origin].clone(), @@ -219,6 +220,10 @@ impl BaseAgent for Relayer { core.metrics.clone(), db, 5, + AppContextClassifier::new( + mailboxes[destination].clone(), + settings.metric_app_contexts.clone(), + ), ); msg_ctxs.insert( @@ -229,7 +234,7 @@ impl BaseAgent for Relayer { Arc::new(MessageContext { destination_mailbox: mailboxes[destination].clone(), origin_db: dbs.get(origin).unwrap().clone(), - metadata_builder, + metadata_builder: Arc::new(metadata_builder), origin_gas_payment_enforcer: gas_payment_enforcers[origin].clone(), transaction_gas_limit, metrics: MessageSubmissionMetrics::new(&core_metrics, origin, destination), diff --git a/rust/agents/relayer/src/settings/mod.rs b/rust/agents/relayer/src/settings/mod.rs index a595f0899b..c6934a77c7 100644 --- a/rust/agents/relayer/src/settings/mod.rs +++ b/rust/agents/relayer/src/settings/mod.rs @@ -54,6 +54,8 @@ pub struct RelayerSettings { /// If true, allows local storage based checkpoint syncers. /// Not intended for production use. pub allow_local_checkpoint_syncers: bool, + /// App contexts used for metrics. + pub metric_app_contexts: Vec<(MatchingList, String)>, } /// Config for gas payment enforcement @@ -118,26 +120,11 @@ impl FromRawConf for RelayerSettings { .parse_from_str("Expected database path") .unwrap_or_else(|| std::env::current_dir().unwrap().join("hyperlane_db")); - let (raw_gas_payment_enforcement_path, raw_gas_payment_enforcement) = match p + let (raw_gas_payment_enforcement_path, raw_gas_payment_enforcement) = p .get_opt_key("gasPaymentEnforcement") .take_config_err_flat(&mut err) - { - None => None, - Some(ValueParser { - val: Value::String(policy_str), - cwp, - }) => serde_json::from_str::(policy_str) - .context("Expected JSON string") - .take_err(&mut err, || cwp.clone()) - .map(|v| (cwp, recase_json_value(v, Case::Flat))), - Some(ValueParser { - val: value @ Value::Array(_), - cwp, - }) => Some((cwp, value.clone())), - Some(_) => Err(eyre!("Expected JSON array or stringified JSON")) - .take_err(&mut err, || cwp.clone()), - } - .unwrap_or_else(|| (&p.cwp + "gas_payment_enforcement", Value::Array(vec![]))); + .and_then(parse_json_array) + .unwrap_or_else(|| (&p.cwp + "gas_payment_enforcement", Value::Array(vec![]))); let gas_payment_enforcement_parser = ValueParser::new( raw_gas_payment_enforcement_path, @@ -247,6 +234,32 @@ impl FromRawConf for RelayerSettings { }) .collect(); + let (raw_metric_app_contexts_path, raw_metric_app_contexts) = p + .get_opt_key("metricAppContexts") + .take_config_err_flat(&mut err) + .and_then(parse_json_array) + .unwrap_or_else(|| (&p.cwp + "metric_app_contexts", Value::Array(vec![]))); + + let metric_app_contexts_parser = + ValueParser::new(raw_metric_app_contexts_path, &raw_metric_app_contexts); + let metric_app_contexts = metric_app_contexts_parser + .into_array_iter() + .map(|itr| { + itr.filter_map(|policy| { + let name = policy.chain(&mut err).get_key("name").parse_string().end(); + + let matching_list = policy + .chain(&mut err) + .get_key("matchingList") + .and_then(parse_matching_list) + .unwrap_or_default(); + + name.map(|name| (matching_list, name.to_owned())) + }) + .collect_vec() + }) + .unwrap_or_default(); + err.into_result(RelayerSettings { base, db, @@ -258,28 +271,35 @@ impl FromRawConf for RelayerSettings { transaction_gas_limit, skip_transaction_gas_limit_for, allow_local_checkpoint_syncers, + metric_app_contexts, }) } } -fn parse_matching_list(p: ValueParser) -> ConfigResult { +fn parse_json_array(p: ValueParser) -> Option<(ConfigPath, Value)> { let mut err = ConfigParsingError::default(); - let raw_list = match &p { + match p { ValueParser { - val: Value::String(matching_list_str), + val: Value::String(array_str), cwp, - } => serde_json::from_str::(matching_list_str) + } => serde_json::from_str::(array_str) .context("Expected JSON string") .take_err(&mut err, || cwp.clone()) - .map(|v| recase_json_value(v, Case::Flat)), + .map(|v| (cwp, recase_json_value(v, Case::Flat))), ValueParser { val: value @ Value::Array(_), - .. - } => Some((*value).clone()), + cwp, + } => Some((cwp, value.clone())), _ => Err(eyre!("Expected JSON array or stringified JSON")) .take_err(&mut err, || p.cwp.clone()), - }; + } +} + +fn parse_matching_list(p: ValueParser) -> ConfigResult { + let mut err = ConfigParsingError::default(); + + let raw_list = parse_json_array(p.clone()).map(|(_, v)| v); let Some(raw_list) = raw_list else { return err.into_result(MatchingList::default()); }; diff --git a/rust/chains/hyperlane-cosmos/src/mailbox.rs b/rust/chains/hyperlane-cosmos/src/mailbox.rs index 0b3927cda1..bb94bc7feb 100644 --- a/rust/chains/hyperlane-cosmos/src/mailbox.rs +++ b/rust/chains/hyperlane-cosmos/src/mailbox.rs @@ -144,9 +144,9 @@ impl Mailbox for CosmosMailbox { .await?; let response: mailbox::DefaultIsmResponse = serde_json::from_slice(&data)?; - // convert Hex to H256 - let ism = H256::from_slice(&hex::decode(response.default_ism)?); - Ok(ism) + // convert bech32 to H256 + let ism = CosmosAddress::from_str(&response.default_ism)?; + Ok(ism.digest()) } #[instrument(err, ret, skip(self))] @@ -166,7 +166,7 @@ impl Mailbox for CosmosMailbox { .await?; let response: mailbox::RecipientIsmResponse = serde_json::from_slice(&data)?; - // convert Hex to H256 + // convert bech32 to H256 let ism = CosmosAddress::from_str(&response.ism)?; Ok(ism.digest()) } diff --git a/rust/chains/hyperlane-ethereum/src/interchain_gas.rs b/rust/chains/hyperlane-ethereum/src/interchain_gas.rs index 24b7ae502a..b4a93fd541 100644 --- a/rust/chains/hyperlane-ethereum/src/interchain_gas.rs +++ b/rust/chains/hyperlane-ethereum/src/interchain_gas.rs @@ -84,6 +84,7 @@ impl Indexer for EthereumInterchainGasPaymasterIndexer< where M: Middleware + 'static, { + /// Note: This call may return duplicates depending on the provider used #[instrument(err, skip(self))] async fn fetch_logs( &self, diff --git a/rust/chains/hyperlane-ethereum/src/mailbox.rs b/rust/chains/hyperlane-ethereum/src/mailbox.rs index 4c566abbdf..02c5bb51da 100644 --- a/rust/chains/hyperlane-ethereum/src/mailbox.rs +++ b/rust/chains/hyperlane-ethereum/src/mailbox.rs @@ -125,6 +125,7 @@ where self.get_finalized_block_number().await } + /// Note: This call may return duplicates depending on the provider used #[instrument(err, skip(self))] async fn fetch_logs( &self, @@ -168,6 +169,7 @@ where self.get_finalized_block_number().await } + /// Note: This call may return duplicates depending on the provider used #[instrument(err, skip(self))] async fn fetch_logs(&self, range: RangeInclusive) -> ChainResult> { Ok(self diff --git a/rust/chains/hyperlane-ethereum/src/merkle_tree_hook.rs b/rust/chains/hyperlane-ethereum/src/merkle_tree_hook.rs index 1beffed5bc..90b0f73314 100644 --- a/rust/chains/hyperlane-ethereum/src/merkle_tree_hook.rs +++ b/rust/chains/hyperlane-ethereum/src/merkle_tree_hook.rs @@ -105,6 +105,7 @@ impl Indexer for EthereumMerkleTreeHookIndexer where M: Middleware + 'static, { + /// Note: This call may return duplicates depending on the provider used #[instrument(err, skip(self))] async fn fetch_logs( &self, diff --git a/rust/config/mainnet3_config.json b/rust/config/mainnet3_config.json index 57fb00101a..52a28760a2 100644 --- a/rust/config/mainnet3_config.json +++ b/rust/config/mainnet3_config.json @@ -433,7 +433,7 @@ "canonicalAsset": "untrn", "prefix": "neutron", "gasPrice": { - "amount": "0.5", + "amount": "0.57", "denom": "untrn" }, "index": { @@ -701,7 +701,8 @@ "mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7", "validatorAnnounce": "0xd83A4F747fE80Ed98839e05079B1B7Fe037b1638", "index": { - "from": 271840 + "from": 426670, + "chunk": 999 } }, "viction": { @@ -740,7 +741,8 @@ "interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4", "protocolFee": "0xd83A4F747fE80Ed98839e05079B1B7Fe037b1638", "index": { - "from": 73573878 + "from": 73573878, + "chunk": 1000 } } }, diff --git a/rust/config/testnet4_config.json b/rust/config/testnet4_config.json index d0fbd12598..498f63906c 100644 --- a/rust/config/testnet4_config.json +++ b/rust/config/testnet4_config.json @@ -101,37 +101,85 @@ "from": 20566929 } }, - "arbitrumgoerli": { - "chainId": 421613, - "domainId": 421613, - "name": "arbitrumgoerli", - "protocol": "ethereum", - "displayName": "Arbitrum Goerli", - "displayNameShort": "Arb. Goerli", + "ancient8testnet": { + "blockExplorers": [ + { + "apiUrl": "https://testnet.a8scan.io/api", + "family": "blockscout", + "name": "a8scan", + "url": "https://testnet.a8scan.io" + } + ], + "chainId": 2863311531, + "blocks": { + "confirmations": 1, + "estimateBlockTime": 2, + "reorgPeriod": 0 + }, + "displayName": "Ancient 8 Testnet", + "domainId": 2863311531, + "isTestnet": true, + "name": "ancient8testnet", "nativeToken": { + "decimals": 18, "name": "Ether", - "symbol": "ETH", - "decimals": 18 + "symbol": "ETH" }, + "protocol": "ethereum", "rpcUrls": [ { - "http": "https://goerli-rollup.arbitrum.io/rpc" + "http": "https://rpc-testnet.ancient8.gg" } ], + "merkleRootMultisigIsmFactory": "0x6E7b29CB2A7617405B4d30C6f84bBD51b4Bb4be8", + "messageIdMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "aggregationIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "aggregationHookFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "routingIsmFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "proxyAdmin": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "validatorAnnounce": "0xD0680F80F4f947968206806C2598Cbc5b6FE5b03", + "interchainSecurityModule": "0x4ac19e0bafc2aF6B98094F0a1B817dF196551219", + "merkleTreeHook": "0x3707bc8C7342aA6f693bCe1Bd7671Fca146F7F0A", + "fallbackRoutingHook": "0x863E8c26621c52ACa1849C53500606e73BA272F0", + "storageGasOracle": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "interchainGasPaymaster": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "protocolFee": "0x267B6B6eAf6790faE5D5E9070F28a9cE64CbF279", + "index": { + "from": 6511770 + } + }, + "arbitrumgoerli": { "blockExplorers": [ { - "name": "Arbiscan", - "url": "https://goerli.arbiscan.io", "apiUrl": "https://api-goerli.arbiscan.io/api", - "family": "etherscan" + "family": "etherscan", + "name": "Arbiscan", + "url": "https://goerli.arbiscan.io" } ], "blocks": { "confirmations": 1, - "reorgPeriod": 1, - "estimateBlockTime": 3 + "estimateBlockTime": 3, + "reorgPeriod": 1 }, + "chainId": 421613, + "displayName": "Arbitrum Goerli", + "displayNameShort": "Arb. Goerli", + "domainId": 421613, "isTestnet": true, + "name": "arbitrumgoerli", + "nativeToken": { + "decimals": 18, + "name": "Ether", + "symbol": "ETH" + }, + "protocol": "ethereum", + "rpcUrls": [ + { + "http": "https://goerli-rollup.arbitrum.io/rpc" + } + ], "merkleRootMultisigIsmFactory": "0x17D58eBb5Ea0E2d360c877E119FAef4C4052e6B9", "messageIdMultisigIsmFactory": "0x922CeEe9e8832a047e6aD68Df4F079F271b73Ac3", "aggregationIsmFactory": "0xC5Bb8CDD44B6c56695df45c7AA8012a97dD6ED13", @@ -140,13 +188,12 @@ "proxyAdmin": "0x00DFB81Bfc45fa03060b605273147F274ea807E5", "mailbox": "0x13dABc0351407d5aAa0A50003a166A73b4febfDc", "validatorAnnounce": "0x4a01EEBa1CC20F47A2e60aE4ec932051601FcB9e", - "defaultIsm": "0x8C841784947dEa42f78263D54bec15c0cF65fA22", "merkleTreeHook": "0xf0A38e1eEA49dAc7968F470c3aA0BDE2565A5d80", "storageGasOracle": "0xFc8229ADB46D96056A6e451Fb3c55d60FFeD056f", "interchainGasPaymaster": "0x76189acFA212298d7022624a4633411eE0d2f26F", "aggregationHook": "0xf852EB6b98d84A4296754043a56759a0Ae0E06df", "protocolFee": "0x0358ba0D90ED2d90fB8cBb610F27C274D8077a0B", - "fallbackRoutingHook": "0x3Ce607F6FcE5Dfb9821f33504d86E04A4CD0C75f", + "fallbackRoutingHook": "0xEdA6f85f4761A1f9e42FD40CA5a4E8Ce1C764015", "index": { "from": 50669378 } diff --git a/rust/hyperlane-base/src/contract_sync/mod.rs b/rust/hyperlane-base/src/contract_sync/mod.rs index 3968ad9f57..219f06c905 100644 --- a/rust/hyperlane-base/src/contract_sync/mod.rs +++ b/rust/hyperlane-base/src/contract_sync/mod.rs @@ -1,4 +1,4 @@ -use std::{fmt::Debug, marker::PhantomData, sync::Arc}; +use std::{collections::HashSet, fmt::Debug, hash::Hash, marker::PhantomData, sync::Arc}; use cursor::*; use derive_new::new; @@ -31,7 +31,7 @@ pub struct ContractSync, I: Indexer> { impl ContractSync where - T: Debug + Send + Sync + Clone + 'static, + T: Debug + Send + Sync + Clone + Eq + Hash + 'static, D: HyperlaneLogStore + 'static, I: Indexer + Clone + 'static, { @@ -67,6 +67,8 @@ where debug!(?range, "Looking for for events in index range"); let logs = self.indexer.fetch_logs(range.clone()).await?; + let deduped_logs = HashSet::<_>::from_iter(logs); + let logs = Vec::from_iter(deduped_logs); info!( ?range, diff --git a/rust/hyperlane-base/src/metrics/core.rs b/rust/hyperlane-base/src/metrics/core.rs index a0c40d8a8e..738538dae0 100644 --- a/rust/hyperlane-base/src/metrics/core.rs +++ b/rust/hyperlane-base/src/metrics/core.rs @@ -1,14 +1,16 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::fmt::{Debug, Formatter}; use std::sync::{Arc, OnceLock}; use eyre::Result; +use hyperlane_core::{HyperlaneDomain, H160}; use prometheus::{ histogram_opts, labels, opts, register_counter_vec_with_registry, register_gauge_vec_with_registry, register_histogram_vec_with_registry, register_int_counter_vec_with_registry, register_int_gauge_vec_with_registry, CounterVec, Encoder, GaugeVec, HistogramVec, IntCounterVec, IntGaugeVec, Registry, }; +use tokio::sync::RwLock; use tokio::task::JoinHandle; use tracing::warn; @@ -37,7 +39,6 @@ pub struct CoreMetrics { span_counts: IntCounterVec, span_events: IntCounterVec, last_known_message_nonce: IntGaugeVec, - validator_checkpoint_index: IntGaugeVec, submitter_queue_length: IntGaugeVec, operations_processed_count: IntCounterVec, @@ -51,6 +52,9 @@ pub struct CoreMetrics { /// Set of provider-specific metrics. These only need to get created once. provider_metrics: OnceLock, + + /// Metrics that are used to observe validator sets. + pub validator_metrics: ValidatorObservabilityMetricManager, } impl CoreMetrics { @@ -109,13 +113,18 @@ impl CoreMetrics { registry )?; - let validator_checkpoint_index = register_int_gauge_vec_with_registry!( + let observed_validator_latest_index = register_int_gauge_vec_with_registry!( opts!( - namespaced!("validator_checkpoint_index"), - "Observed signed checkpoint indices per validator", + namespaced!("observed_validator_latest_index"), + "The latest observed latest signed checkpoint indices per validator, from the perspective of the relayer", const_labels_ref ), - &["origin", "validator"], + &[ + "origin", + "destination", + "validator", + "app_context", + ], registry )?; @@ -169,7 +178,6 @@ impl CoreMetrics { span_counts, span_events, last_known_message_nonce, - validator_checkpoint_index, submitter_queue_length, @@ -180,6 +188,10 @@ impl CoreMetrics { json_rpc_client_metrics: OnceLock::new(), provider_metrics: OnceLock::new(), + + validator_metrics: ValidatorObservabilityMetricManager::new( + observed_validator_latest_index.clone(), + ), }) } @@ -298,14 +310,6 @@ impl CoreMetrics { self.last_known_message_nonce.clone() } - /// Gauge for reporting the most recent validator checkpoint index - /// Labels: - /// - `origin`: Origin chain - /// - `validator`: Address of the validator - pub fn validator_checkpoint_index(&self) -> IntGaugeVec { - self.validator_checkpoint_index.clone() - } - /// Latest message nonce in the validator. /// /// Phase: @@ -468,3 +472,97 @@ impl Debug for CoreMetrics { ) } } + +#[derive(Debug, Eq, PartialEq, Hash)] +struct AppContextKey { + origin: HyperlaneDomain, + destination: HyperlaneDomain, + app_context: String, +} + +/// Manages metrics for observing sets of validators. +pub struct ValidatorObservabilityMetricManager { + observed_validator_latest_index: IntGaugeVec, + + app_context_validators: RwLock>>, +} + +impl ValidatorObservabilityMetricManager { + fn new(observed_validator_latest_index: IntGaugeVec) -> Self { + Self { + observed_validator_latest_index, + app_context_validators: RwLock::new(HashMap::new()), + } + } + + /// Updates the metrics with the latest checkpoint index for each validator + /// in a given set. + pub async fn set_validator_latest_checkpoints( + &self, + origin: &HyperlaneDomain, + destination: &HyperlaneDomain, + app_context: String, + latest_checkpoints: &HashMap>, + ) { + let key = AppContextKey { + origin: origin.clone(), + destination: destination.clone(), + app_context: app_context.clone(), + }; + + let mut app_context_validators = self.app_context_validators.write().await; + + // First, clear out all previous metrics for the app context. + // This is necessary because the set of validators may have changed. + if let Some(prev_validators) = app_context_validators.get(&key) { + for validator in prev_validators { + // We unwrap because an error here occurs if the # of labels + // provided is incorrect, and we'd like to loudly fail in e2e if that + // happens. + self.observed_validator_latest_index + .remove_label_values(&[ + origin.as_ref(), + destination.as_ref(), + &format!("0x{:x}", validator).to_lowercase(), + &app_context, + ]) + .unwrap(); + } + } + + let mut set = HashSet::new(); + + // Then set the new metrics and update the cached set of validators. + for (validator, latest_checkpoint) in latest_checkpoints { + self.observed_validator_latest_index + .with_label_values(&[ + origin.as_ref(), + destination.as_ref(), + &format!("0x{:x}", validator).to_lowercase(), + &app_context, + ]) + // If the latest checkpoint is None, set to -1 to indicate that + // the validator did not provide a valid latest checkpoint index. + .set(latest_checkpoint.map(|i| i as i64).unwrap_or(-1)); + set.insert(*validator); + } + app_context_validators.insert(key, set); + } + + /// Gauge for reporting recently observed latest checkpoint indices for validator sets. + /// The entire set for an app context should be updated at once, and it should be updated + /// in a way that is robust to validator set changes. + /// Set to -1 to indicate a validator did not provide a valid latest checkpoint index. + /// Note that it's possible for an app to be using an aggregation ISM of more than one + /// validator set. If these sets are different, there is no label built into the metric + /// to distinguish them. + /// + /// Labels: + /// - `origin`: Origin chain + /// - `destination`: Destination chain + /// - `validator`: Address of the validator + /// - `app_context`: App context for the validator set + pub fn observed_validator_latest_index(&self) -> IntGaugeVec { + self.observed_validator_latest_index.clone() + } +} diff --git a/rust/hyperlane-base/src/settings/checkpoint_syncer.rs b/rust/hyperlane-base/src/settings/checkpoint_syncer.rs index 342f44732c..01640747eb 100644 --- a/rust/hyperlane-base/src/settings/checkpoint_syncer.rs +++ b/rust/hyperlane-base/src/settings/checkpoint_syncer.rs @@ -1,12 +1,11 @@ use core::str::FromStr; -use std::{collections::HashMap, path::PathBuf}; +use std::path::PathBuf; use eyre::{eyre, Context, Report, Result}; -use hyperlane_core::H160; -use prometheus::{IntGauge, IntGaugeVec}; +use prometheus::IntGauge; use rusoto_core::Region; -use crate::{CheckpointSyncer, LocalStorage, MultisigCheckpointSyncer, S3Storage}; +use crate::{CheckpointSyncer, LocalStorage, S3Storage}; /// Checkpoint Syncer types #[derive(Debug, Clone)] @@ -83,31 +82,3 @@ impl CheckpointSyncerConf { }) } } - -/// Config for a MultisigCheckpointSyncer -#[derive(Debug, Clone)] -pub struct MultisigCheckpointSyncerConf { - /// The checkpoint syncer for each valid validator signer address - checkpointsyncers: HashMap, -} - -impl MultisigCheckpointSyncerConf { - /// Get a MultisigCheckpointSyncer from the config - pub fn build( - &self, - origin: &str, - validator_checkpoint_index: IntGaugeVec, - ) -> Result { - let mut checkpoint_syncers = HashMap::new(); - for (key, value) in self.checkpointsyncers.iter() { - let gauge = - validator_checkpoint_index.with_label_values(&[origin, &key.to_lowercase()]); - if let Ok(conf) = value.build(Some(gauge)) { - checkpoint_syncers.insert(H160::from_str(key)?, conf.into()); - } else { - continue; - } - } - Ok(MultisigCheckpointSyncer::new(checkpoint_syncers)) - } -} diff --git a/rust/hyperlane-base/src/types/multisig.rs b/rust/hyperlane-base/src/types/multisig.rs index 4fd60f7985..dc7878af39 100644 --- a/rust/hyperlane-base/src/types/multisig.rs +++ b/rust/hyperlane-base/src/types/multisig.rs @@ -5,19 +5,76 @@ use derive_new::new; use eyre::Result; use tracing::{debug, instrument}; -use hyperlane_core::{MultisigSignedCheckpoint, SignedCheckpointWithMessageId, H160, H256}; +use hyperlane_core::{ + HyperlaneDomain, MultisigSignedCheckpoint, SignedCheckpointWithMessageId, H160, H256, +}; -use crate::CheckpointSyncer; +use crate::{CheckpointSyncer, CoreMetrics}; -/// Fetches signed checkpoints from multiple validators to create -/// MultisigSignedCheckpoints +/// For a particular validator set, fetches signed checkpoints from multiple +/// validators to create MultisigSignedCheckpoints. #[derive(Clone, Debug, new)] pub struct MultisigCheckpointSyncer { /// The checkpoint syncer for each valid validator signer address checkpoint_syncers: HashMap>, + metrics: Arc, + app_context: Option, } impl MultisigCheckpointSyncer { + /// Gets the latest checkpoint index from each validator's checkpoint syncer. + /// Returns a vector of the latest indices, in an unspecified order, and does + /// not contain indices for validators that did not provide a latest index. + /// Also updates the validator latest checkpoint metrics. + pub async fn get_validator_latest_checkpoints_and_update_metrics( + &self, + validators: &[H256], + origin: &HyperlaneDomain, + destination: &HyperlaneDomain, + ) -> Vec { + // Get the latest_index from each validator's checkpoint syncer. + // If a validator does not return a latest index, None is recorded so + // this can be surfaced in the metrics. + let mut latest_indices: HashMap> = + HashMap::with_capacity(validators.len()); + + for validator in validators { + let address = H160::from(*validator); + if let Some(checkpoint_syncer) = self.checkpoint_syncers.get(&address) { + // Gracefully handle errors getting the latest_index + match checkpoint_syncer.latest_index().await { + Ok(Some(index)) => { + debug!(?address, ?index, "Validator returned latest index"); + latest_indices.insert(H160::from(*validator), Some(index)); + } + result => { + debug!( + ?address, + ?result, + "Failed to get latest index from validator" + ); + latest_indices.insert(H160::from(*validator), None); + } + } + } + } + + if let Some(app_context) = &self.app_context { + self.metrics + .validator_metrics + .set_validator_latest_checkpoints( + origin, + destination, + app_context.clone(), + &latest_indices, + ) + .await; + } + + // Filter out any validators that did not return a latest index + latest_indices.values().copied().flatten().collect() + } + /// Attempts to get the latest checkpoint with a quorum of signatures among /// validators. /// @@ -37,24 +94,13 @@ impl MultisigCheckpointSyncer { threshold: usize, minimum_index: u32, maximum_index: u32, + origin: &HyperlaneDomain, + destination: &HyperlaneDomain, ) -> Result> { - // Get the latest_index from each validator's checkpoint syncer. - let mut latest_indices = Vec::with_capacity(validators.len()); - for validator in validators { - let address = H160::from(*validator); - if let Some(checkpoint_syncer) = self.checkpoint_syncers.get(&address) { - // Gracefully handle errors getting the latest_index - match checkpoint_syncer.latest_index().await { - Ok(Some(index)) => { - debug!(?address, ?index, "Validator returned latest index"); - latest_indices.push(index); - } - err => { - debug!(?address, ?err, "Failed to get latest index from validator"); - } - } - } - } + let mut latest_indices = self + .get_validator_latest_checkpoints_and_update_metrics(validators, origin, destination) + .await; + debug!( ?latest_indices, "Fetched latest indices from checkpoint syncers" diff --git a/rust/hyperlane-core/src/types/log_metadata.rs b/rust/hyperlane-core/src/types/log_metadata.rs index bdb4b043fe..e85824dab9 100644 --- a/rust/hyperlane-core/src/types/log_metadata.rs +++ b/rust/hyperlane-core/src/types/log_metadata.rs @@ -10,7 +10,7 @@ use crate::{H256, H512, U256}; /// A close clone of the Ethereum `LogMeta`, this is designed to be a more /// generic metadata that we can use for other blockchains later. Some changes /// may be required in the future. -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default, Hash)] pub struct LogMeta { /// Address from which this log originated pub address: H256, diff --git a/rust/hyperlane-core/src/types/merkle_tree.rs b/rust/hyperlane-core/src/types/merkle_tree.rs index 96ea78ff1c..5d4e20a9fc 100644 --- a/rust/hyperlane-core/src/types/merkle_tree.rs +++ b/rust/hyperlane-core/src/types/merkle_tree.rs @@ -4,7 +4,7 @@ use std::io::{Read, Write}; use crate::{Decode, Encode, HyperlaneProtocolError, Sequenced, H256}; /// Merkle Tree Hook insertion event -#[derive(Debug, Copy, Clone, new, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, new, Eq, PartialEq, Hash)] pub struct MerkleTreeInsertion { leaf_index: u32, message_id: H256, diff --git a/rust/hyperlane-core/src/types/message.rs b/rust/hyperlane-core/src/types/message.rs index badabd815c..99fb2fef45 100644 --- a/rust/hyperlane-core/src/types/message.rs +++ b/rust/hyperlane-core/src/types/message.rs @@ -21,7 +21,7 @@ impl From<&HyperlaneMessage> for RawHyperlaneMessage { } /// A full Hyperlane message between chains -#[derive(Clone, Eq, PartialEq)] +#[derive(Clone, Eq, PartialEq, Hash)] pub struct HyperlaneMessage { /// 1 Hyperlane version number pub version: u8, diff --git a/rust/hyperlane-core/src/types/mod.rs b/rust/hyperlane-core/src/types/mod.rs index 58d466abce..9d56cb7f08 100644 --- a/rust/hyperlane-core/src/types/mod.rs +++ b/rust/hyperlane-core/src/types/mod.rs @@ -115,7 +115,7 @@ pub struct GasPaymentKey { } /// A payment of a message's gas costs. -#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)] pub struct InterchainGasPayment { /// Id of the message pub message_id: H256, diff --git a/solidity/CHANGELOG.md b/solidity/CHANGELOG.md index 0a63377559..d1a86ed4ad 100644 --- a/solidity/CHANGELOG.md +++ b/solidity/CHANGELOG.md @@ -1,5 +1,17 @@ # @hyperlane-xyz/core +## 3.5.1 + +### Patch Changes + +- @hyperlane-xyz/utils@3.5.1 + +## 3.5.0 + +### Patch Changes + +- @hyperlane-xyz/utils@3.5.0 + ## 3.4.0 ### Patch Changes diff --git a/solidity/package.json b/solidity/package.json index d19a718e8e..39522176c8 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -1,10 +1,10 @@ { "name": "@hyperlane-xyz/core", "description": "Core solidity contracts for Hyperlane", - "version": "3.4.0", + "version": "3.5.1", "dependencies": { "@eth-optimism/contracts": "^0.6.0", - "@hyperlane-xyz/utils": "3.4.0", + "@hyperlane-xyz/utils": "3.5.1", "@openzeppelin/contracts": "^4.9.3", "@openzeppelin/contracts-upgradeable": "^v4.9.3" }, diff --git a/typescript/cli/CHANGELOG.md b/typescript/cli/CHANGELOG.md index bf03bac185..3568080a7a 100644 --- a/typescript/cli/CHANGELOG.md +++ b/typescript/cli/CHANGELOG.md @@ -1,5 +1,24 @@ # @hyperlane-xyz/cli +## 3.5.1 + +### Patch Changes + +- Updated dependencies [a04454d6d] + - @hyperlane-xyz/sdk@3.5.1 + - @hyperlane-xyz/utils@3.5.1 + +## 3.5.0 + +### Patch Changes + +- 05a943b4a: Skip mandatory balance check for remotes in send commands" +- Updated dependencies [655b6a0cd] +- Updated dependencies [08ba0d32b] +- Updated dependencies [f7d285e3a] + - @hyperlane-xyz/sdk@3.5.0 + - @hyperlane-xyz/utils@3.5.0 + ## 3.4.0 ### Patch Changes diff --git a/typescript/cli/package.json b/typescript/cli/package.json index c0ac92c5da..f0aa308a66 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -1,10 +1,10 @@ { "name": "@hyperlane-xyz/cli", - "version": "3.4.0", + "version": "3.5.1", "description": "A command-line utility for common Hyperlane operations", "dependencies": { - "@hyperlane-xyz/sdk": "3.4.0", - "@hyperlane-xyz/utils": "3.4.0", + "@hyperlane-xyz/sdk": "3.5.1", + "@hyperlane-xyz/utils": "3.5.1", "@inquirer/prompts": "^3.0.0", "bignumber.js": "^9.1.1", "chalk": "^5.3.0", diff --git a/typescript/cli/src/version.ts b/typescript/cli/src/version.ts index a4138e791e..d17eb6093b 100644 --- a/typescript/cli/src/version.ts +++ b/typescript/cli/src/version.ts @@ -1 +1 @@ -export const VERSION = '3.4.0'; +export const VERSION = '3.5.1'; diff --git a/typescript/helloworld/CHANGELOG.md b/typescript/helloworld/CHANGELOG.md index 88e2235921..85ba12f2a7 100644 --- a/typescript/helloworld/CHANGELOG.md +++ b/typescript/helloworld/CHANGELOG.md @@ -1,5 +1,23 @@ # @hyperlane-xyz/helloworld +## 3.5.1 + +### Patch Changes + +- Updated dependencies [a04454d6d] + - @hyperlane-xyz/sdk@3.5.1 + - @hyperlane-xyz/core@3.5.1 + +## 3.5.0 + +### Patch Changes + +- Updated dependencies [655b6a0cd] +- Updated dependencies [08ba0d32b] +- Updated dependencies [f7d285e3a] + - @hyperlane-xyz/sdk@3.5.0 + - @hyperlane-xyz/core@3.5.0 + ## 3.4.0 ### Patch Changes diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index 585d96b614..986e8f1f40 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -1,10 +1,10 @@ { "name": "@hyperlane-xyz/helloworld", "description": "A basic skeleton of an Hyperlane app", - "version": "3.4.0", + "version": "3.5.1", "dependencies": { - "@hyperlane-xyz/core": "3.4.0", - "@hyperlane-xyz/sdk": "3.4.0", + "@hyperlane-xyz/core": "3.5.1", + "@hyperlane-xyz/sdk": "3.5.1", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" }, diff --git a/typescript/infra/CHANGELOG.md b/typescript/infra/CHANGELOG.md index 81abc73326..ca065714cb 100644 --- a/typescript/infra/CHANGELOG.md +++ b/typescript/infra/CHANGELOG.md @@ -1,5 +1,30 @@ # @hyperlane-xyz/infra +## 3.5.1 + +### Patch Changes + +- Updated dependencies [a04454d6d] + - @hyperlane-xyz/sdk@3.5.1 + - @hyperlane-xyz/helloworld@3.5.1 + - @hyperlane-xyz/utils@3.5.1 + +## 3.5.0 + +### Minor Changes + +- 655b6a0cd: Redeploy Routing ISM Factories + +### Patch Changes + +- f7d285e3a: Adds Test Recipient addresses to the SDK artifacts +- Updated dependencies [655b6a0cd] +- Updated dependencies [08ba0d32b] +- Updated dependencies [f7d285e3a] + - @hyperlane-xyz/sdk@3.5.0 + - @hyperlane-xyz/helloworld@3.5.0 + - @hyperlane-xyz/utils@3.5.0 + ## 3.4.0 ### Patch Changes diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index d5efa431f2..8aa5fda7e5 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -43,14 +43,14 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '86b7f98-20231207-153805', + tag: '34611f0-20231218-204504', }, gasPaymentEnforcement, }, validators: { docker: { repo, - tag: '86b7f98-20231207-153805', + tag: '34611f0-20231218-204504', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.Hyperlane), @@ -59,7 +59,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '86b7f98-20231207-153805', + tag: '34611f0-20231218-204504', }, }, }; @@ -72,7 +72,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '86b7f98-20231207-153805', + tag: '34611f0-20231218-204504', }, // whitelist: releaseCandidateHelloworldMatchingList, gasPaymentEnforcement, @@ -84,7 +84,7 @@ const releaseCandidate: RootAgentConfig = { validators: { docker: { repo, - tag: '86b7f98-20231207-153805', + tag: '34611f0-20231218-204504', }, rpcConsensusType: RpcConsensusType.Quorum, chains: validatorChainConfig(Contexts.ReleaseCandidate), @@ -108,7 +108,7 @@ const neutron: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '86b7f98-20231207-153805', + tag: '67585a2-20231220-223937', }, gasPaymentEnforcement: [ { diff --git a/typescript/infra/config/environments/testnet4/agent.ts b/typescript/infra/config/environments/testnet4/agent.ts index 4621e0a1e1..defddf046e 100644 --- a/typescript/infra/config/environments/testnet4/agent.ts +++ b/typescript/infra/config/environments/testnet4/agent.ts @@ -1,5 +1,4 @@ import { - Chains, GasPaymentEnforcementPolicyType, RpcConsensusType, chainMetadata, @@ -50,7 +49,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '86b7f98-20231207-153805', + tag: '34611f0-20231218-204504', }, blacklist: [ ...releaseCandidateHelloworldMatchingList, @@ -67,7 +66,7 @@ const hyperlane: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '86b7f98-20231207-153805', + tag: '34611f0-20231218-204504', }, chains: validatorChainConfig(Contexts.Hyperlane), }, @@ -88,7 +87,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '86b7f98-20231207-153805', + tag: '34611f0-20231218-204504', }, whitelist: [...releaseCandidateHelloworldMatchingList], gasPaymentEnforcement, @@ -101,7 +100,7 @@ const releaseCandidate: RootAgentConfig = { rpcConsensusType: RpcConsensusType.Fallback, docker: { repo, - tag: '86b7f98-20231207-153805', + tag: '34611f0-20231218-204504', }, chains: validatorChainConfig(Contexts.ReleaseCandidate), }, diff --git a/typescript/infra/config/environments/testnet4/chains.ts b/typescript/infra/config/environments/testnet4/chains.ts index 3f87914ede..292aa6c8cb 100644 --- a/typescript/infra/config/environments/testnet4/chains.ts +++ b/typescript/infra/config/environments/testnet4/chains.ts @@ -1,12 +1,31 @@ -import { ChainMap, ChainMetadata, chainMetadata } from '@hyperlane-xyz/sdk'; +import { + ChainMap, + ChainMetadata, + Chains, + chainMetadata, +} from '@hyperlane-xyz/sdk'; import { AgentChainNames, Role } from '../../../src/roles'; -// Blessed -export const ethereumTestnetConfigs: ChainMap = { - alfajores: chainMetadata.alfajores, - basegoerli: chainMetadata.basegoerli, - fuji: chainMetadata.fuji, +const selectedChains = [ + Chains.alfajores, + Chains.ancient8testnet, + Chains.arbitrumgoerli, + Chains.basegoerli, + Chains.bsctestnet, + Chains.fuji, + Chains.goerli, + Chains.moonbasealpha, + Chains.optimismgoerli, + Chains.polygonzkevmtestnet, + Chains.scrollsepolia, + Chains.sepolia, +]; + +export const testnetConfigs: ChainMap = { + ...Object.fromEntries( + selectedChains.map((chain) => [chain, chainMetadata[chain]]), + ), mumbai: { ...chainMetadata.mumbai, transactionOverrides: { @@ -14,41 +33,14 @@ export const ethereumTestnetConfigs: ChainMap = { maxPriorityFeePerGas: 40 * 10 ** 9, // 40 gwei }, }, - bsctestnet: chainMetadata.bsctestnet, - goerli: chainMetadata.goerli, - scrollsepolia: chainMetadata.scrollsepolia, - sepolia: chainMetadata.sepolia, - moonbasealpha: chainMetadata.moonbasealpha, - optimismgoerli: chainMetadata.optimismgoerli, - arbitrumgoerli: chainMetadata.arbitrumgoerli, - polygonzkevmtestnet: chainMetadata.polygonzkevmtestnet, -}; - -// Blessed non-Ethereum chains. -export const nonEthereumTestnetConfigs: ChainMap = { - // solanadevnet: chainMetadata.solanadevnet, }; -export const testnetConfigs: ChainMap = { - ...ethereumTestnetConfigs, - ...nonEthereumTestnetConfigs, -}; - -export type TestnetChains = keyof typeof testnetConfigs; -export const supportedChainNames = Object.keys( - testnetConfigs, -) as TestnetChains[]; +export const supportedChainNames = Object.keys(testnetConfigs); export const environment = 'testnet4'; -export const ethereumChainNames = Object.keys( - ethereumTestnetConfigs, -) as TestnetChains[]; - // Hyperlane & RC context agent chain names. export const agentChainNames: AgentChainNames = { - // Run validators for all chains. [Role.Validator]: supportedChainNames, - // Only run relayers for Ethereum chains at the moment. - [Role.Relayer]: ethereumChainNames, - [Role.Scraper]: ethereumChainNames, + [Role.Relayer]: supportedChainNames, + [Role.Scraper]: supportedChainNames, }; diff --git a/typescript/infra/config/environments/testnet4/core/verification.json b/typescript/infra/config/environments/testnet4/core/verification.json index 31eb4ee72a..d7bfa081e2 100644 --- a/typescript/infra/config/environments/testnet4/core/verification.json +++ b/typescript/infra/config/environments/testnet4/core/verification.json @@ -4126,5 +4126,979 @@ "constructorArguments": "000000000000000000000000598face78a4302f11e3de0bee1894da0b2cb71f8000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000068311418d79fe8d96599384ed767d225635d88a8", "isProxy": false } + ], + "ancient8testnet": [ + { + "name": "ProxyAdmin", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000aaaaaaab", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "000000000000000000000000c2e36cd6e32e194ee11f15d9273b64461a4d49a200000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "MerkleTreeHook", + "address": "0x3707bc8C7342aA6f693bCe1Bd7671Fca146F7F0A", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x863E8c26621c52ACa1849C53500606e73BA272F0", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c0000000000000000000000003707bc8c7342aa6f693bce1bd7671fca146f7f0a", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "MerkleTreeHook", + "address": "0x3707bc8C7342aA6f693bCe1Bd7671Fca146F7F0A", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x863E8c26621c52ACa1849C53500606e73BA272F0", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c0000000000000000000000003707bc8c7342aa6f693bce1bd7671fca146f7f0a", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "ProtocolFee", + "address": "0x267B6B6eAf6790faE5D5E9070F28a9cE64CbF279", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xD0680F80F4f947968206806C2598Cbc5b6FE5b03", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "ProxyAdmin", + "address": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "Mailbox", + "address": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000aaaaaaab", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "constructorArguments": "000000000000000000000000c2e36cd6e32e194ee11f15d9273b64461a4d49a200000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "MerkleTreeHook", + "address": "0x3707bc8C7342aA6f693bCe1Bd7671Fca146F7F0A", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x863E8c26621c52ACa1849C53500606e73BA272F0", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c0000000000000000000000003707bc8c7342aa6f693bce1bd7671fca146f7f0a", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "MerkleTreeHook", + "address": "0x3707bc8C7342aA6f693bCe1Bd7671Fca146F7F0A", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "FallbackRoutingHook", + "address": "0x863E8c26621c52ACa1849C53500606e73BA272F0", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c0000000000000000000000003707bc8c7342aa6f693bce1bd7671fca146f7f0a", + "isProxy": false + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "StorageGasOracle", + "address": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "InterchainGasPaymaster", + "address": "0xAD34A66Bf6dB18E858F6B686557075568c6E031C", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "TransparentUpgradeableProxy", + "address": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "constructorArguments": "000000000000000000000000ad34a66bf6db18e858f6b686557075568c6e031c00000000000000000000000044b764045bfdc68517e10e783e69b376cef196b200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c00000000000000000000000000000000000000000000000000000000", + "isProxy": true + }, + { + "name": "ProtocolFee", + "address": "0x267B6B6eAf6790faE5D5E9070F28a9cE64CbF279", + "constructorArguments": "000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c000000000000000000000000fad1c94469700833717fa8a3017278bc1ca8031c", + "isProxy": false + }, + { + "name": "ValidatorAnnounce", + "address": "0xD0680F80F4f947968206806C2598Cbc5b6FE5b03", + "constructorArguments": "0000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + } ] } diff --git a/typescript/infra/config/environments/testnet4/gas-oracle.ts b/typescript/infra/config/environments/testnet4/gas-oracle.ts index b173f4d3a5..9dab5732b1 100644 --- a/typescript/infra/config/environments/testnet4/gas-oracle.ts +++ b/typescript/infra/config/environments/testnet4/gas-oracle.ts @@ -11,11 +11,12 @@ import { getTokenExchangeRateFromValues, } from '../../../src/config/gas-oracle'; -import { TestnetChains, supportedChainNames } from './chains'; +import { supportedChainNames } from './chains'; // Taken by looking at each testnet and overestimating gas prices const gasPrices: ChainMap = { alfajores: ethers.utils.parseUnits('10', 'gwei'), + ancient8testnet: ethers.utils.parseUnits('0.1', 'gwei'), fuji: ethers.utils.parseUnits('30', 'gwei'), mumbai: ethers.utils.parseUnits('45', 'gwei'), bsctestnet: ethers.utils.parseUnits('15', 'gwei'), @@ -50,6 +51,7 @@ const RARITY_APPROXIMATE_VALUE: Record = { const chainTokenRarity: ChainMap = { alfajores: Rarity.Common, + ancient8testnet: Rarity.Rare, fuji: Rarity.Rare, mumbai: Rarity.Rare, bsctestnet: Rarity.Rare, @@ -67,7 +69,7 @@ const chainTokenRarity: ChainMap = { }; // Gets the "value" of a testnet chain -function getApproximateValue(chain: TestnetChains): BigNumber { +function getApproximateValue(chain: ChainName): BigNumber { const rarity = chainTokenRarity[chain]; return RARITY_APPROXIMATE_VALUE[rarity]; } diff --git a/typescript/infra/config/environments/testnet4/igp.ts b/typescript/infra/config/environments/testnet4/igp.ts index c098d0af61..b04342ba3e 100644 --- a/typescript/infra/config/environments/testnet4/igp.ts +++ b/typescript/infra/config/environments/testnet4/igp.ts @@ -1,5 +1,6 @@ import { ChainMap, + ChainName, GasOracleContractType, IgpConfig, defaultMultisigConfigs, @@ -7,10 +8,10 @@ import { } from '@hyperlane-xyz/sdk'; import { exclude, objMap } from '@hyperlane-xyz/utils'; -import { TestnetChains, supportedChainNames } from './chains'; +import { supportedChainNames } from './chains'; import { owners } from './owners'; -function getGasOracles(local: TestnetChains) { +function getGasOracles(local: ChainName) { return Object.fromEntries( exclude(local, supportedChainNames).map((name) => [ name, diff --git a/typescript/infra/config/environments/testnet4/ism/verification.json b/typescript/infra/config/environments/testnet4/ism/verification.json index 71c1a20704..9b573597f6 100644 --- a/typescript/infra/config/environments/testnet4/ism/verification.json +++ b/typescript/infra/config/environments/testnet4/ism/verification.json @@ -2726,5 +2726,127 @@ "constructorArguments": "", "isProxy": true } + ], + "ancient8testnet": [ + { + "name": "MerkleRootMultisigIsmFactory", + "address": "0x6E7b29CB2A7617405B4d30C6f84bBD51b4Bb4be8", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x209e7F9d40954E230008B9bb076a0901d32695e5", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "MessageIdMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "AggregationIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "AggregationHookFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "RoutingIsmFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "MerkleRootMultisigIsmFactory", + "address": "0x6E7b29CB2A7617405B4d30C6f84bBD51b4Bb4be8", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMerkleRootMultisigIsm", + "address": "0x209e7F9d40954E230008B9bb076a0901d32695e5", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "MessageIdMultisigIsmFactory", + "address": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticMessageIdMultisigIsm", + "address": "0x99B304925A08aba9305bC0A8FccBf71B4290c5EF", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "AggregationIsmFactory", + "address": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationIsm", + "address": "0x33999AB153F68D481AAB1B238368Ffd1Fe81F360", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "AggregationHookFactory", + "address": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "StaticAggregationHook", + "address": "0x3e6F45B03314bD21BcE4201666d483291575E391", + "constructorArguments": "", + "isProxy": true + }, + { + "name": "RoutingIsmFactory", + "address": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "constructorArguments": "", + "isProxy": false + }, + { + "name": "DomaingRoutingIsm", + "address": "0x87935eB971eaA9826060261b07a919451dfd0409", + "constructorArguments": "", + "isProxy": true + } ] } diff --git a/typescript/infra/config/environments/testnet4/owners.ts b/typescript/infra/config/environments/testnet4/owners.ts index 2522ea3892..3dcc2bad0f 100644 --- a/typescript/infra/config/environments/testnet4/owners.ts +++ b/typescript/infra/config/environments/testnet4/owners.ts @@ -1,14 +1,14 @@ import { ChainMap } from '@hyperlane-xyz/sdk'; import { Address } from '@hyperlane-xyz/utils'; -import { ethereumChainNames } from './chains'; +import { supportedChainNames } from './chains'; const ETHEREUM_DEPLOYER_ADDRESS = '0xfaD1C94469700833717Fa8a3017278BC1cA8031C'; // const SEALEVEL_DEPLOYER_ADDRESS = '6DjHX6Ezjpq3zZMZ8KsqyoFYo1zPSDoiZmLLkxD4xKXS'; export const owners: ChainMap
= { ...Object.fromEntries( - ethereumChainNames.map((chain) => [chain, ETHEREUM_DEPLOYER_ADDRESS]), + supportedChainNames.map((chain) => [chain, ETHEREUM_DEPLOYER_ADDRESS]), ), // [chainMetadata.solanadevnet.name]: SEALEVEL_DEPLOYER_ADDRESS, }; diff --git a/typescript/infra/config/environments/testnet4/validators.ts b/typescript/infra/config/environments/testnet4/validators.ts index 44ddc20054..fe07e605fc 100644 --- a/typescript/infra/config/environments/testnet4/validators.ts +++ b/typescript/infra/config/environments/testnet4/validators.ts @@ -31,6 +31,18 @@ export const validatorChainConfig = ( 'alfajores', ), }, + ancient8testnet: { + interval: 5, + reorgPeriod: chainMetadata.ancient8testnet.blocks!.reorgPeriod!, + validators: validatorsConfig( + { + [Contexts.Hyperlane]: ['0x2233a5ce12f814bd64c9cdd73410bb8693124d40'], + [Contexts.ReleaseCandidate]: [], + [Contexts.Neutron]: [], + }, + 'ancient8testnet', + ), + }, basegoerli: { interval: 5, reorgPeriod: chainMetadata.basegoerli.blocks!.reorgPeriod!, diff --git a/typescript/infra/config/environments/testnet4/warp/ancient8-ETH-addresses.json b/typescript/infra/config/environments/testnet4/warp/ancient8-ETH-addresses.json new file mode 100644 index 0000000000..73dcf9954d --- /dev/null +++ b/typescript/infra/config/environments/testnet4/warp/ancient8-ETH-addresses.json @@ -0,0 +1,8 @@ +{ + "ancient8testnet": { + "router": "0x1b33611fCc073aB0737011d5512EF673Bff74962" + }, + "goerli": { + "router": "0x0918293aadfa13F8c9F2cdE415811b6AD9ff4a2d" + } +} diff --git a/typescript/infra/config/environments/testnet4/warp/ancient8-USDC-addresses.json b/typescript/infra/config/environments/testnet4/warp/ancient8-USDC-addresses.json new file mode 100644 index 0000000000..b14dacd6d3 --- /dev/null +++ b/typescript/infra/config/environments/testnet4/warp/ancient8-USDC-addresses.json @@ -0,0 +1,8 @@ +{ + "ancient8testnet": { + "router": "0x28B02B97a850872C4D33C3E024fab6499ad96564" + }, + "goerli": { + "router": "0xEF2a1f411d919878159303D9E3fe00D001F7D1D0" + } +} diff --git a/typescript/infra/config/environments/testnet4/warp/verification.json b/typescript/infra/config/environments/testnet4/warp/verification.json new file mode 100644 index 0000000000..e6ec671bc6 --- /dev/null +++ b/typescript/infra/config/environments/testnet4/warp/verification.json @@ -0,0 +1,30 @@ +{ + "ancient8testnet": [ + { + "name": "HypERC20", + "address": "0x28B02B97a850872C4D33C3E024fab6499ad96564", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000000120000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + }, + { + "name": "HypERC20", + "address": "0x1b33611fCc073aB0737011d5512EF673Bff74962", + "constructorArguments": "00000000000000000000000000000000000000000000000000000000000000120000000000000000000000006966b0e55883d49bfb24539356a2f8a673e02039", + "isProxy": false + } + ], + "goerli": [ + { + "name": "HypERC20Collateral", + "address": "0xEF2a1f411d919878159303D9E3fe00D001F7D1D0", + "constructorArguments": "00000000000000000000000007865c6e87b9f70255377e024ace6630c1eaa37f00000000000000000000000049cfd6ef774acab14814d699e3f7ee36fdfba932", + "isProxy": false + }, + { + "name": "HypNative", + "address": "0x0918293aadfa13F8c9F2cdE415811b6AD9ff4a2d", + "constructorArguments": "00000000000000000000000049cfd6ef774acab14814d699e3f7ee36fdfba932", + "isProxy": false + } + ] +} diff --git a/typescript/infra/config/routingIsm.ts b/typescript/infra/config/routingIsm.ts index 2d306e6ce7..6e4d2e8f36 100644 --- a/typescript/infra/config/routingIsm.ts +++ b/typescript/infra/config/routingIsm.ts @@ -12,7 +12,7 @@ import { import { DeployEnvironment } from '../src/config'; import { Contexts } from './contexts'; -import { ethereumChainNames as mainnet3Chains } from './environments/mainnet3/chains'; +import { supportedChainNames as mainnet3Chains } from './environments/mainnet3/chains'; import { owners as mainnet3Owners } from './environments/mainnet3/owners'; import { owners as testOwners } from './environments/test/owners'; import { supportedChainNames as testnet4Chains } from './environments/testnet4/chains'; diff --git a/typescript/infra/helm/key-funder/templates/cron-job.yaml b/typescript/infra/helm/key-funder/templates/cron-job.yaml index e0fcb09c83..ed2ce3dce3 100644 --- a/typescript/infra/helm/key-funder/templates/cron-job.yaml +++ b/typescript/infra/helm/key-funder/templates/cron-job.yaml @@ -10,6 +10,7 @@ spec: jobTemplate: spec: backoffLimit: 0 + activeDeadlineSeconds: 14400 # 60 * 60 * 4 seconds = 4 hours template: spec: restartPolicy: Never diff --git a/typescript/infra/package.json b/typescript/infra/package.json index b924ce8981..4253c8ef5e 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/infra", "description": "Infrastructure utilities for the Hyperlane Network", - "version": "3.4.0", + "version": "3.5.1", "dependencies": { "@arbitrum/sdk": "^3.0.0", "@aws-sdk/client-iam": "^3.74.0", @@ -12,9 +12,9 @@ "@ethersproject/experimental": "^5.7.0", "@ethersproject/hardware-wallets": "^5.7.0", "@ethersproject/providers": "^5.7.2", - "@hyperlane-xyz/helloworld": "3.4.0", - "@hyperlane-xyz/sdk": "3.4.0", - "@hyperlane-xyz/utils": "3.4.0", + "@hyperlane-xyz/helloworld": "3.5.1", + "@hyperlane-xyz/sdk": "3.5.1", + "@hyperlane-xyz/utils": "3.5.1", "@nomiclabs/hardhat-etherscan": "^3.0.3", "@safe-global/api-kit": "^1.3.0", "@safe-global/protocol-kit": "^1.2.0", diff --git a/typescript/infra/scripts/announce-validators.ts b/typescript/infra/scripts/announce-validators.ts index 542e9de962..509c0d5237 100644 --- a/typescript/infra/scripts/announce-validators.ts +++ b/typescript/infra/scripts/announce-validators.ts @@ -8,6 +8,7 @@ import { AllChains, ChainName, HyperlaneCore } from '@hyperlane-xyz/sdk'; import { S3Validator } from '../src/agents/aws/validator'; import { CheckpointSyncerType } from '../src/config'; import { deployEnvToSdkEnv } from '../src/config/environment'; +import { isEthereumProtocolChain } from '../src/utils/utils'; import { getAgentConfig, @@ -80,8 +81,9 @@ async function main() { return; } await Promise.all( - Object.entries(agentConfig.validators.chains).map( - async ([chain, validatorChainConfig]) => { + Object.entries(agentConfig.validators.chains) + .filter(([chain, _]) => isEthereumProtocolChain(chain)) + .map(async ([chain, validatorChainConfig]) => { for (const validatorBaseConfig of validatorChainConfig.validators) { if ( validatorBaseConfig.checkpointSyncer.type == @@ -104,8 +106,7 @@ async function main() { chains.push(chain); } } - }, - ), + }), ); } diff --git a/typescript/infra/scripts/deploy.ts b/typescript/infra/scripts/deploy.ts index b205e72900..d8dc24a863 100644 --- a/typescript/infra/scripts/deploy.ts +++ b/typescript/infra/scripts/deploy.ts @@ -15,11 +15,7 @@ import { InterchainQueryDeployer, LiquidityLayerDeployer, } from '@hyperlane-xyz/sdk'; -import { - HypERC20CollateralConfig, - HypERC20Config, - TokenType, -} from '@hyperlane-xyz/sdk/dist/token/config'; +import { TokenType } from '@hyperlane-xyz/sdk/dist/token/config'; import { objMap } from '@hyperlane-xyz/utils'; import { Contexts } from '../config/contexts'; @@ -95,25 +91,25 @@ async function main() { multiProvider, ); const routerConfig = core.getRouterConfig(owner); - const syntheticConfig: HypERC20Config = { + const syntheticConfig = { type: TokenType.synthetic, name: 'USDT', symbol: 'USDT', decimals: 6, totalSupply: 0, - gas: 75_000, // collateral overhead - ...routerConfig['viction'], + ...routerConfig['ancient8testnet'], }; - const collateralConfig: HypERC20CollateralConfig = { - type: TokenType.collateral, - token: '0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT - gas: 65_000, // synthetic overhead - ...routerConfig['ethereum'], - interchainSecurityModule: aggregationIsm('viction', Contexts.Hyperlane), + const collateralConfig = { + type: TokenType.native, + ...routerConfig['goerli'], + interchainSecurityModule: aggregationIsm( + 'ancient8testnet', + Contexts.Hyperlane, + ), }; config = { - viction: syntheticConfig, - ethereum: collateralConfig, + ancient8testnet: syntheticConfig, + goerli: collateralConfig, }; deployer = new HypERC20Deployer(multiProvider, ismFactory); } else if (module === Modules.INTERCHAIN_GAS_PAYMASTER) { diff --git a/typescript/sdk/CHANGELOG.md b/typescript/sdk/CHANGELOG.md index 56d575928b..ea099570bc 100644 --- a/typescript/sdk/CHANGELOG.md +++ b/typescript/sdk/CHANGELOG.md @@ -1,5 +1,26 @@ # @hyperlane-xyz/sdk +## 3.5.1 + +### Patch Changes + +- a04454d6d: Use getBalance instead of queryContractSmart for CwTokenAdapter + - @hyperlane-xyz/core@3.5.1 + - @hyperlane-xyz/utils@3.5.1 + +## 3.5.0 + +### Minor Changes + +- 655b6a0cd: Redeploy Routing ISM Factories + +### Patch Changes + +- 08ba0d32b: Remove dead arbitrum goerli explorer link" +- f7d285e3a: Adds Test Recipient addresses to the SDK artifacts + - @hyperlane-xyz/core@3.5.0 + - @hyperlane-xyz/utils@3.5.0 + ## 3.4.0 ### Minor Changes diff --git a/typescript/sdk/logos/black/ancient8.svg b/typescript/sdk/logos/black/ancient8.svg new file mode 100644 index 0000000000..d82eb02686 --- /dev/null +++ b/typescript/sdk/logos/black/ancient8.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/typescript/sdk/logos/color/ancient8.svg b/typescript/sdk/logos/color/ancient8.svg new file mode 100644 index 0000000000..91b13825b3 --- /dev/null +++ b/typescript/sdk/logos/color/ancient8.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index 0bc963543b..212091bdc2 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -1,12 +1,12 @@ { "name": "@hyperlane-xyz/sdk", "description": "The official SDK for the Hyperlane Network", - "version": "3.4.0", + "version": "3.5.1", "dependencies": { "@cosmjs/cosmwasm-stargate": "^0.31.3", "@cosmjs/stargate": "^0.31.3", - "@hyperlane-xyz/core": "3.4.0", - "@hyperlane-xyz/utils": "3.4.0", + "@hyperlane-xyz/core": "3.5.1", + "@hyperlane-xyz/utils": "3.5.1", "@solana/spl-token": "^0.3.8", "@solana/web3.js": "^1.78.0", "@types/coingecko-api": "^1.0.10", diff --git a/typescript/sdk/src/consts/chainMetadata.ts b/typescript/sdk/src/consts/chainMetadata.ts index 4fbb89ec0d..bff7d3abe4 100644 --- a/typescript/sdk/src/consts/chainMetadata.ts +++ b/typescript/sdk/src/consts/chainMetadata.ts @@ -46,6 +46,35 @@ export const alfajores: ChainMetadata = { rpcUrls: [{ http: 'https://alfajores-forno.celo-testnet.org' }], }; +export const ancient8testnet: ChainMetadata = { + blockExplorers: [ + { + apiUrl: 'https://testnet.a8scan.io/api', + family: ExplorerFamily.Blockscout, + name: 'a8scan', + url: 'https://testnet.a8scan.io', + }, + ], + blocks: { + confirmations: 1, + estimateBlockTime: 2, + reorgPeriod: 0, + }, + chainId: 2863311531, + displayName: 'Ancient 8 Testnet', + displayNameShort: 'A8 Testnet', + domainId: 2863311531, + isTestnet: true, + name: Chains.ancient8testnet, + nativeToken: etherToken, + protocol: ProtocolType.Ethereum, + rpcUrls: [ + { + http: 'https://rpc-testnet.ancient8.gg', + }, + ], +}; + export const arbitrum: ChainMetadata = { blockExplorers: [ { @@ -1018,6 +1047,7 @@ export const viction: ChainMetadata = { */ export const chainMetadata: ChainMap = { alfajores, + ancient8testnet, arbitrum, arbitrumgoerli, avalanche, diff --git a/typescript/sdk/src/consts/chains.ts b/typescript/sdk/src/consts/chains.ts index 31626829b8..67f4b198fa 100644 --- a/typescript/sdk/src/consts/chains.ts +++ b/typescript/sdk/src/consts/chains.ts @@ -4,6 +4,7 @@ */ export enum Chains { alfajores = 'alfajores', + ancient8testnet = 'ancient8testnet', arbitrum = 'arbitrum', arbitrumgoerli = 'arbitrumgoerli', avalanche = 'avalanche', @@ -75,6 +76,7 @@ export const Mainnets: Array = [ export const Testnets: Array = [ Chains.alfajores, + Chains.ancient8testnet, Chains.arbitrumgoerli, Chains.basegoerli, Chains.bsctestnet, diff --git a/typescript/sdk/src/consts/environments/testnet.json b/typescript/sdk/src/consts/environments/testnet.json index 93257a9431..a16a880532 100644 --- a/typescript/sdk/src/consts/environments/testnet.json +++ b/typescript/sdk/src/consts/environments/testnet.json @@ -213,5 +213,23 @@ "testRecipient": "0xF45A4D54223DA32bf7b5D43a9a460Ef3C94C713B", "testTokenRecipient": "0x57d098e6952B6C1c85Ce0B68C9Deada3dCf7D05A", "routingIsmFactory": "0x832Ea28749C93C05E5AaF8207E4e61Bd56aE3877" + }, + "ancient8testnet": { + "merkleRootMultisigIsmFactory": "0x6E7b29CB2A7617405B4d30C6f84bBD51b4Bb4be8", + "messageIdMultisigIsmFactory": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213", + "aggregationIsmFactory": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7", + "aggregationHookFactory": "0xeb6f11189197223c656807a83B0DD374f9A6dF44", + "routingIsmFactory": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37", + "mailbox": "0x6966b0E55883d49BFB24539356a2f8A673E02039", + "proxyAdmin": "0x44b764045BfDC68517e10e783E69B376cef196B2", + "validatorAnnounce": "0xD0680F80F4f947968206806C2598Cbc5b6FE5b03", + "interchainSecurityModule": "0x4ac19e0bafc2aF6B98094F0a1B817dF196551219", + "merkleTreeHook": "0x3707bc8C7342aA6f693bCe1Bd7671Fca146F7F0A", + "fallbackRoutingHook": "0x863E8c26621c52ACa1849C53500606e73BA272F0", + "storageGasOracle": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C", + "interchainGasPaymaster": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD", + "protocolFee": "0x267B6B6eAf6790faE5D5E9070F28a9cE64CbF279", + "testRecipient": "0xb94F96D398eA5BAB5CA528EE9Fdc19afaA825818", + "testTokenRecipient": "0x51A0a100e7BC63Ea7821A3a023B6F17fb94FF011" } } diff --git a/typescript/sdk/src/consts/multisigIsm.ts b/typescript/sdk/src/consts/multisigIsm.ts index 339334e31b..2fa93538ea 100644 --- a/typescript/sdk/src/consts/multisigIsm.ts +++ b/typescript/sdk/src/consts/multisigIsm.ts @@ -11,6 +11,11 @@ export const defaultMultisigConfigs: ChainMap = { ], }, + ancient8testnet: { + threshold: 1, + validators: ['0x75dd01dca4b6ad6bd59d8226aa071a03a8f9e46f'], + }, + arbitrum: { threshold: 3, validators: [ @@ -44,8 +49,9 @@ export const defaultMultisigConfigs: ChainMap = { threshold: 2, validators: [ '0xb9453d675e0fa3c178a17b4ce1ad5b1a279b3af9', - '0x4512985a574cb127b2af2d4bb676876ce804e3f8', + '0x64889519ad3ffc8f3ae436fcd63efc6b853fd63f', // staked '0x41188cb5a5493a961c467ba38a3f8b1f1d35ee63', // everstake + '0xcff391b4e516452d424db66beb9052b041a9ed79', // dsrv ], }, @@ -64,6 +70,7 @@ export const defaultMultisigConfigs: ChainMap = { '0x570af9b7b36568c8877eebba6c6727aa9dab7268', '0x8292b1a53907ece0f76af8a50724e9492bcdc8a3', // dsrv '0xeaf5cf9100f36a4baeea779f8745dda86159103c', // everstake + '0x5450447aee7b544c462c9352bef7cad049b0c2dc', // zeeprime ], }, @@ -121,6 +128,7 @@ export const defaultMultisigConfigs: ChainMap = { '0xd4df66a859585678f2ea8357161d896be19cc1ca', '0x19fb7e04a1be6b39b6966a0b0c60b929a93ed672', // dsrv '0xdb96116d13a2fadde9742d7cc88474a5ed39a03a', // everstake + '0x5450447aee7b544c462c9352bef7cad049b0c2dc', // zeeprime ], }, @@ -199,6 +207,7 @@ export const defaultMultisigConfigs: ChainMap = { '0x5b7d47b76c69740462432f6a5a0ca5005e014157', // dsrv '0x22b1ad4322cdb5f2c76ebf4e5a93803d480fcf0d', // everstake '0x9636fbe90b6816438327b0fbde435aa3c8eeda15', // staked + '0x5450447aee7b544c462c9352bef7cad049b0c2dc', // zeeprime ], }, @@ -217,6 +226,7 @@ export const defaultMultisigConfigs: ChainMap = { '0x12ecb319c7f4e8ac5eb5226662aeb8528c5cefac', '0x008f24cbb1cc30ad0f19f2516ca75730e37efb5f', // dsrv '0x722aa4d45387009684582bca8281440d16b8b40f', // everstake + '0x5450447aee7b544c462c9352bef7cad049b0c2dc', // zeeprime ], }, @@ -224,7 +234,7 @@ export const defaultMultisigConfigs: ChainMap = { threshold: 2, validators: [ '0x86f2a44592bb98da766e880cfd70d3bbb295e61a', - '0xc84076030bdabaabb9e61161d833dd84b700afda', + '0x865818fe1db986036d5fd0466dcd462562436d1a', // dsrv '0x57231619fea13d85270ca6943298046c75a6dd01', // everstake ], }, @@ -242,8 +252,9 @@ export const defaultMultisigConfigs: ChainMap = { threshold: 2, validators: [ '0xad557170a9f2f21c35e03de07cb30dcbcc3dff63', - '0xb37fe43a9f47b7024c2d5ae22526cc66b5261533', + '0x37148DE77D9FA915e6F0A9B54bCdF5e6f53ca511', // staked '0x276de8e2b88e659c4e5ad30d62d9de42c3da3403', // everstake + '0xbac4ac39f1d8b5ef15f26fdb1294a7c9aba3f948', // dsrv ], }, diff --git a/typescript/sdk/src/core/HyperlaneCoreDeployer.ts b/typescript/sdk/src/core/HyperlaneCoreDeployer.ts index 674c7b61ba..6e1226b6fc 100644 --- a/typescript/sdk/src/core/HyperlaneCoreDeployer.ts +++ b/typescript/sdk/src/core/HyperlaneCoreDeployer.ts @@ -109,7 +109,10 @@ export class HyperlaneCoreDeployer extends HyperlaneDeployer< if ( !e.message.includes('already initialized') && // Some RPC providers dont return the revert reason (nor allow ethers to parse it), so we have to check the message - !e.message.includes('Reverted 0x08c379a') + !e.message.includes('Reverted 0x08c379a') && + // Handle situation where the gas estimation fails on the call function, + // then the real error reason is not available in `e.message`, but rather in `e.error.reason` + !e.error?.reason?.includes('already initialized') ) { throw e; } diff --git a/typescript/sdk/src/metadata/agentConfig.ts b/typescript/sdk/src/metadata/agentConfig.ts index ea4f8270cc..5be7f21fcd 100644 --- a/typescript/sdk/src/metadata/agentConfig.ts +++ b/typescript/sdk/src/metadata/agentConfig.ts @@ -235,29 +235,36 @@ const GasPaymentEnforcementSchema = z.union([ ]); export type GasPaymentEnforcement = z.infer; +const MetricAppContextSchema = z.object({ + name: z.string().min(1), + matchingList: MatchingListSchema.describe( + 'A matching list, any message that matches will be classified as this app context.', + ), +}); + export const RelayerAgentConfigSchema = AgentConfigSchema.extend({ db: z .string() - .nonempty() + .min(1) .optional() .describe('The path to the relayer database.'), relayChains: CommaSeperatedChainList.describe( 'Comma seperated list of chains to relay messages between.', ), gasPaymentEnforcement: z - .union([z.array(GasPaymentEnforcementSchema), z.string().nonempty()]) + .union([z.array(GasPaymentEnforcementSchema), z.string().min(1)]) .optional() .describe( 'The gas payment enforcement configuration as JSON. Expects an ordered array of `GasPaymentEnforcementConfig`.', ), whitelist: z - .union([MatchingListSchema, z.string().nonempty()]) + .union([MatchingListSchema, z.string().min(1)]) .optional() .describe( 'If no whitelist is provided ALL messages will be considered on the whitelist.', ), blacklist: z - .union([MatchingListSchema, z.string().nonempty()]) + .union([MatchingListSchema, z.string().min(1)]) .optional() .describe( 'If no blacklist is provided ALL will be considered to not be on the blacklist.', @@ -274,12 +281,18 @@ export const RelayerAgentConfigSchema = AgentConfigSchema.extend({ .describe( 'If true, allows local storage based checkpoint syncers. Not intended for production use.', ), + metricAppContexts: z + .union([z.array(MetricAppContextSchema), z.string().min(1)]) + .optional() + .describe( + 'A list of app contexts and their matching lists to use for metrics. A message will be classified as the first matching app context.', + ), }); export type RelayerConfig = z.infer; export const ScraperAgentConfigSchema = AgentConfigSchema.extend({ - db: z.string().nonempty().describe('Database connection string'), + db: z.string().min(1).describe('Database connection string'), chainsToScrape: CommaSeperatedChainList.describe( 'Comma separated list of chain names to scrape', ), @@ -290,32 +303,29 @@ export type ScraperConfig = z.infer; export const ValidatorAgentConfigSchema = AgentConfigSchema.extend({ db: z .string() - .nonempty() + .min(1) .optional() .describe('The path to the validator database.'), originChainName: z .string() - .nonempty() + .min(1) .describe('Name of the chain to validate messages on'), validator: AgentSignerSchema.describe('The validator attestation signer'), checkpointSyncer: z.discriminatedUnion('type', [ z .object({ type: z.literal('localStorage'), - path: z - .string() - .nonempty() - .describe('Path to the local storage location'), + path: z.string().min(1).describe('Path to the local storage location'), }) .describe('A local checkpoint syncer'), z .object({ type: z.literal('s3'), - bucket: z.string().nonempty(), - region: z.string().nonempty(), + bucket: z.string().min(1), + region: z.string().min(1), folder: z .string() - .nonempty() + .min(1) .optional() .describe( 'The folder/key-prefix to use, defaults to the root of the bucket', diff --git a/typescript/sdk/src/providers/SmartProvider/SmartProvider.test.ts b/typescript/sdk/src/providers/SmartProvider/SmartProvider.test.ts index 0deddd6a38..a3c240d4b3 100644 --- a/typescript/sdk/src/providers/SmartProvider/SmartProvider.test.ts +++ b/typescript/sdk/src/providers/SmartProvider/SmartProvider.test.ts @@ -10,13 +10,13 @@ import { ChainMetadata } from '../../metadata/chainMetadataTypes'; import { ProviderMethod } from './ProviderMethods'; import { HyperlaneSmartProvider } from './SmartProvider'; -const MIN_BLOCK_NUM = 10000000; +const MIN_BLOCK_NUM = 10200000; const DEFAULT_ACCOUNT = '0x9d525E28Fe5830eE92d7Aa799c4D21590567B595'; const WETH_CONTRACT = '0xb4fbf271143f4fbf7b91a5ded31805e42b2208d6'; const WETH_TRANSFER_TOPIC0 = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'; const WETH_TRANSFER_TOPIC1 = - '0x0000000000000000000000004648a43b2c14da09fdf82b161150d3f634f40491'; + '0x00000000000000000000000022a9af161b9660f3dc1b996bf1e622a2c58b8558'; const WETH_CALL_DATA = '0x70a082310000000000000000000000004f7a67464b5976d7547c860109e4432d50afb38e'; const TRANSFER_TX_HASH = @@ -61,7 +61,9 @@ describe('SmartProvider', () => { for (const [description, config] of configs) { describe(description, () => { - provider = HyperlaneSmartProvider.fromChainMetadata(config); + provider = HyperlaneSmartProvider.fromChainMetadata(config, { + debug: true, + }); itDoesIfSupported(ProviderMethod.GetBlock, async () => { const latestBlock = await provider.getBlock('latest'); diff --git a/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts b/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts index 10249bca11..fcbc0f6c4d 100644 --- a/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts +++ b/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts @@ -121,12 +121,9 @@ export class CwTokenAdapter } async getBalance(address: Address): Promise { - const resp = await this.queryToken({ - balance: { - address, - }, - }); - return resp.balance; + const provider = await this.getProvider(); + const balance = await provider.getBalance(address, this.addresses.token); + return balance.amount; } async getMetadata(): Promise { diff --git a/typescript/utils/CHANGELOG.md b/typescript/utils/CHANGELOG.md index 61bdcf1123..40b1b23c6f 100644 --- a/typescript/utils/CHANGELOG.md +++ b/typescript/utils/CHANGELOG.md @@ -1,5 +1,9 @@ # @hyperlane-xyz/utils +## 3.5.1 + +## 3.5.0 + ## 3.4.0 ### Patch Changes diff --git a/typescript/utils/package.json b/typescript/utils/package.json index 89be8bec1a..1976a5b946 100644 --- a/typescript/utils/package.json +++ b/typescript/utils/package.json @@ -1,7 +1,7 @@ { "name": "@hyperlane-xyz/utils", "description": "General utilities and types for the Hyperlane network", - "version": "3.4.0", + "version": "3.5.1", "dependencies": { "@cosmjs/encoding": "^0.31.3", "@solana/web3.js": "^1.78.0", diff --git a/yarn.lock b/yarn.lock index 04e50f8372..b4cc1e108b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4235,8 +4235,8 @@ __metadata: version: 0.0.0-use.local resolution: "@hyperlane-xyz/cli@workspace:typescript/cli" dependencies: - "@hyperlane-xyz/sdk": "npm:3.4.0" - "@hyperlane-xyz/utils": "npm:3.4.0" + "@hyperlane-xyz/sdk": "npm:3.5.1" + "@hyperlane-xyz/utils": "npm:3.5.1" "@inquirer/prompts": "npm:^3.0.0" "@types/mocha": "npm:^10.0.1" "@types/node": "npm:^18.14.5" @@ -4261,12 +4261,12 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/core@npm:3.4.0, @hyperlane-xyz/core@workspace:solidity": +"@hyperlane-xyz/core@npm:3.5.1, @hyperlane-xyz/core@workspace:solidity": version: 0.0.0-use.local resolution: "@hyperlane-xyz/core@workspace:solidity" dependencies: "@eth-optimism/contracts": "npm:^0.6.0" - "@hyperlane-xyz/utils": "npm:3.4.0" + "@hyperlane-xyz/utils": "npm:3.5.1" "@nomiclabs/hardhat-ethers": "npm:^2.2.1" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@openzeppelin/contracts": "npm:^4.9.3" @@ -4293,12 +4293,12 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/helloworld@npm:3.4.0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": +"@hyperlane-xyz/helloworld@npm:3.5.1, @hyperlane-xyz/helloworld@workspace:typescript/helloworld": version: 0.0.0-use.local resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld" dependencies: - "@hyperlane-xyz/core": "npm:3.4.0" - "@hyperlane-xyz/sdk": "npm:3.4.0" + "@hyperlane-xyz/core": "npm:3.5.1" + "@hyperlane-xyz/sdk": "npm:3.5.1" "@nomiclabs/hardhat-ethers": "npm:^2.2.1" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@openzeppelin/contracts-upgradeable": "npm:^4.9.3" @@ -4343,9 +4343,9 @@ __metadata: "@ethersproject/experimental": "npm:^5.7.0" "@ethersproject/hardware-wallets": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.2" - "@hyperlane-xyz/helloworld": "npm:3.4.0" - "@hyperlane-xyz/sdk": "npm:3.4.0" - "@hyperlane-xyz/utils": "npm:3.4.0" + "@hyperlane-xyz/helloworld": "npm:3.5.1" + "@hyperlane-xyz/sdk": "npm:3.5.1" + "@hyperlane-xyz/utils": "npm:3.5.1" "@nomiclabs/hardhat-ethers": "npm:^2.2.1" "@nomiclabs/hardhat-etherscan": "npm:^3.0.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" @@ -4393,14 +4393,14 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/sdk@npm:3.4.0, @hyperlane-xyz/sdk@workspace:typescript/sdk": +"@hyperlane-xyz/sdk@npm:3.5.1, @hyperlane-xyz/sdk@workspace:typescript/sdk": version: 0.0.0-use.local resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk" dependencies: "@cosmjs/cosmwasm-stargate": "npm:^0.31.3" "@cosmjs/stargate": "npm:^0.31.3" - "@hyperlane-xyz/core": "npm:3.4.0" - "@hyperlane-xyz/utils": "npm:3.4.0" + "@hyperlane-xyz/core": "npm:3.5.1" + "@hyperlane-xyz/utils": "npm:3.5.1" "@nomiclabs/hardhat-ethers": "npm:^2.2.1" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" "@solana/spl-token": "npm:^0.3.8" @@ -4437,7 +4437,7 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/utils@npm:3.4.0, @hyperlane-xyz/utils@workspace:typescript/utils": +"@hyperlane-xyz/utils@npm:3.5.1, @hyperlane-xyz/utils@workspace:typescript/utils": version: 0.0.0-use.local resolution: "@hyperlane-xyz/utils@workspace:typescript/utils" dependencies: