-
Notifications
You must be signed in to change notification settings - Fork 8
feat(ev-deployer): part 2 - add Hyperlane contract support #181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
89eccaa
0c8f54e
2ba2b80
a540858
b9e2670
18ed817
f7d0e71
46ea9a6
e5f4eb9
be1b241
7e19222
e9fa70e
946026d
9dd5011
217be0c
4da01ea
3faa629
aeffc0d
a2d194e
e8a39f8
089ef22
6b85563
93b3eaa
70111fd
fa0e71f
1acd3c8
cb838e8
ee68354
ef5ac9e
65bbf9e
08c9eb4
46b75bf
9729cc0
a881b75
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,6 @@ | ||
| [submodule "contracts/lib/forge-std"] | ||
| path = contracts/lib/forge-std | ||
| url = https://github.com/foundry-rs/forge-std | ||
| [submodule "contracts/lib/hyperlane-monorepo"] | ||
| path = contracts/lib/hyperlane-monorepo | ||
| url = https://github.com/hyperlane-xyz/hyperlane-monorepo.git | ||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -14,14 +14,7 @@ The binary is output to `target/release/ev-deployer`. | |||
|
|
||||
| EV Deployer uses a TOML config file to define what contracts to include and how to configure them. See [`examples/devnet.toml`](examples/devnet.toml) for a complete example. | ||||
|
|
||||
| ```toml | ||||
| [chain] | ||||
| chain_id = 1234 | ||||
|
|
||||
| [contracts.admin_proxy] | ||||
| address = "0x000000000000000000000000000000000000Ad00" | ||||
| owner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" | ||||
| ``` | ||||
| See [`examples/devnet.toml`](examples/devnet.toml) for a complete example with all contracts configured. | ||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove duplicated sentence in configuration section. Line 17 repeats the same Proposed docs cleanup-See [`examples/devnet.toml`](examples/devnet.toml) for a complete example with all contracts configured.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||
|
|
||||
| ### Config reference | ||||
|
|
||||
|
|
@@ -38,6 +31,55 @@ owner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" | |||
| | `address` | address | Address to deploy at | | ||||
| | `owner` | address | Owner (must not be zero) | | ||||
|
|
||||
| #### `[contracts.fee_vault]` | ||||
|
|
||||
| | Field | Type | Description | | ||||
| |----------------------|---------|--------------------------------------------------| | ||||
| | `address` | address | Address to deploy at | | ||||
| | `owner` | address | Owner address | | ||||
| | `destination_domain` | u32 | Hyperlane destination domain (default: 0) | | ||||
| | `recipient_address` | bytes32 | Hyperlane recipient address (default: zero) | | ||||
| | `minimum_amount` | u64 | Minimum amount for bridging (default: 0) | | ||||
| | `call_fee` | u64 | Call fee for sendToCelestia (default: 0) | | ||||
| | `bridge_share_bps` | u64 | Basis points for bridge share, 0–10000 (default: 0, treated as 10000) | | ||||
| | `other_recipient` | address | Other recipient for split accounting (default: zero) | | ||||
| | `hyp_native_minter` | address | HypNativeMinter address (default: zero) | | ||||
|
|
||||
| #### `[contracts.mailbox]` | ||||
|
|
||||
| | Field | Type | Description | | ||||
| |-----------------|---------|-----------------------------------------------------| | ||||
| | `address` | address | Address to deploy at | | ||||
| | `owner` | address | Owner address (default: zero) | | ||||
| | `default_ism` | address | Default interchain security module (default: zero) | | ||||
| | `default_hook` | address | Default post-dispatch hook (default: zero) | | ||||
| | `required_hook` | address | Required post-dispatch hook, e.g. MerkleTreeHook (default: zero) | | ||||
|
|
||||
| #### `[contracts.merkle_tree_hook]` | ||||
|
|
||||
| | Field | Type | Description | | ||||
| |-----------|---------|----------------------------------------------------| | ||||
| | `address` | address | Address to deploy at | | ||||
| | `owner` | address | Owner address (default: zero) | | ||||
| | `mailbox` | address | Mailbox address (patched into bytecode as immutable)| | ||||
|
|
||||
| #### `[contracts.noop_ism]` | ||||
|
|
||||
| | Field | Type | Description | | ||||
| |-----------|---------|----------------------| | ||||
| | `address` | address | Address to deploy at | | ||||
|
|
||||
| #### `[contracts.protocol_fee]` | ||||
|
|
||||
| | Field | Type | Description | | ||||
| |--------------------|---------|---------------------------------------------------| | ||||
| | `address` | address | Address to deploy at | | ||||
| | `owner` | address | Owner address (default: zero) | | ||||
| | `max_protocol_fee` | u64 | Maximum protocol fee in wei | | ||||
| | `protocol_fee` | u64 | Protocol fee charged per dispatch in wei (default: 0) | | ||||
| | `beneficiary` | address | Beneficiary address that receives collected fees (default: zero) | | ||||
|
|
||||
|
|
||||
| ## Usage | ||||
|
|
||||
| ### Generate a starter config | ||||
|
|
@@ -88,7 +130,12 @@ Output: | |||
|
|
||||
| ```json | ||||
| { | ||||
| "admin_proxy": "0x000000000000000000000000000000000000Ad00" | ||||
| "admin_proxy": "0x000000000000000000000000000000000000Ad00", | ||||
| "fee_vault": "0x000000000000000000000000000000000000FE00", | ||||
| "mailbox": "0x0000000000000000000000000000000000001200", | ||||
| "merkle_tree_hook": "0x0000000000000000000000000000000000001100", | ||||
| "noop_ism": "0x0000000000000000000000000000000000001300", | ||||
| "protocol_fee": "0x0000000000000000000000000000000000001400" | ||||
| } | ||||
| ``` | ||||
|
|
||||
|
|
@@ -100,9 +147,14 @@ ev-deployer compute-address --config deploy.toml --contract admin_proxy | |||
|
|
||||
| ## Contracts | ||||
|
|
||||
| | Contract | Description | | ||||
| |----------------|-----------------------------------------------------| | ||||
| | `admin_proxy` | Proxy contract with owner-based access control | | ||||
| | Contract | Description | | ||||
| |--------------------|---------------------------------------------------------| | ||||
| | `admin_proxy` | Proxy contract with owner-based access control | | ||||
| | `fee_vault` | Fee vault with Hyperlane bridging support | | ||||
| | `mailbox` | Hyperlane core messaging hub | | ||||
| | `merkle_tree_hook` | Hyperlane required hook (Merkle tree for messages) | | ||||
| | `noop_ism` | Hyperlane ISM that accepts all messages | | ||||
| | `protocol_fee` | Hyperlane post-dispatch hook that charges a protocol fee| | ||||
|
|
||||
| Runtime bytecodes are embedded in the binary — no external toolchain is needed at deploy time. | ||||
|
|
||||
|
|
||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -4,3 +4,36 @@ chain_id = 1234 | |||||
| [contracts.admin_proxy] | ||||||
| address = "0x000000000000000000000000000000000000Ad00" | ||||||
| owner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" | ||||||
|
|
||||||
| [contracts.fee_vault] | ||||||
| address = "0x000000000000000000000000000000000000FE00" | ||||||
| owner = "0x000000000000000000000000000000000000Ad00" | ||||||
| destination_domain = 0 | ||||||
| recipient_address = "0x0000000000000000000000000000000000000000000000000000000000000000" | ||||||
| minimum_amount = 0 | ||||||
| call_fee = 0 | ||||||
| bridge_share_bps = 10000 | ||||||
| other_recipient = "0x0000000000000000000000000000000000000000" | ||||||
| hyp_native_minter = "0x0000000000000000000000000000000000000000" | ||||||
|
|
||||||
| [contracts.mailbox] | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should hyperlane contain its own namespace under
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. makes total sense |
||||||
| address = "0x0000000000000000000000000000000000001200" | ||||||
| owner = "0x000000000000000000000000000000000000Ad00" | ||||||
| default_ism = "0x0000000000000000000000000000000000001300" | ||||||
| default_hook = "0x0000000000000000000000000000000000001400" | ||||||
| required_hook = "0x0000000000000000000000000000000000001100" | ||||||
|
|
||||||
| [contracts.merkle_tree_hook] | ||||||
| address = "0x0000000000000000000000000000000000001100" | ||||||
| owner = "0x000000000000000000000000000000000000Ad00" | ||||||
| mailbox = "0x0000000000000000000000000000000000001200" | ||||||
|
|
||||||
| [contracts.noop_ism] | ||||||
| address = "0x0000000000000000000000000000000000001300" | ||||||
|
|
||||||
| [contracts.protocol_fee] | ||||||
| address = "0x0000000000000000000000000000000000001400" | ||||||
| owner = "0x000000000000000000000000000000000000Ad00" | ||||||
| max_protocol_fee = 1000000000000000000 | ||||||
| protocol_fee = 0 | ||||||
| beneficiary = "0x000000000000000000000000000000000000Ad00" | ||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,6 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //! TOML config types, parsing, and validation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use alloy_primitives::Address; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use alloy_primitives::{Address, B256}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use serde::Deserialize; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::path::Path; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -28,6 +28,16 @@ pub(crate) struct ChainConfig { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub(crate) struct ContractsConfig { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `AdminProxy` contract config (optional). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub admin_proxy: Option<AdminProxyConfig>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `FeeVault` contract config (optional). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fee_vault: Option<FeeVaultConfig>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `MerkleTreeHook` contract config (optional). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub merkle_tree_hook: Option<MerkleTreeHookConfig>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `Mailbox` contract config (optional). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub mailbox: Option<MailboxConfig>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `NoopIsm` contract config (optional). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub noop_ism: Option<NoopIsmConfig>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `ProtocolFee` contract config (optional). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub protocol_fee: Option<ProtocolFeeConfig>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `AdminProxy` configuration. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -39,6 +49,92 @@ pub(crate) struct AdminProxyConfig { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub owner: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `FeeVault` configuration. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Deserialize)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub(crate) struct FeeVaultConfig { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Address to deploy at. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub address: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Owner address. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub owner: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Hyperlane destination domain. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub destination_domain: u32, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Hyperlane recipient address (bytes32). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub recipient_address: B256, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Minimum amount for bridging. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub minimum_amount: u64, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Call fee for sendToCelestia. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub call_fee: u64, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Basis points for bridge share (0-10000). 0 defaults to 10000. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub bridge_share_bps: u64, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Other recipient for split accounting. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub other_recipient: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `HypNativeMinter` address. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub hyp_native_minter: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `MerkleTreeHook` configuration (Hyperlane required hook). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Deserialize)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub(crate) struct MerkleTreeHookConfig { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Address to deploy at. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub address: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Owner address (for post-genesis hook/ISM changes). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub owner: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Mailbox address (patched into bytecode as immutable). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub mailbox: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `ProtocolFee` configuration (Hyperlane post-dispatch hook that charges a protocol fee). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Deserialize)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub(crate) struct ProtocolFeeConfig { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Address to deploy at. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub address: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Owner address. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub owner: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Maximum protocol fee in wei. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub max_protocol_fee: u64, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Protocol fee charged per dispatch in wei. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub protocol_fee: u64, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Beneficiary address that receives collected fees. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub beneficiary: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `Mailbox` configuration (Hyperlane core messaging hub). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Deserialize)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub(crate) struct MailboxConfig { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Address to deploy at. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub address: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Owner address. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub owner: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Default interchain security module. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub default_ism: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Default post-dispatch hook. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub default_hook: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Required post-dispatch hook (e.g. `MerkleTreeHook`). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[serde(default)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub required_hook: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `NoopIsm` configuration (Hyperlane ISM that accepts all messages). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Deserialize)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub(crate) struct NoopIsmConfig { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Address to deploy at. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub address: Address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| impl DeployConfig { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Load and validate config from a TOML file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub(crate) fn load(path: &Path) -> eyre::Result<Self> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -57,6 +153,43 @@ impl DeployConfig { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(ref fv) = self.contracts.fee_vault { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eyre::ensure!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| !fv.owner.is_zero(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fee_vault.owner must not be the zero address" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eyre::ensure!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fv.bridge_share_bps <= 10000, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fee_vault.bridge_share_bps must be 0-10000, got {}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fv.bridge_share_bps | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(ref mth) = self.contracts.merkle_tree_hook { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eyre::ensure!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| !mth.mailbox.is_zero(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "merkle_tree_hook.mailbox must not be the zero address" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(ref pf) = self.contracts.protocol_fee { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eyre::ensure!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| !pf.owner.is_zero(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "protocol_fee.owner must not be the zero address" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eyre::ensure!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| !pf.beneficiary.is_zero(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "protocol_fee.beneficiary must not be the zero address" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let (Some(ap), Some(fv)) = (&self.contracts.admin_proxy, &self.contracts.fee_vault) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eyre::ensure!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ap.address != fv.address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "contracts.admin_proxy.address and contracts.fee_vault.address must be distinct" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+186
to
+191
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Address collision validation is incomplete—silent overwrites possible. Only Consider collecting all configured addresses and validating they are distinct: 🛠️ Suggested approach to validate all addresses are distinct+ // Collect all configured contract addresses and ensure they are distinct.
+ let mut addresses: Vec<(&str, Address)> = Vec::new();
+ if let Some(ref ap) = self.contracts.admin_proxy {
+ addresses.push(("admin_proxy", ap.address));
+ }
+ if let Some(ref fv) = self.contracts.fee_vault {
+ addresses.push(("fee_vault", fv.address));
+ }
+ if let Some(ref mth) = self.contracts.merkle_tree_hook {
+ addresses.push(("merkle_tree_hook", mth.address));
+ }
+ if let Some(ref mb) = self.contracts.mailbox {
+ addresses.push(("mailbox", mb.address));
+ }
+ if let Some(ref ni) = self.contracts.noop_ism {
+ addresses.push(("noop_ism", ni.address));
+ }
+ if let Some(ref pf) = self.contracts.protocol_fee {
+ addresses.push(("protocol_fee", pf.address));
+ }
+ for i in 0..addresses.len() {
+ for j in (i + 1)..addresses.len() {
+ eyre::ensure!(
+ addresses[i].1 != addresses[j].1,
+ "contracts.{}.address and contracts.{}.address must be distinct",
+ addresses[i].0,
+ addresses[j].0
+ );
+ }
+ }
+
- if let (Some(ap), Some(fv)) = (&self.contracts.admin_proxy, &self.contracts.fee_vault) {
- eyre::ensure!(
- ap.address != fv.address,
- "contracts.admin_proxy.address and contracts.fee_vault.address must be distinct"
- );
- }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -107,6 +240,57 @@ chain_id = 1 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn parse_merkle_tree_hook_config() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let toml = r#" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [chain] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chain_id = 1234 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [contracts.merkle_tree_hook] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| address = "0x0000000000000000000000000000000000001100" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| owner = "0x000000000000000000000000000000000000ad00" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mailbox = "0x0000000000000000000000000000000000001200" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "#; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let config: DeployConfig = toml::from_str(toml).unwrap(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config.validate().unwrap(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!(config.contracts.merkle_tree_hook.is_some()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mth = config.contracts.merkle_tree_hook.unwrap(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!(!mth.mailbox.is_zero()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn reject_zero_mailbox_merkle_tree_hook() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let toml = r#" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [chain] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chain_id = 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [contracts.merkle_tree_hook] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| address = "0x0000000000000000000000000000000000001100" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mailbox = "0x0000000000000000000000000000000000000000" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "#; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let config: DeployConfig = toml::from_str(toml).unwrap(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!(config.validate().is_err()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn reject_duplicate_addresses() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let toml = r#" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [chain] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chain_id = 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [contracts.admin_proxy] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| address = "0x000000000000000000000000000000000000Ad00" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| owner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [contracts.fee_vault] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| address = "0x000000000000000000000000000000000000Ad00" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| owner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "#; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let config: DeployConfig = toml::from_str(toml).unwrap(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!(config.validate().is_err()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn admin_proxy_only() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let toml = r#" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [chain] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Submodule declaration appears incomplete without committed gitlink.
If only
.gitmodulesis added but the submodule gitlink is not committed,actions/checkoutwith recursive submodules will not materializecontracts/lib/hyperlane-monorepo, and the workflow step at Line 44 in.github/workflows/ev_deployer.ymlwill fail oncd .../solidity.Please ensure the submodule pointer (gitlink) is included in the PR, pinned to the intended commit.
🤖 Prompt for AI Agents