From 07ffbbea5ba38496c2490df9fe6372068c58c59a Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Thu, 12 Dec 2024 05:28:37 +0000 Subject: [PATCH 1/6] feat: overrides in the relayer to force collateral warp route mints to be read-only (#4918) ### Description Some context, and the fix for future warp routes: https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4905 This will force messages to certain collateral warp route recipients to have mint accounts as readonly. This is a first step toward requiring lower fees for some txs. An example of Helius fees for a USDC process that includes the USDC mint as writeable: ``` {"jsonrpc":"2.0","result":{"priorityFeeLevels":{"min":0.0,"low":292041.0,"medium":2207571.0,"high":10405557.0,"veryHigh":22996019.0,"unsafeMax":2000000000.0}},"id":"1"} ``` vs when it's not writeable: ``` {"jsonrpc":"2.0","result":{"priorityFeeLevels":{"min":0.0,"low":0.0,"medium":1.0,"high":150000.0,"veryHigh":10000000.0,"unsafeMax":2000000000.0}},"id":"1"} ``` The alternative to having this PR would be to: - keep marking mints as writeable, forcing us to overpay - or do a program upgrade of the warp routes (unlikely to happen) ### Drive-by changes - Removed `#[allow(warnings)]` from mailbox.rs and made required changes ### Related issues ### Backward compatibility ### Testing --- rust/main/Cargo.lock | 1 + rust/main/Cargo.toml | 1 + .../relayer/src/server/message_retry.rs | 24 +-- rust/main/agents/validator/src/submit.rs | 12 +- .../src/libs/account/tests.rs | 8 +- .../src/providers/cosmos/provider/parse.rs | 2 +- .../main/chains/hyperlane-sealevel/Cargo.toml | 1 + .../chains/hyperlane-sealevel/src/mailbox.rs | 140 +++++++++--------- 8 files changed, 102 insertions(+), 87 deletions(-) diff --git a/rust/main/Cargo.lock b/rust/main/Cargo.lock index 110954d2f7..e29131af94 100644 --- a/rust/main/Cargo.lock +++ b/rust/main/Cargo.lock @@ -4639,6 +4639,7 @@ dependencies = [ "serializable-account-meta", "solana-account-decoder", "solana-client", + "solana-program", "solana-sdk", "solana-transaction-status", "thiserror", diff --git a/rust/main/Cargo.toml b/rust/main/Cargo.toml index 6a0b7cbb35..72e3d6348d 100644 --- a/rust/main/Cargo.toml +++ b/rust/main/Cargo.toml @@ -127,6 +127,7 @@ sha256 = "1.1.4" sha3 = "0.10" solana-account-decoder = "=1.14.13" solana-client = "=1.14.13" +solana-program = "=1.14.13" solana-sdk = "=1.14.13" solana-transaction-status = "=1.14.13" static_assertions = "1.1" diff --git a/rust/main/agents/relayer/src/server/message_retry.rs b/rust/main/agents/relayer/src/server/message_retry.rs index 6d04eed86a..6d160355a5 100644 --- a/rust/main/agents/relayer/src/server/message_retry.rs +++ b/rust/main/agents/relayer/src/server/message_retry.rs @@ -96,9 +96,11 @@ mod tests { let (addr, mut rx) = setup_test_server(); let client = reqwest::Client::new(); - let mut message = HyperlaneMessage::default(); - // Use a random destination domain - message.destination = 42; + let message = HyperlaneMessage { + // Use a random destination domain + destination: 42, + ..Default::default() + }; let pending_operation = MockPendingOperation::with_message_data(message.clone()); let matching_list_body = json!([ { @@ -127,9 +129,11 @@ mod tests { let (addr, mut rx) = setup_test_server(); let client = reqwest::Client::new(); - let mut message = HyperlaneMessage::default(); - // Use a random origin domain - message.origin = 42; + let message = HyperlaneMessage { + // Use a random origin domain + origin: 42, + ..Default::default() + }; let pending_operation = MockPendingOperation::with_message_data(message.clone()); let matching_list_body = json!([ { @@ -216,9 +220,11 @@ mod tests { let (addr, mut rx) = setup_test_server(); let client = reqwest::Client::new(); - let mut message = HyperlaneMessage::default(); - // Use a random origin domain - message.origin = 42; + let message = HyperlaneMessage { + // Use a random origin domain + origin: 42, + ..Default::default() + }; let pending_operation = MockPendingOperation::with_message_data(message.clone()); let matching_list_body = json!([ { diff --git a/rust/main/agents/validator/src/submit.rs b/rust/main/agents/validator/src/submit.rs index 954b8d0d95..f4779c6656 100644 --- a/rust/main/agents/validator/src/submit.rs +++ b/rust/main/agents/validator/src/submit.rs @@ -559,7 +559,7 @@ mod test { let unix_timestamp = chrono::Utc::now().timestamp() as u64; let expected_reorg_period = 12; - let pre_reorg_merke_insertions = vec![ + let pre_reorg_merke_insertions = [ MerkleTreeInsertion::new(0, H256::random()), MerkleTreeInsertion::new(1, H256::random()), MerkleTreeInsertion::new(2, H256::random()), @@ -570,9 +570,9 @@ mod test { } // the last leaf is different post-reorg - let post_reorg_merkle_insertions = vec![ - pre_reorg_merke_insertions[0].clone(), - pre_reorg_merke_insertions[1].clone(), + let post_reorg_merkle_insertions = [ + pre_reorg_merke_insertions[0], + pre_reorg_merke_insertions[1], MerkleTreeInsertion::new(2, H256::random()), ]; let mut mock_onchain_merkle_tree = IncrementalMerkle::default(); @@ -589,9 +589,7 @@ mod test { // the db returns the pre-reorg merkle tree insertions let mut db = MockDb::new(); db.expect_retrieve_merkle_tree_insertion_by_leaf_index() - .returning(move |sequence| { - Ok(Some(pre_reorg_merke_insertions[*sequence as usize].clone())) - }); + .returning(move |sequence| Ok(Some(pre_reorg_merke_insertions[*sequence as usize]))); // boilerplate mocks let mut mock_merkle_tree_hook = MockMerkleTreeHook::new(); diff --git a/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs b/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs index 0ba8f73d74..1dc7d30331 100644 --- a/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs +++ b/rust/main/chains/hyperlane-cosmos/src/libs/account/tests.rs @@ -61,14 +61,14 @@ fn test_ethereum_style() { fn compressed_public_key() -> PublicKey { let hex = hex::decode(COMPRESSED_PUBLIC_KEY).unwrap(); let tendermint = tendermint::PublicKey::from_raw_secp256k1(&hex).unwrap(); - let pub_key = PublicKey::from(tendermint); - pub_key + + PublicKey::from(tendermint) } fn decompressed_public_key() -> PublicKey { let hex = hex::decode(COMPRESSED_PUBLIC_KEY).unwrap(); let decompressed = decompress_public_key(&hex).unwrap(); let tendermint = tendermint::PublicKey::from_raw_secp256k1(&decompressed).unwrap(); - let pub_key = PublicKey::from(tendermint); - pub_key + + PublicKey::from(tendermint) } diff --git a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider/parse.rs b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider/parse.rs index aac9b7ce5a..a2212f6128 100644 --- a/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider/parse.rs +++ b/rust/main/chains/hyperlane-cosmos/src/providers/cosmos/provider/parse.rs @@ -153,7 +153,7 @@ mod tests { fn encode_proto(msg: &MsgRecvPacket) -> Any { let mut buf = Vec::with_capacity(msg.encoded_len()); - MsgRecvPacket::encode(&msg, &mut buf).unwrap(); + MsgRecvPacket::encode(msg, &mut buf).unwrap(); Any { type_url: "".to_string(), diff --git a/rust/main/chains/hyperlane-sealevel/Cargo.toml b/rust/main/chains/hyperlane-sealevel/Cargo.toml index 666ebee877..171e7b31ba 100644 --- a/rust/main/chains/hyperlane-sealevel/Cargo.toml +++ b/rust/main/chains/hyperlane-sealevel/Cargo.toml @@ -18,6 +18,7 @@ serde.workspace = true serde_json.workspace = true solana-account-decoder.workspace = true solana-client.workspace = true +solana-program.workspace = true solana-sdk.workspace = true solana-transaction-status.workspace = true thiserror.workspace = true diff --git a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs index d64963e242..66e58131aa 100644 --- a/rust/main/chains/hyperlane-sealevel/src/mailbox.rs +++ b/rust/main/chains/hyperlane-sealevel/src/mailbox.rs @@ -1,6 +1,7 @@ -#![allow(warnings)] // FIXME remove +// Silence a clippy bug https://github.com/rust-lang/rust-clippy/issues/12281 +#![allow(clippy::blocks_in_conditions)] -use std::{collections::HashMap, num::NonZeroU64, ops::RangeInclusive, str::FromStr as _}; +use std::{collections::HashMap, ops::RangeInclusive, str::FromStr as _}; use async_trait::async_trait; use borsh::{BorshDeserialize, BorshSerialize}; @@ -9,10 +10,9 @@ use hyperlane_sealevel_interchain_security_module_interface::{ }; use hyperlane_sealevel_mailbox::{ accounts::{ - DispatchedMessageAccount, Inbox, InboxAccount, OutboxAccount, ProcessedMessage, - ProcessedMessageAccount, DISPATCHED_MESSAGE_DISCRIMINATOR, PROCESSED_MESSAGE_DISCRIMINATOR, + DispatchedMessageAccount, Inbox, InboxAccount, ProcessedMessageAccount, + DISPATCHED_MESSAGE_DISCRIMINATOR, PROCESSED_MESSAGE_DISCRIMINATOR, }, - instruction, instruction::InboxProcess, mailbox_dispatched_message_pda_seeds, mailbox_inbox_pda_seeds, mailbox_outbox_pda_seeds, mailbox_process_authority_pda_seeds, mailbox_processed_message_pda_seeds, @@ -20,54 +20,36 @@ use hyperlane_sealevel_mailbox::{ use hyperlane_sealevel_message_recipient_interface::{ HandleInstruction, MessageRecipientInstruction, }; -use jsonrpc_core::futures_util::TryFutureExt; +use lazy_static::lazy_static; use serializable_account_meta::SimulationReturnData; -use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig}; -use solana_client::{ - nonblocking::rpc_client::RpcClient, - rpc_client::SerializableTransaction, - rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig, RpcSendTransactionConfig}, - rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType}, - rpc_response::Response, -}; +use solana_client::{rpc_client::SerializableTransaction, rpc_response::Response}; +use solana_program::pubkey; use solana_sdk::{ account::Account, bs58, clock::Slot, commitment_config::CommitmentConfig, compute_budget::ComputeBudgetInstruction, - hash::Hash, instruction::{AccountMeta, Instruction}, - message::Message, pubkey::Pubkey, signature::Signature, signer::{keypair::Keypair, Signer as _}, - transaction::{Transaction, VersionedTransaction}, -}; -use solana_transaction_status::{ - EncodedConfirmedBlock, EncodedTransaction, EncodedTransactionWithStatusMeta, TransactionStatus, - UiCompiledInstruction, UiConfirmedBlock, UiInnerInstructions, UiInstruction, UiMessage, - UiParsedInstruction, UiReturnDataEncoding, UiTransaction, UiTransactionReturnData, - UiTransactionStatusMeta, + transaction::Transaction, }; +use solana_transaction_status::TransactionStatus; use tracing::{debug, info, instrument, warn}; use hyperlane_core::{ - accumulator::incremental::IncrementalMerkle, config::StrOrIntParseError, BatchItem, - ChainCommunicationError, ChainCommunicationError::ContractError, ChainResult, Checkpoint, - ContractLocator, Decode as _, Encode as _, FixedPointNumber, HyperlaneAbi, HyperlaneChain, - HyperlaneContract, HyperlaneDomain, HyperlaneMessage, HyperlaneProvider, Indexed, Indexer, - KnownHyperlaneDomain, LogMeta, Mailbox, MerkleTreeHook, ReorgPeriod, SequenceAwareIndexer, - TxCostEstimate, TxOutcome, H256, H512, U256, + config::StrOrIntParseError, ChainCommunicationError, ChainResult, ContractLocator, Decode as _, + Encode as _, FixedPointNumber, HyperlaneChain, HyperlaneContract, HyperlaneDomain, + HyperlaneMessage, HyperlaneProvider, Indexed, Indexer, KnownHyperlaneDomain, LogMeta, Mailbox, + MerkleTreeHook, ReorgPeriod, SequenceAwareIndexer, TxCostEstimate, TxOutcome, H256, H512, U256, }; use crate::account::{search_accounts_by_discriminator, search_and_validate_account}; -use crate::error::HyperlaneSealevelError; use crate::log_meta_composer::{ - is_interchain_payment_instruction, is_message_delivery_instruction, - is_message_dispatch_instruction, LogMetaComposer, + is_message_delivery_instruction, is_message_dispatch_instruction, LogMetaComposer, }; -use crate::utils::{decode_h256, decode_h512, from_base58}; use crate::{ConnectionConf, SealevelProvider, SealevelRpcClient}; const SYSTEM_PROGRAM: &str = "11111111111111111111111111111111"; @@ -87,14 +69,33 @@ const PROCESS_DESIRED_PRIORITIZATION_FEE_LAMPORTS_PER_TX: u64 = 500000; /// In micro-lamports. Multiply this by the compute units to figure out /// the additional cost of processing a message, in addition to the mandatory /// "base" cost of signature verification. +/// Unused at the moment, but kept for future reference. +#[allow(dead_code)] const PROCESS_COMPUTE_UNIT_PRICE_MICRO_LAMPORTS: u64 = - ( - // Convert to micro-lamports - (PROCESS_DESIRED_PRIORITIZATION_FEE_LAMPORTS_PER_TX * 1_000_000) - // Divide by the max compute units - / PROCESS_COMPUTE_UNITS as u64 - ); - + // Convert to micro-lamports + (PROCESS_DESIRED_PRIORITIZATION_FEE_LAMPORTS_PER_TX * 1_000_000) + // Divide by the max compute units + / PROCESS_COMPUTE_UNITS as u64; + +// Earlier versions of collateral warp routes were deployed off a version where the mint +// was requested as a writeable account for handle instruction. This is not necessary, +// and generally requires a higher priority fee to be paid. +// This is a HashMap of of (collateral warp route recipient -> mint address) that is +// used to force the mint address to be readonly. +lazy_static! { + static ref RECIPIENT_FORCED_READONLY_ACCOUNTS: HashMap = HashMap::from([ + // EZSOL + (pubkey!("b5pMgizA9vrGRt3hVqnU7vUVGBQUnLpwPzcJhG1ucyQ"), pubkey!("ezSoL6fY1PVdJcJsUpe5CM3xkfmy3zoVCABybm5WtiC")), + // ORCA + (pubkey!("8acihSm2QTGswniKgdgr4JBvJihZ1cakfvbqWCPBLoSp"), pubkey!("orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE")), + // USDC + (pubkey!("3EpVCPUgyjq2MfGeCttyey6bs5zya5wjYZ2BE6yDg6bm"), pubkey!("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")), + // USDT + (pubkey!("Bk79wMjvpPCh5iQcCEjPWFcG1V2TfgdwaBsWBEYFYSNU"), pubkey!("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB")), + // WIF + (pubkey!("CuQmsT4eSF4dYiiGUGYYQxJ7c58pUAD5ADE3BbFGzQKx"), pubkey!("EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm")), + ]); +} /// A reference to a Mailbox contract on some Sealevel chain pub struct SealevelMailbox { pub(crate) program_id: Pubkey, @@ -131,13 +132,17 @@ impl SealevelMailbox { }) } + /// Get the Inbox account pubkey and bump seed. pub fn inbox(&self) -> (Pubkey, u8) { self.inbox } + + /// Get the Outbox account pubkey and bump seed. pub fn outbox(&self) -> (Pubkey, u8) { self.outbox } + /// Get the provider RPC client. pub fn rpc(&self) -> &SealevelRpcClient { self.provider.rpc() } @@ -257,14 +262,26 @@ impl SealevelMailbox { message: message.body.clone(), }); - self.get_account_metas_with_instruction_bytes( - recipient_program_id, - &instruction - .encode() - .map_err(ChainCommunicationError::from_other)?, - hyperlane_sealevel_message_recipient_interface::HANDLE_ACCOUNT_METAS_PDA_SEEDS, - ) - .await + let mut account_metas = self + .get_account_metas_with_instruction_bytes( + recipient_program_id, + &instruction + .encode() + .map_err(ChainCommunicationError::from_other)?, + hyperlane_sealevel_message_recipient_interface::HANDLE_ACCOUNT_METAS_PDA_SEEDS, + ) + .await?; + + if let Some(forced_readonly_account) = + RECIPIENT_FORCED_READONLY_ACCOUNTS.get(&recipient_program_id) + { + account_metas + .iter_mut() + .filter(|account_meta| account_meta.pubkey == *forced_readonly_account) + .for_each(|account_meta| account_meta.is_writable = false); + } + + Ok(account_metas) } async fn get_account_metas_with_instruction_bytes( @@ -306,7 +323,8 @@ impl SealevelMailbox { } } - // Stolen from Solana's non-blocking client, but with Jito! + /// Send a transaction to Jito and wait for it to be confirmed. + /// Logic stolen from Solana's non-blocking client. pub async fn send_and_confirm_transaction_with_jito( &self, transaction: &impl SerializableTransaction, @@ -421,7 +439,7 @@ impl HyperlaneContract for SealevelMailbox { impl HyperlaneChain for SealevelMailbox { fn domain(&self) -> &HyperlaneDomain { - &self.provider.domain() + self.provider.domain() } fn provider(&self) -> Box { @@ -664,6 +682,7 @@ pub struct SealevelMailboxIndexer { } impl SealevelMailboxIndexer { + /// Create a new SealevelMailboxIndexer pub fn new( conf: &ConnectionConf, locator: ContractLocator, @@ -694,7 +713,7 @@ impl SealevelMailboxIndexer { } fn rpc(&self) -> &SealevelRpcClient { - &self.mailbox.rpc() + self.mailbox.rpc() } async fn get_dispatched_message_with_nonce( @@ -707,7 +726,7 @@ impl SealevelMailboxIndexer { let accounts = search_accounts_by_discriminator( self.rpc(), &self.program_id, - &DISPATCHED_MESSAGE_DISCRIMINATOR, + DISPATCHED_MESSAGE_DISCRIMINATOR, &nonce_bytes, unique_dispatched_message_pubkey_offset, unique_dispatch_message_pubkey_length, @@ -715,7 +734,7 @@ impl SealevelMailboxIndexer { .await?; let valid_message_storage_pda_pubkey = search_and_validate_account(accounts, |account| { - self.dispatched_message_account(&account) + self.dispatched_message_account(account) })?; // Now that we have the valid message storage PDA pubkey, we can get the full account data. @@ -800,7 +819,7 @@ impl SealevelMailboxIndexer { let accounts = search_accounts_by_discriminator( self.rpc(), &self.program_id, - &PROCESSED_MESSAGE_DISCRIMINATOR, + PROCESSED_MESSAGE_DISCRIMINATOR, &sequence_bytes, delivered_message_id_offset, delivered_message_id_length, @@ -810,7 +829,7 @@ impl SealevelMailboxIndexer { debug!(account_len = ?accounts.len(), "Found accounts with processed message discriminator"); let valid_message_storage_pda_pubkey = search_and_validate_account(accounts, |account| { - self.delivered_message_account(&account) + self.delivered_message_account(account) })?; // Now that we have the valid delivered message storage PDA pubkey, @@ -965,14 +984,3 @@ impl SequenceAwareIndexer for SealevelMailboxIndexer { Ok((Some(sequence), tip)) } } - -struct SealevelMailboxAbi; - -// TODO figure out how this is used and if we can support it for sealevel. -impl HyperlaneAbi for SealevelMailboxAbi { - const SELECTOR_SIZE_BYTES: usize = 8; - - fn fn_map() -> HashMap, &'static str> { - todo!() - } -} From 629b2bccfce968dc868705094de796683a4ff678 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Thu, 12 Dec 2024 10:56:43 +0000 Subject: [PATCH 2/6] fix: Re-enable Eclipse in Scraper (#4988) ### Description Re-enable Eclipse in Scraper ### Related issues - Contributes into https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/4271 ### Backward compatibility Yes ### Testing None (config change) Co-authored-by: Danil Nemirovsky <4614623+ameten@users.noreply.github.com> --- typescript/infra/config/environments/mainnet3/agent.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/typescript/infra/config/environments/mainnet3/agent.ts b/typescript/infra/config/environments/mainnet3/agent.ts index 9fa5ede3c2..ad075baccc 100644 --- a/typescript/infra/config/environments/mainnet3/agent.ts +++ b/typescript/infra/config/environments/mainnet3/agent.ts @@ -276,8 +276,7 @@ export const hyperlaneContextAgentChainConfig: AgentChainConfig< degenchain: true, dogechain: true, duckchain: true, - // Disabled until we get archival RPC for Eclipse - eclipsemainnet: false, + eclipsemainnet: true, endurance: true, ethereum: true, everclear: true, From 657ac92553e53142d586144a542e1b684dac79a5 Mon Sep 17 00:00:00 2001 From: Yorke Rhodes Date: Thu, 12 Dec 2024 10:16:56 -0500 Subject: [PATCH 3/6] fix: suppress help on CLI failures (#4976) ### Description No longer outputs help dialog on any error --- .changeset/long-llamas-fly.md | 5 +++++ typescript/cli/cli.ts | 12 +----------- 2 files changed, 6 insertions(+), 11 deletions(-) create mode 100644 .changeset/long-llamas-fly.md diff --git a/.changeset/long-llamas-fly.md b/.changeset/long-llamas-fly.md new file mode 100644 index 0000000000..c0d6d01e9b --- /dev/null +++ b/.changeset/long-llamas-fly.md @@ -0,0 +1,5 @@ +--- +"@hyperlane-xyz/cli": patch +--- + +Suppress help on CLI failures diff --git a/typescript/cli/cli.ts b/typescript/cli/cli.ts index 45cad33bb8..1485a1ab9f 100644 --- a/typescript/cli/cli.ts +++ b/typescript/cli/cli.ts @@ -34,9 +34,6 @@ import { configureLogger, errorRed } from './src/logger.js'; import { checkVersion } from './src/utils/version-check.js'; import { VERSION } from './src/version.js'; -// From yargs code: -const MISSING_PARAMS_ERROR = 'Not enough non-option arguments'; - console.log(chalk.blue('Hyperlane'), chalk.magentaBright('CLI')); await checkVersion(); @@ -78,14 +75,7 @@ try { .demandCommand() .strict() .help() - .fail((msg, err, yargs) => { - if (msg && !msg.includes(MISSING_PARAMS_ERROR)) errorRed('Error: ' + msg); - console.log(''); - yargs.showHelp(); - console.log(''); - if (err) errorRed(err.toString()); - process.exit(1); - }).argv; + .showHelpOnFail(false).argv; } catch (error: any) { errorRed('Error: ' + error.message); } From c2ca8490d690ba43a18d64d0fecbb31850d4f0cc Mon Sep 17 00:00:00 2001 From: xeno097 Date: Thu, 12 Dec 2024 12:07:37 -0400 Subject: [PATCH 4/6] fix(cli): fix signer init strategy (#4987) ### Description Probably fixes an issue due to a recent pr merge that changes how signers are initialized based on the command to be executed ### Drive-by changes - Updates the key info message log level from info to debug to avoid the following ![image](https://github.com/user-attachments/assets/3ad0d4f8-36b9-4e2f-8c28-199858f8ef0e) ### Related issues ### Backward compatibility - Yes ### Testing - Manual --- .changeset/hot-spies-share.md | 5 ++ typescript/cli/src/commands/signCommands.ts | 3 +- .../strategies/chain/ChainResolverFactory.ts | 12 +-- .../strategies/chain/MultiChainResolver.ts | 76 ++++++++++--------- .../signer/MultiProtocolSignerManager.ts | 6 +- 5 files changed, 58 insertions(+), 44 deletions(-) create mode 100644 .changeset/hot-spies-share.md diff --git a/.changeset/hot-spies-share.md b/.changeset/hot-spies-share.md new file mode 100644 index 0000000000..4a215ae53c --- /dev/null +++ b/.changeset/hot-spies-share.md @@ -0,0 +1,5 @@ +--- +'@hyperlane-xyz/cli': minor +--- + +fix signer strategy init for broken cli commands diff --git a/typescript/cli/src/commands/signCommands.ts b/typescript/cli/src/commands/signCommands.ts index 8cfa6d4c1a..8243a10a88 100644 --- a/typescript/cli/src/commands/signCommands.ts +++ b/typescript/cli/src/commands/signCommands.ts @@ -13,7 +13,8 @@ export const SIGN_COMMANDS = [ export function isSignCommand(argv: any): boolean { //TODO: fix reading and checking warp without signer, and remove this const temporarySignCommandsCheck = - argv._[0] === 'warp' && (argv._[1] === 'read' || argv._[1] === 'check'); + argv._[0] === 'warp' && + (argv._[1] === 'read' || argv._[1] === 'check' || argv._[1] === 'verify'); return ( SIGN_COMMANDS.includes(argv._[0]) || (argv._.length > 1 && SIGN_COMMANDS.includes(argv._[1])) || diff --git a/typescript/cli/src/context/strategies/chain/ChainResolverFactory.ts b/typescript/cli/src/context/strategies/chain/ChainResolverFactory.ts index e417ba27b3..8e91417501 100644 --- a/typescript/cli/src/context/strategies/chain/ChainResolverFactory.ts +++ b/typescript/cli/src/context/strategies/chain/ChainResolverFactory.ts @@ -1,7 +1,6 @@ import { CommandType } from '../../../commands/signCommands.js'; import { MultiChainResolver } from './MultiChainResolver.js'; -import { SingleChainResolver } from './SingleChainResolver.js'; import { ChainResolver } from './types.js'; /** @@ -11,13 +10,16 @@ import { ChainResolver } from './types.js'; export class ChainResolverFactory { private static strategyMap: Map ChainResolver> = new Map([ [CommandType.WARP_DEPLOY, () => MultiChainResolver.forWarpRouteConfig()], - [CommandType.WARP_SEND, () => MultiChainResolver.forOriginDestination()], + // Using the forRelayer resolver because warp send allows the user to self relay the tx + [CommandType.WARP_SEND, () => MultiChainResolver.forRelayer()], [CommandType.WARP_APPLY, () => MultiChainResolver.forWarpRouteConfig()], [CommandType.WARP_READ, () => MultiChainResolver.forWarpCoreConfig()], [CommandType.WARP_CHECK, () => MultiChainResolver.forWarpCoreConfig()], - [CommandType.SEND_MESSAGE, () => MultiChainResolver.forOriginDestination()], + // Using the forRelayer resolver because send allows the user to self relay the tx + [CommandType.SEND_MESSAGE, () => MultiChainResolver.forRelayer()], [CommandType.AGENT_KURTOSIS, () => MultiChainResolver.forAgentKurtosis()], - [CommandType.STATUS, () => MultiChainResolver.forOriginDestination()], + // Using the forRelayer resolver because status allows the user to self relay the tx + [CommandType.STATUS, () => MultiChainResolver.forRelayer()], [CommandType.SUBMIT, () => MultiChainResolver.forStrategyConfig()], [CommandType.RELAYER, () => MultiChainResolver.forRelayer()], [CommandType.CORE_APPLY, () => MultiChainResolver.forCoreApply()], @@ -30,7 +32,7 @@ export class ChainResolverFactory { static getStrategy(argv: Record): ChainResolver { const commandKey = `${argv._[0]}:${argv._[1] || ''}`.trim() as CommandType; const createStrategy = - this.strategyMap.get(commandKey) || (() => new SingleChainResolver()); + this.strategyMap.get(commandKey) || (() => MultiChainResolver.default()); return createStrategy(); } } diff --git a/typescript/cli/src/context/strategies/chain/MultiChainResolver.ts b/typescript/cli/src/context/strategies/chain/MultiChainResolver.ts index 64f3257520..8563e9e5d9 100644 --- a/typescript/cli/src/context/strategies/chain/MultiChainResolver.ts +++ b/typescript/cli/src/context/strategies/chain/MultiChainResolver.ts @@ -4,8 +4,9 @@ import { DeployedCoreAddresses, DeployedCoreAddressesSchema, EvmCoreModule, + MultiProvider, } from '@hyperlane-xyz/sdk'; -import { assert } from '@hyperlane-xyz/utils'; +import { ProtocolType, assert } from '@hyperlane-xyz/utils'; import { DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH } from '../../../commands/options.js'; import { readCoreDeployConfigs } from '../../../config/core.js'; @@ -26,13 +27,12 @@ import { getWarpCoreConfigOrExit } from '../../../utils/warp.js'; import { ChainResolver } from './types.js'; enum ChainSelectionMode { - ORIGIN_DESTINATION, AGENT_KURTOSIS, WARP_CONFIG, WARP_READ, STRATEGY, - RELAYER, CORE_APPLY, + DEFAULT, } // This class could be broken down into multiple strategies @@ -54,13 +54,11 @@ export class MultiChainResolver implements ChainResolver { return this.resolveAgentChains(argv); case ChainSelectionMode.STRATEGY: return this.resolveStrategyChains(argv); - case ChainSelectionMode.RELAYER: - return this.resolveRelayerChains(argv); case ChainSelectionMode.CORE_APPLY: return this.resolveCoreApplyChains(argv); - case ChainSelectionMode.ORIGIN_DESTINATION: + case ChainSelectionMode.DEFAULT: default: - return this.resolveOriginDestinationChains(argv); + return this.resolveRelayerChains(argv); } } @@ -119,28 +117,6 @@ export class MultiChainResolver implements ChainResolver { return [argv.origin, ...argv.targets]; } - private async resolveOriginDestinationChains( - argv: Record, - ): Promise { - const { chainMetadata } = argv.context; - - argv.origin = - argv.origin ?? - (await runSingleChainSelectionStep( - chainMetadata, - 'Select the origin chain', - )); - - argv.destination = - argv.destination ?? - (await runSingleChainSelectionStep( - chainMetadata, - 'Select the destination chain', - )); - - return [argv.origin, argv.destination]; - } - private async resolveStrategyChains( argv: Record, ): Promise { @@ -151,7 +127,29 @@ export class MultiChainResolver implements ChainResolver { private async resolveRelayerChains( argv: Record, ): Promise { - return argv.chains.split(',').map((item: string) => item.trim()); + const { multiProvider } = argv.context; + const chains = []; + + if (argv.origin) { + chains.push(argv.origin); + } + + if (argv.destination) { + chains.push(argv.destination); + } + + if (!argv.chains) { + return Array.from( + new Set([...chains, ...this.getEvmChains(multiProvider)]), + ); + } + + return Array.from( + new Set([ + ...chains, + ...argv.chains.split(',').map((item: string) => item.trim()), + ]), + ); } private async getWarpRouteConfigChains( @@ -219,16 +217,20 @@ export class MultiChainResolver implements ChainResolver { } } - static forAgentKurtosis(): MultiChainResolver { - return new MultiChainResolver(ChainSelectionMode.AGENT_KURTOSIS); + private getEvmChains(multiProvider: MultiProvider): ChainName[] { + const chains = multiProvider.getKnownChainNames(); + + return chains.filter( + (chain) => multiProvider.getProtocol(chain) === ProtocolType.Ethereum, + ); } - static forOriginDestination(): MultiChainResolver { - return new MultiChainResolver(ChainSelectionMode.ORIGIN_DESTINATION); + static forAgentKurtosis(): MultiChainResolver { + return new MultiChainResolver(ChainSelectionMode.AGENT_KURTOSIS); } static forRelayer(): MultiChainResolver { - return new MultiChainResolver(ChainSelectionMode.RELAYER); + return new MultiChainResolver(ChainSelectionMode.DEFAULT); } static forStrategyConfig(): MultiChainResolver { @@ -246,4 +248,8 @@ export class MultiChainResolver implements ChainResolver { static forCoreApply(): MultiChainResolver { return new MultiChainResolver(ChainSelectionMode.CORE_APPLY); } + + static default(): MultiChainResolver { + return new MultiChainResolver(ChainSelectionMode.DEFAULT); + } } diff --git a/typescript/cli/src/context/strategies/signer/MultiProtocolSignerManager.ts b/typescript/cli/src/context/strategies/signer/MultiProtocolSignerManager.ts index 12f9c0f819..f8e411bad1 100644 --- a/typescript/cli/src/context/strategies/signer/MultiProtocolSignerManager.ts +++ b/typescript/cli/src/context/strategies/signer/MultiProtocolSignerManager.ts @@ -118,12 +118,12 @@ export class MultiProtocolSignerManager { let privateKey: string; if (this.options.key) { - this.logger.info( + this.logger.debug( `Using private key passed via CLI --key flag for chain ${chain}`, ); privateKey = this.options.key; } else if (ENV.HYP_KEY) { - this.logger.info(`Using private key from .env for chain ${chain}`); + this.logger.debug(`Using private key from .env for chain ${chain}`); privateKey = ENV.HYP_KEY; } else { privateKey = await this.extractPrivateKey(chain, signerStrategy); @@ -145,7 +145,7 @@ export class MultiProtocolSignerManager { `No private key found for chain ${chain}`, ); - this.logger.info( + this.logger.debug( `Extracting private key from strategy config/user prompt for chain ${chain}`, ); return strategyConfig.privateKey; From c3510265c28d2e5f8fed58ba9a56ebac2b8ada2a Mon Sep 17 00:00:00 2001 From: Trevor Porter Date: Thu, 12 Dec 2024 16:35:51 +0000 Subject: [PATCH 5/6] feat: add treasure batch contract address (#4991) ### Description - Multicall3 is at a nonstandard address due to it being a zksync chain ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --- rust/main/config/mainnet_config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index dc66d22345..c7fb366bd9 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -6322,6 +6322,7 @@ "validatorAnnounce": "0x1196055C61af3e3DA6f8458B07b255a72b64Bcf7" }, "treasure": { + "batchContractAddress": "0x2e29fe39496a56856D8698bD43e1dF4D0CE6266a", "blockExplorers": [ { "apiUrl": "https://rpc-explorer-verify.treasure.lol/contract_verification", From fd20bb1e92001bbbb34061821133a21909719d08 Mon Sep 17 00:00:00 2001 From: Lee <6251863+ltyu@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:52:01 -0500 Subject: [PATCH 6/6] feat: Add FeeHook and Swell to pzEth (#4974) ### Description ### Drive-by changes ### Related issues ### Backward compatibility ### Testing --------- Co-authored-by: Trevor Porter --- .changeset/dull-pianos-kiss.md | 9 ++ .registryrc | 2 +- rust/main/config/mainnet_config.json | 3 + typescript/cli/package.json | 2 +- typescript/helloworld/package.json | 2 +- .../configGetters/getRenzoEZETHWarpConfig.ts | 115 +++++++++++++++++- .../configGetters/getRenzoPZETHWarpConfig.ts | 40 +++++- .../environments/mainnet3/warp/warpIds.ts | 4 +- typescript/infra/config/warp.ts | 4 +- typescript/infra/package.json | 2 +- .../sdk/src/router/HyperlaneRouterChecker.ts | 10 +- typescript/widgets/package.json | 2 +- yarn.lock | 16 +-- 13 files changed, 183 insertions(+), 28 deletions(-) create mode 100644 .changeset/dull-pianos-kiss.md diff --git a/.changeset/dull-pianos-kiss.md b/.changeset/dull-pianos-kiss.md new file mode 100644 index 0000000000..333a748904 --- /dev/null +++ b/.changeset/dull-pianos-kiss.md @@ -0,0 +1,9 @@ +--- +'@hyperlane-xyz/helloworld': minor +'@hyperlane-xyz/widgets': minor +'@hyperlane-xyz/infra': minor +'@hyperlane-xyz/cli': minor +'@hyperlane-xyz/sdk': minor +--- + +Add FeeHook and Swell to pz and ez eth config generator. Bump up Registry 6.6.0 diff --git a/.registryrc b/.registryrc index ed389daa94..15e15930d3 100644 --- a/.registryrc +++ b/.registryrc @@ -1 +1 @@ -c7891cdf0fc6a1541c41e19251611c9152ee8bf9 +bde63f7c32e8d169d7e3163b14b5bb25bd3d5042 diff --git a/rust/main/config/mainnet_config.json b/rust/main/config/mainnet_config.json index c7fb366bd9..bb97daa396 100644 --- a/rust/main/config/mainnet_config.json +++ b/rust/main/config/mainnet_config.json @@ -925,6 +925,9 @@ "protocolFee": "0x8B05BF30F6247a90006c5837eA63C7905D79e6d8", "proxyAdmin": "0x75EE15Ee1B4A75Fa3e2fDF5DF3253c25599cc659", "rpcUrls": [ + { + "http": "https://rpc.ankr.com/eth" + }, { "http": "https://ethereum.publicnode.com" }, diff --git a/typescript/cli/package.json b/typescript/cli/package.json index 48f7d80596..7940f8e756 100644 --- a/typescript/cli/package.json +++ b/typescript/cli/package.json @@ -5,7 +5,7 @@ "dependencies": { "@aws-sdk/client-kms": "^3.577.0", "@aws-sdk/client-s3": "^3.577.0", - "@hyperlane-xyz/registry": "6.3.0", + "@hyperlane-xyz/registry": "6.6.0", "@hyperlane-xyz/sdk": "7.3.0", "@hyperlane-xyz/utils": "7.3.0", "@inquirer/core": "9.0.10", diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json index a7fdc9bb28..83bc100ac3 100644 --- a/typescript/helloworld/package.json +++ b/typescript/helloworld/package.json @@ -4,7 +4,7 @@ "version": "7.3.0", "dependencies": { "@hyperlane-xyz/core": "5.8.3", - "@hyperlane-xyz/registry": "6.3.0", + "@hyperlane-xyz/registry": "6.6.0", "@hyperlane-xyz/sdk": "7.3.0", "@openzeppelin/contracts-upgradeable": "^4.9.3", "ethers": "^5.7.2" diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts index 8928f2fb58..93ea7df1ef 100644 --- a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoEZETHWarpConfig.ts @@ -1,15 +1,24 @@ +import { parseEther } from 'ethers/lib/utils.js'; + +import { Mailbox__factory } from '@hyperlane-xyz/core'; import { ChainMap, + ChainName, + HookConfig, + HookType, HypTokenRouterConfig, IsmType, MultisigConfig, TokenType, buildAggregationIsmConfigs, } from '@hyperlane-xyz/sdk'; -import { symmetricDifference } from '@hyperlane-xyz/utils'; +import { Address, assert, symmetricDifference } from '@hyperlane-xyz/utils'; +import { getEnvironmentConfig } from '../../../../../scripts/core-utils.js'; import { getRegistry as getMainnet3Registry } from '../../chains.js'; +import rawTokenPrices from '../../tokenPrices.json'; +const tokenPrices: ChainMap = rawTokenPrices; const chainsToDeploy = [ 'arbitrum', 'optimism', @@ -23,7 +32,33 @@ const chainsToDeploy = [ 'zircuit', 'taiko', 'sei', + 'swell', ]; +export const MAX_PROTOCOL_FEE = parseEther('100').toString(); // Changing this will redeploy the PROTOCOL_FEE hook + +export function getProtocolFee(chain: ChainName) { + return (0.5 / Number(tokenPrices[chain])).toFixed(10).toString(); // ~$0.50 USD +} + +export function getRenzoHook( + defaultHook: Address, + chain: ChainName, +): HookConfig { + return { + type: HookType.AGGREGATION, + hooks: [ + defaultHook, + { + type: HookType.PROTOCOL_FEE, + owner: ezEthSafes[chain], + beneficiary: ezEthSafes[chain], + protocolFee: parseEther(getProtocolFee(chain)).toString(), + maxProtocolFee: MAX_PROTOCOL_FEE, + }, + ], + }; +} + const lockboxChain = 'ethereum'; // over the default 100k to account for xerc20 gas + ISM overhead over the default ISM https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/49f41d9759fd515bfd89e6e22e799c41b27b4119/typescript/sdk/src/router/GasRouterDeployer.ts#L14 const warpRouteOverheadGas = 200_000; @@ -41,6 +76,7 @@ const xERC20: Record<(typeof chainsToDeploy)[number], string> = { zircuit: '0x2416092f143378750bb29b79eD961ab195CcEea5', taiko: '0x2416092f143378750bb29b79eD961ab195CcEea5', sei: '0x6DCfbF4729890043DFd34A93A2694E5303BA2703', // redEth + swell: '0x2416092f143378750bb29b79eD961ab195CcEea5', }; export const ezEthValidators: ChainMap = { @@ -164,6 +200,16 @@ export const ezEthValidators: ChainMap = { { address: '0x952df7f0cb8611573a53dd7cbf29768871d9f8b0', alias: 'Renzo' }, ], }, + swell: { + threshold: 1, + validators: [ + { + address: '0x9eadf9217be22d9878e0e464727a2176d5c69ff8', + alias: 'Luganodes', + }, + { address: '0xb6b9b4bd4eb6eb3aef5e9826e7f8b8455947f67c', alias: 'Renzo' }, + ], + }, }; export const ezEthSafes: Record = { @@ -179,11 +225,65 @@ export const ezEthSafes: Record = { zircuit: '0x8410927C286A38883BC23721e640F31D3E3E79F8', taiko: '0x8410927C286A38883BC23721e640F31D3E3E79F8', sei: '0x0e60fd361fF5b90088e1782e6b21A7D177d462C5', + swell: '0x435E8c9652Da151292F3981bbf663EBEB6668501', +}; + +const existingProxyAdmins: ChainMap<{ address: string; owner: string }> = { + arbitrum: { + address: '0xdcB558d5C0F9A35C53Fa343c77eD0d346576e2Cf', + owner: ezEthSafes.arbitrum, + }, + optimism: { + address: '0xa50910ae66Df6A5F8e85dac032FD45BC2b7be6fF', + owner: ezEthSafes.optimism, + }, + base: { + address: '0xec1DdF05ff85D2B22B7d27E5b5E0B82961B7D889', + owner: ezEthSafes.base, + }, + blast: { + address: '0xA26F8cE2E21A503bf9e18c213965d7BC14997F48', + owner: ezEthSafes.blast, + }, + bsc: { + address: '0x486b39378f99f073A3043C6Aabe8666876A8F3C5', + owner: ezEthSafes.bsc, + }, + mode: { + address: '0x2F78F22a1D7491500C9ED9352b8239fbAbcDd84E', + owner: ezEthSafes.mode, + }, + fraxtal: { + address: '0x8bB69721B4E9b9df08bEdaeaA193008C7317Db59', + owner: ezEthSafes.fraxtal, + }, + linea: { + address: '0x2F78F22a1D7491500C9ED9352b8239fbAbcDd84E', + owner: ezEthSafes.linea, + }, + ethereum: { + address: '0x2F78F22a1D7491500C9ED9352b8239fbAbcDd84E', + owner: ezEthSafes.ethereum, + }, + zircuit: { + address: '0xec1DdF05ff85D2B22B7d27E5b5E0B82961B7D889', + owner: ezEthSafes.zircuit, + }, + sei: { + address: '0x33219fEF24C198d979F05d692a17507E41a0A73e', + owner: ezEthSafes.sei, + }, + taiko: { + address: '0xA3666f8a327AADB666F1906A38B17937e5F11f92', + owner: ezEthSafes.taiko, + }, }; export const getRenzoEZETHWarpConfig = async (): Promise< ChainMap > => { + const config = getEnvironmentConfig('mainnet3'); + const multiProvider = await config.getMultiProvider(); const registry = await getMainnet3Registry(); const validatorDiff = symmetricDifference( @@ -222,6 +322,15 @@ export const getRenzoEZETHWarpConfig = async (): Promise< await Promise.all( chainsToDeploy.map( async (chain): Promise<[string, HypTokenRouterConfig]> => { + const addresses = await registry.getChainAddresses(chain); + assert(addresses, 'No addresses in Registry'); + const { mailbox } = addresses; + + const mailboxContract = Mailbox__factory.connect( + mailbox, + multiProvider.getProvider(chain), + ); + const defaultHook = await mailboxContract.defaultHook(); const ret: [string, HypTokenRouterConfig] = [ chain, { @@ -233,7 +342,7 @@ export const getRenzoEZETHWarpConfig = async (): Promise< token: chain === lockboxChain ? lockbox : xERC20[chain], owner: ezEthSafes[chain], gas: warpRouteOverheadGas, - mailbox: (await registry.getChainAddresses(chain))!.mailbox, + mailbox, interchainSecurityModule: { type: IsmType.AGGREGATION, threshold: 2, @@ -254,6 +363,8 @@ export const getRenzoEZETHWarpConfig = async (): Promise< }, ], }, + hook: getRenzoHook(defaultHook, chain), + proxyAdmin: existingProxyAdmins[chain], }, ]; diff --git a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoPZETHWarpConfig.ts b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoPZETHWarpConfig.ts index 9c269f5413..6196031a8e 100644 --- a/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoPZETHWarpConfig.ts +++ b/typescript/infra/config/environments/mainnet3/warp/configGetters/getRenzoPZETHWarpConfig.ts @@ -1,3 +1,4 @@ +import { Mailbox__factory } from '@hyperlane-xyz/core'; import { ChainMap, HypTokenRouterConfig, @@ -5,11 +6,16 @@ import { TokenType, buildAggregationIsmConfigs, } from '@hyperlane-xyz/sdk'; -import { symmetricDifference } from '@hyperlane-xyz/utils'; +import { assert, symmetricDifference } from '@hyperlane-xyz/utils'; +import { getEnvironmentConfig } from '../../../../../scripts/core-utils.js'; import { getRegistry as getMainnet3Registry } from '../../chains.js'; -import { ezEthSafes, ezEthValidators } from './getRenzoEZETHWarpConfig.js'; +import { + ezEthSafes, + ezEthValidators, + getRenzoHook, +} from './getRenzoEZETHWarpConfig.js'; const lockbox = '0xbC5511354C4A9a50DE928F56DB01DD327c4e56d5'; const xERC20 = '0x9cb41CD74D01ae4b4f640EC40f7A60cA1bCF83E7'; @@ -17,21 +23,36 @@ const lockboxChain = 'ethereum'; // over the default 100k to account for xerc20 gas + ISM overhead over the default ISM https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/49f41d9759fd515bfd89e6e22e799c41b27b4119/typescript/sdk/src/router/GasRouterDeployer.ts#L14 const warpRouteOverheadGas = 200_000; -const chainsToDeploy = ['ethereum', 'zircuit']; +const chainsToDeploy = ['ethereum', 'swell', 'zircuit']; const pzEthValidators = { ethereum: ezEthValidators.ethereum, zircuit: ezEthValidators.zircuit, + swell: ezEthValidators.swell, }; const pzEthSafes: Record = { ethereum: ezEthSafes.ethereum, zircuit: ezEthSafes.zircuit, + swell: ezEthSafes.swell, +}; + +const existingProxyAdmins: ChainMap<{ address: string; owner: string }> = { + ethereum: { + address: '0x4f4671Ce69c9af15e33eB7Cf6D1358d1B39Af3bF', + owner: '0xD1e6626310fD54Eceb5b9a51dA2eC329D6D4B68A', + }, + zircuit: { + address: '0x8b789B4A56675240c9f0985B467752b870c75711', + owner: '0x8410927C286A38883BC23721e640F31D3E3E79F8', + }, }; export const getRenzoPZETHWarpConfig = async (): Promise< ChainMap > => { + const config = getEnvironmentConfig('mainnet3'); + const multiProvider = await config.getMultiProvider(); const registry = await getMainnet3Registry(); const validatorDiff = symmetricDifference( @@ -59,6 +80,15 @@ export const getRenzoPZETHWarpConfig = async (): Promise< await Promise.all( chainsToDeploy.map( async (chain): Promise<[string, HypTokenRouterConfig]> => { + const addresses = await registry.getChainAddresses(chain); + assert(addresses, 'No addresses in Registry'); + const { mailbox } = addresses; + + const mailboxContract = Mailbox__factory.connect( + mailbox, + multiProvider.getProvider(chain), + ); + const defaultHook = await mailboxContract.defaultHook(); const ret: [string, HypTokenRouterConfig] = [ chain, { @@ -70,7 +100,7 @@ export const getRenzoPZETHWarpConfig = async (): Promise< token: chain === lockboxChain ? lockbox : xERC20, owner: pzEthSafes[chain], gas: warpRouteOverheadGas, - mailbox: (await registry.getChainAddresses(chain))!.mailbox, + mailbox, interchainSecurityModule: { type: IsmType.AGGREGATION, threshold: 2, @@ -91,6 +121,8 @@ export const getRenzoPZETHWarpConfig = async (): Promise< }, ], }, + hook: getRenzoHook(defaultHook, chain), + proxyAdmin: existingProxyAdmins[chain], }, ]; diff --git a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts index 3d23bdc087..685567e4ad 100644 --- a/typescript/infra/config/environments/mainnet3/warp/warpIds.ts +++ b/typescript/infra/config/environments/mainnet3/warp/warpIds.ts @@ -1,6 +1,6 @@ export enum WarpRouteIds { Ancient8EthereumUSDC = 'USDC/ancient8-ethereum', - ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismSeiTaikoZircuitEZETH = 'EZETH/arbitrum-base-blast-bsc-ethereum-fraxtal-linea-mode-optimism-sei-taiko-zircuit', + ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismSeiSwellTaikoZircuitEZETH = 'EZETH/arbitrum-base-blast-bsc-ethereum-fraxtal-linea-mode-optimism-sei-swell-taiko-zircuit', ArbitrumBaseEnduranceUSDC = 'USDC/arbitrum-base-endurance', ArbitrumEthereumZircuitAMPHRETH = 'AMPHRETH/arbitrum-ethereum-zircuit', ArbitrumNeutronEclip = 'ECLIP/arbitrum-neutron', @@ -24,7 +24,7 @@ export enum WarpRouteIds { EthereumVictionETH = 'ETH/ethereum-viction', EthereumVictionUSDC = 'USDC/ethereum-viction', EthereumVictionUSDT = 'USDT/ethereum-viction', - EthereumZircuitPZETH = 'PZETH/ethereum-zircuit', + EthereumSwellZircuitPZETH = 'PZETH/ethereum-swell-zircuit', EthereumBscLumiaLUMIA = 'LUMIA/bsc-ethereum-lumia', InevmInjectiveINJ = 'INJ/inevm-injective', MantapacificNeutronTIA = 'TIA/mantapacific-neutron', diff --git a/typescript/infra/config/warp.ts b/typescript/infra/config/warp.ts index 5c9049eb7d..f9ebeb69c6 100644 --- a/typescript/infra/config/warp.ts +++ b/typescript/infra/config/warp.ts @@ -53,7 +53,7 @@ export const warpConfigGetterMap: Record = { [WarpRouteIds.EthereumInevmUSDT]: getEthereumInevmUSDTWarpConfig, [WarpRouteIds.ArbitrumNeutronEclip]: getArbitrumNeutronEclipWarpConfig, [WarpRouteIds.ArbitrumNeutronTIA]: getArbitrumNeutronTiaWarpConfig, - [WarpRouteIds.ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismSeiTaikoZircuitEZETH]: + [WarpRouteIds.ArbitrumBaseBlastBscEthereumFraxtalLineaModeOptimismSeiSwellTaikoZircuitEZETH]: getRenzoEZETHWarpConfig, [WarpRouteIds.InevmInjectiveINJ]: getInevmInjectiveINJWarpConfig, [WarpRouteIds.EthereumFlowCbBTC]: getEthereumFlowCbBTCWarpConfig, @@ -61,7 +61,7 @@ export const warpConfigGetterMap: Record = { [WarpRouteIds.EthereumVictionETH]: getEthereumVictionETHWarpConfig, [WarpRouteIds.EthereumVictionUSDC]: getEthereumVictionUSDCWarpConfig, [WarpRouteIds.EthereumVictionUSDT]: getEthereumVictionUSDTWarpConfig, - [WarpRouteIds.EthereumZircuitPZETH]: getRenzoPZETHWarpConfig, + [WarpRouteIds.EthereumSwellZircuitPZETH]: getRenzoPZETHWarpConfig, [WarpRouteIds.EthereumBscLumiaLUMIA]: getEthereumBscLUMIAWarpConfig, [WarpRouteIds.MantapacificNeutronTIA]: getMantapacificNeutronTiaWarpConfig, [WarpRouteIds.EclipseEthereumApxEth]: getEclipseEthereumApxEthWarpConfig, diff --git a/typescript/infra/package.json b/typescript/infra/package.json index 6f67d4ae23..a1aebb8998 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -14,7 +14,7 @@ "@ethersproject/providers": "*", "@google-cloud/secret-manager": "^5.5.0", "@hyperlane-xyz/helloworld": "7.3.0", - "@hyperlane-xyz/registry": "6.3.0", + "@hyperlane-xyz/registry": "6.6.0", "@hyperlane-xyz/sdk": "7.3.0", "@hyperlane-xyz/utils": "7.3.0", "@inquirer/prompts": "3.3.2", diff --git a/typescript/sdk/src/router/HyperlaneRouterChecker.ts b/typescript/sdk/src/router/HyperlaneRouterChecker.ts index abdc5c8852..e514c8522e 100644 --- a/typescript/sdk/src/router/HyperlaneRouterChecker.ts +++ b/typescript/sdk/src/router/HyperlaneRouterChecker.ts @@ -3,7 +3,6 @@ import { ethers } from 'ethers'; import { AddressBytes32, addressToBytes32, - assert, eqAddress, isZeroishAddress, rootLogger, @@ -68,10 +67,11 @@ export class HyperlaneRouterChecker< } if (config.hook) { - assert( - typeof config.hook === 'string', - 'Hook objects not supported in router checker', - ); + if (typeof config.hook !== 'string') + return this.logger.info( + `Hook objects not supported in router checker for HookConfig: ${config.hook}`, + ); + const hook = await router.hook(); if (!eqAddress(hook, config.hook as string)) { this.addViolation({ diff --git a/typescript/widgets/package.json b/typescript/widgets/package.json index f662fa2a29..701ff8ddd8 100644 --- a/typescript/widgets/package.json +++ b/typescript/widgets/package.json @@ -27,7 +27,7 @@ "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", "@eslint/js": "^9.15.0", - "@hyperlane-xyz/registry": "6.3.0", + "@hyperlane-xyz/registry": "6.6.0", "@storybook/addon-essentials": "^7.6.14", "@storybook/addon-interactions": "^7.6.14", "@storybook/addon-links": "^7.6.14", diff --git a/yarn.lock b/yarn.lock index 91d745e473..70a2c8f27f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7367,7 +7367,7 @@ __metadata: "@eslint/js": "npm:^9.15.0" "@ethersproject/abi": "npm:*" "@ethersproject/providers": "npm:*" - "@hyperlane-xyz/registry": "npm:6.3.0" + "@hyperlane-xyz/registry": "npm:6.6.0" "@hyperlane-xyz/sdk": "npm:7.3.0" "@hyperlane-xyz/utils": "npm:7.3.0" "@inquirer/core": "npm:9.0.10" @@ -7469,7 +7469,7 @@ __metadata: dependencies: "@eslint/js": "npm:^9.15.0" "@hyperlane-xyz/core": "npm:5.8.3" - "@hyperlane-xyz/registry": "npm:6.3.0" + "@hyperlane-xyz/registry": "npm:6.6.0" "@hyperlane-xyz/sdk": "npm:7.3.0" "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" @@ -7520,7 +7520,7 @@ __metadata: "@ethersproject/providers": "npm:*" "@google-cloud/secret-manager": "npm:^5.5.0" "@hyperlane-xyz/helloworld": "npm:7.3.0" - "@hyperlane-xyz/registry": "npm:6.3.0" + "@hyperlane-xyz/registry": "npm:6.6.0" "@hyperlane-xyz/sdk": "npm:7.3.0" "@hyperlane-xyz/utils": "npm:7.3.0" "@inquirer/prompts": "npm:3.3.2" @@ -7582,13 +7582,13 @@ __metadata: languageName: unknown linkType: soft -"@hyperlane-xyz/registry@npm:6.3.0": - version: 6.3.0 - resolution: "@hyperlane-xyz/registry@npm:6.3.0" +"@hyperlane-xyz/registry@npm:6.6.0": + version: 6.6.0 + resolution: "@hyperlane-xyz/registry@npm:6.6.0" dependencies: yaml: "npm:2.4.5" zod: "npm:^3.21.2" - checksum: 10/7a1b7226593edf8e12c7e3d425b7889679d46abae1e8c5a389a0b472e2e0a08b292ba89f60572eff9e844c7b5f7322e4420a8888fabef9967c206d5b39f391a1 + checksum: 10/4e8c955054a3872439f8a52ba208db848da1e46cdf920d4c0cf42080a147c4185d6fed2b00dec0320dfebeb7287578c8a95d3f2f81c2ba713a83a426a1793525 languageName: node linkType: hard @@ -7688,7 +7688,7 @@ __metadata: "@emotion/styled": "npm:^11.13.0" "@eslint/js": "npm:^9.15.0" "@headlessui/react": "npm:^2.1.8" - "@hyperlane-xyz/registry": "npm:6.3.0" + "@hyperlane-xyz/registry": "npm:6.6.0" "@hyperlane-xyz/sdk": "npm:7.3.0" "@hyperlane-xyz/utils": "npm:7.3.0" "@interchain-ui/react": "npm:^1.23.28"