From 1ecc93c64d2e5dbbaca2123f6faca8325402da28 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 19 Mar 2026 21:20:55 +0100 Subject: [PATCH 1/2] feat: integrate ev-deployer into ev-dev for genesis contract deployment - Add ev-deployer dependency to ev-dev - Accept optional --deploy-config argument in ev-dev CLI - Load deploy config and override chain ID if needed - Display deployed contract addresses in dev chain banner - Add just recipes for installing ev-dev and ev-deployer binaries --- Cargo.lock | 1 + bin/ev-deployer/src/config.rs | 22 ++++---- bin/ev-deployer/src/contracts/admin_proxy.rs | 2 +- bin/ev-deployer/src/contracts/fee_vault.rs | 2 +- bin/ev-deployer/src/contracts/immutables.rs | 10 ++-- bin/ev-deployer/src/contracts/mailbox.rs | 2 +- .../src/contracts/merkle_tree_hook.rs | 2 +- bin/ev-deployer/src/contracts/mod.rs | 19 +++---- bin/ev-deployer/src/contracts/noop_ism.rs | 2 +- bin/ev-deployer/src/contracts/permit2.rs | 2 +- bin/ev-deployer/src/contracts/protocol_fee.rs | 2 +- bin/ev-deployer/src/genesis.rs | 15 +++--- bin/ev-deployer/src/lib.rs | 9 ++++ bin/ev-deployer/src/main.rs | 6 +-- bin/ev-deployer/src/output.rs | 2 +- bin/ev-dev/Cargo.toml | 1 + bin/ev-dev/src/main.rs | 51 +++++++++++++++++-- justfile | 8 +++ 18 files changed, 109 insertions(+), 49 deletions(-) create mode 100644 bin/ev-deployer/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 3e41035..c5d2199 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2937,6 +2937,7 @@ dependencies = [ "alloy-primitives", "alloy-signer-local", "clap", + "ev-deployer", "ev-node", "evolve-ev-reth", "eyre", diff --git a/bin/ev-deployer/src/config.rs b/bin/ev-deployer/src/config.rs index 6140f90..853de34 100644 --- a/bin/ev-deployer/src/config.rs +++ b/bin/ev-deployer/src/config.rs @@ -7,7 +7,7 @@ use std::path::Path; /// Top-level deploy configuration. #[derive(Debug, Deserialize)] #[allow(dead_code)] -pub(crate) struct DeployConfig { +pub struct DeployConfig { /// Chain configuration. pub chain: ChainConfig, /// Contract configurations. @@ -17,14 +17,14 @@ pub(crate) struct DeployConfig { /// Chain-level settings. #[derive(Debug, Deserialize)] #[allow(dead_code)] -pub(crate) struct ChainConfig { +pub struct ChainConfig { /// The chain ID. pub chain_id: u64, } /// All contract configurations. #[derive(Debug, Deserialize)] -pub(crate) struct ContractsConfig { +pub struct ContractsConfig { /// `AdminProxy` contract config (optional). pub admin_proxy: Option, /// `FeeVault` contract config (optional). @@ -43,7 +43,7 @@ pub(crate) struct ContractsConfig { /// `AdminProxy` configuration. #[derive(Debug, Deserialize)] -pub(crate) struct AdminProxyConfig { +pub struct AdminProxyConfig { /// Address to deploy at. pub address: Address, /// Owner address. @@ -52,7 +52,7 @@ pub(crate) struct AdminProxyConfig { /// `FeeVault` configuration. #[derive(Debug, Deserialize)] -pub(crate) struct FeeVaultConfig { +pub struct FeeVaultConfig { /// Address to deploy at. pub address: Address, /// Owner address. @@ -82,7 +82,7 @@ pub(crate) struct FeeVaultConfig { /// `MerkleTreeHook` configuration (Hyperlane required hook). #[derive(Debug, Deserialize)] -pub(crate) struct MerkleTreeHookConfig { +pub struct MerkleTreeHookConfig { /// Address to deploy at. pub address: Address, /// Owner address (for post-genesis hook/ISM changes). @@ -94,7 +94,7 @@ pub(crate) struct MerkleTreeHookConfig { /// `MailboxConfig` configuration (Hyperlane core messaging hub). #[derive(Debug, Deserialize)] -pub(crate) struct MailboxConfig { +pub struct MailboxConfig { /// Address to deploy at. pub address: Address, /// Owner address. @@ -113,21 +113,21 @@ pub(crate) struct MailboxConfig { /// `NoopIsm` configuration (Hyperlane ISM that accepts all messages). #[derive(Debug, Deserialize)] -pub(crate) struct NoopIsmConfig { +pub struct NoopIsmConfig { /// Address to deploy at. pub address: Address, } /// `Permit2` configuration (Uniswap token approval manager). #[derive(Debug, Deserialize)] -pub(crate) struct Permit2Config { +pub struct Permit2Config { /// Address to deploy at. pub address: Address, } /// `ProtocolFee` configuration (Hyperlane post-dispatch hook that charges a protocol fee). #[derive(Debug, Deserialize)] -pub(crate) struct ProtocolFeeConfig { +pub struct ProtocolFeeConfig { /// Address to deploy at. pub address: Address, /// Owner address. @@ -145,7 +145,7 @@ pub(crate) struct ProtocolFeeConfig { impl DeployConfig { /// Load and validate config from a TOML file. - pub(crate) fn load(path: &Path) -> eyre::Result { + pub fn load(path: &Path) -> eyre::Result { let content = std::fs::read_to_string(path)?; let config: Self = toml::from_str(&content)?; config.validate()?; diff --git a/bin/ev-deployer/src/contracts/admin_proxy.rs b/bin/ev-deployer/src/contracts/admin_proxy.rs index 51d5ce5..c1a4e1e 100644 --- a/bin/ev-deployer/src/contracts/admin_proxy.rs +++ b/bin/ev-deployer/src/contracts/admin_proxy.rs @@ -9,7 +9,7 @@ use std::collections::BTreeMap; const ADMIN_PROXY_BYTECODE: &[u8] = &hex!("60806040526004361061007e575f3560e01c80638da5cb5b1161004d5780638da5cb5b1461012d578063e30c397814610157578063f2fde38b14610181578063fa4bb79d146101a957610085565b806318dfb3c7146100895780631cff79cd146100c557806379ba5097146101015780638b5298541461011757610085565b3661008557005b5f5ffd5b348015610094575f5ffd5b506100af60048036038101906100aa9190610cf8565b6101e5565b6040516100bc9190610ea1565b60405180910390f35b3480156100d0575f5ffd5b506100eb60048036038101906100e69190610f70565b6104d9565b6040516100f89190611015565b60405180910390f35b34801561010c575f5ffd5b5061011561066c565b005b348015610122575f5ffd5b5061012b6107ed565b005b348015610138575f5ffd5b506101416108b4565b60405161014e9190611044565b60405180910390f35b348015610162575f5ffd5b5061016b6108d8565b6040516101789190611044565b60405180910390f35b34801561018c575f5ffd5b506101a760048036038101906101a2919061105d565b6108fd565b005b3480156101b4575f5ffd5b506101cf60048036038101906101ca91906110bb565b610aa4565b6040516101dc9190611015565b60405180910390f35b60605f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461026c576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8282905085859050146102ab576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8484905067ffffffffffffffff8111156102c8576102c761112c565b5b6040519080825280602002602001820160405280156102fb57816020015b60608152602001906001900390816102e65790505b5090505f5f90505b858590508110156104d0575f5f87878481811061032357610322611159565b5b9050602002016020810190610338919061105d565b73ffffffffffffffffffffffffffffffffffffffff1686868581811061036157610360611159565b5b90506020028101906103739190611192565b604051610381929190611230565b5f604051808303815f865af19150503d805f81146103ba576040519150601f19603f3d011682016040523d82523d5f602084013e6103bf565b606091505b50915091508161040657806040517fa5fa8d2b0000000000000000000000000000000000000000000000000000000081526004016103fd9190611015565b60405180910390fd5b87878481811061041957610418611159565b5b905060200201602081019061042e919061105d565b73ffffffffffffffffffffffffffffffffffffffff167fc96720f35dd524e76ea92971ce13d08e9a17816bf3b0008a7083e6032354ebb587878681811061047857610477611159565b5b905060200281019061048a9190611192565b8460405161049a93929190611274565b60405180910390a2808484815181106104b6576104b5611159565b5b602002602001018190525050508080600101915050610303565b50949350505050565b60605f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610560576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f8573ffffffffffffffffffffffffffffffffffffffff168585604051610589929190611230565b5f604051808303815f865af19150503d805f81146105c2576040519150601f19603f3d011682016040523d82523d5f602084013e6105c7565b606091505b50915091508161060e57806040517fa5fa8d2b0000000000000000000000000000000000000000000000000000000081526004016106059190611015565b60405180910390fd5b8573ffffffffffffffffffffffffffffffffffffffff167fc96720f35dd524e76ea92971ce13d08e9a17816bf3b0008a7083e6032354ebb586868460405161065893929190611274565b60405180910390a280925050509392505050565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106f2576040517f1853971c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f60015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610872576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610982576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109e7576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60605f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b2b576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f8673ffffffffffffffffffffffffffffffffffffffff16848787604051610b55929190611230565b5f6040518083038185875af1925050503d805f8114610b8f576040519150601f19603f3d011682016040523d82523d5f602084013e610b94565b606091505b509150915081610bdb57806040517fa5fa8d2b000000000000000000000000000000000000000000000000000000008152600401610bd29190611015565b60405180910390fd5b8673ffffffffffffffffffffffffffffffffffffffff167fc96720f35dd524e76ea92971ce13d08e9a17816bf3b0008a7083e6032354ebb5878784604051610c2593929190611274565b60405180910390a28092505050949350505050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112610c6357610c62610c42565b5b8235905067ffffffffffffffff811115610c8057610c7f610c46565b5b602083019150836020820283011115610c9c57610c9b610c4a565b5b9250929050565b5f5f83601f840112610cb857610cb7610c42565b5b8235905067ffffffffffffffff811115610cd557610cd4610c46565b5b602083019150836020820283011115610cf157610cf0610c4a565b5b9250929050565b5f5f5f5f60408587031215610d1057610d0f610c3a565b5b5f85013567ffffffffffffffff811115610d2d57610d2c610c3e565b5b610d3987828801610c4e565b9450945050602085013567ffffffffffffffff811115610d5c57610d5b610c3e565b5b610d6887828801610ca3565b925092505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610de182610d9f565b610deb8185610da9565b9350610dfb818560208601610db9565b610e0481610dc7565b840191505092915050565b5f610e1a8383610dd7565b905092915050565b5f602082019050919050565b5f610e3882610d76565b610e428185610d80565b935083602082028501610e5485610d90565b805f5b85811015610e8f5784840389528151610e708582610e0f565b9450610e7b83610e22565b925060208a01995050600181019050610e57565b50829750879550505050505092915050565b5f6020820190508181035f830152610eb98184610e2e565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610eea82610ec1565b9050919050565b610efa81610ee0565b8114610f04575f5ffd5b50565b5f81359050610f1581610ef1565b92915050565b5f5f83601f840112610f3057610f2f610c42565b5b8235905067ffffffffffffffff811115610f4d57610f4c610c46565b5b602083019150836001820283011115610f6957610f68610c4a565b5b9250929050565b5f5f5f60408486031215610f8757610f86610c3a565b5b5f610f9486828701610f07565b935050602084013567ffffffffffffffff811115610fb557610fb4610c3e565b5b610fc186828701610f1b565b92509250509250925092565b5f82825260208201905092915050565b5f610fe782610d9f565b610ff18185610fcd565b9350611001818560208601610db9565b61100a81610dc7565b840191505092915050565b5f6020820190508181035f83015261102d8184610fdd565b905092915050565b61103e81610ee0565b82525050565b5f6020820190506110575f830184611035565b92915050565b5f6020828403121561107257611071610c3a565b5b5f61107f84828501610f07565b91505092915050565b5f819050919050565b61109a81611088565b81146110a4575f5ffd5b50565b5f813590506110b581611091565b92915050565b5f5f5f5f606085870312156110d3576110d2610c3a565b5b5f6110e087828801610f07565b945050602085013567ffffffffffffffff81111561110157611100610c3e565b5b61110d87828801610f1b565b93509350506040611120878288016110a7565b91505092959194509250565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f5ffd5b5f5ffd5b5f5ffd5b5f5f833560016020038436030381126111ae576111ad611186565b5b80840192508235915067ffffffffffffffff8211156111d0576111cf61118a565b5b6020830192506001820236038313156111ec576111eb61118e565b5b509250929050565b5f81905092915050565b828183375f83830152505050565b5f61121783856111f4565b93506112248385846111fe565b82840190509392505050565b5f61123c82848661120c565b91508190509392505050565b5f6112538385610fcd565b93506112608385846111fe565b61126983610dc7565b840190509392505050565b5f6040820190508181035f83015261128d818587611248565b905081810360208301526112a18184610fdd565b905094935050505056"); /// Build a genesis alloc entry for `AdminProxy`. -pub(crate) fn build(config: &AdminProxyConfig) -> GenesisContract { +pub fn build(config: &AdminProxyConfig) -> GenesisContract { let mut storage = BTreeMap::new(); // Slot 0: owner (address left-padded to 32 bytes) diff --git a/bin/ev-deployer/src/contracts/fee_vault.rs b/bin/ev-deployer/src/contracts/fee_vault.rs index c99bd39..0fad50e 100644 --- a/bin/ev-deployer/src/contracts/fee_vault.rs +++ b/bin/ev-deployer/src/contracts/fee_vault.rs @@ -9,7 +9,7 @@ use std::collections::BTreeMap; const FEE_VAULT_BYTECODE: &[u8] = &hex!("608060405260043610610101575f3560e01c80636cb53e1611610094578063bb0c829811610063578063bb0c8298146102dc578063c3f909d414610306578063eeb4a9c814610337578063f2fde38b1461035f578063f63188b71461038757610108565b80636cb53e16146102565780637d57d97a1461027e5780638da5cb5b1461028857806390321e1a146102b257610108565b806339bb1c5b116100d057806339bb1c5b146101ae5780634cebdc49146101d85780635aff5999146102025780635c4a6d841461022c57610108565b80631636b3681461010c57806326465826146101345780632858c55a1461015c5780632c2d80891461018657610108565b3661010857005b5f5ffd5b348015610117575f5ffd5b50610132600480360381019061012d919061117f565b6103af565b005b34801561013f575f5ffd5b5061015a600480360381019061015591906111dd565b610526565b005b348015610167575f5ffd5b506101706105f6565b60405161017d9190611226565b60405180910390f35b348015610191575f5ffd5b506101ac60048036038101906101a7919061129c565b61060c565b005b3480156101b9575f5ffd5b506101c2610700565b6040516101cf9190611335565b60405180910390f35b3480156101e3575f5ffd5b506101ec610724565b6040516101f9919061135d565b60405180910390f35b34801561020d575f5ffd5b50610216610749565b6040516102239190611385565b60405180910390f35b348015610237575f5ffd5b5061024061074f565b60405161024d91906113ad565b60405180910390f35b348015610261575f5ffd5b5061027c6004803603810190610277919061117f565b610755565b005b6102866108cb565b005b348015610293575f5ffd5b5061029c610caa565b6040516102a9919061135d565b60405180910390f35b3480156102bd575f5ffd5b506102c6610ccf565b6040516102d391906113ad565b60405180910390f35b3480156102e7575f5ffd5b506102f0610cd5565b6040516102fd91906113ad565b60405180910390f35b348015610311575f5ffd5b5061031a610cdb565b60405161032e9897969594939291906113c6565b60405180910390f35b348015610342575f5ffd5b5061035d600480360381019061035891906111dd565b610d81565b005b34801561036a575f5ffd5b506103856004803603810190610380919061117f565b610e51565b005b348015610392575f5ffd5b506103ad60048036038101906103a891906111dd565b61100c565b005b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461043e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610435906114c2565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036104ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104a39061152a565b60405180910390fd5b8060055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fa50c88d04012de3892b47d81943c983dc2690cfb81f0428eaa7d382f95683e4a8160405161051b919061135d565b60405180910390a150565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ac906114c2565b60405180910390fd5b806004819055507f63a8f7442c91b7117b3f235d24793c034fd752a01266bef3ef1d051efb56ca3d816040516105eb91906113ad565b60405180910390a150565b600160149054906101000a900463ffffffff1681565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461069b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610692906114c2565b60405180910390fd5b81600160146101000a81548163ffffffff021916908363ffffffff160217905550806002819055507fcac2c3add78f132121267d80a684a62d521a9799fd8434bd0da1a27c491b044982826040516106f4929190611548565b60405180910390a15050565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60025481565b60065481565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107db906114c2565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610852576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108499061152a565b60405180910390fd5b805f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f6eedba6e0a60268e3d78633f8822cea5dc75430d531f96fb46a29333834665c6816040516108c0919061135d565b60405180910390a150565b5f73ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610959576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610950906115b9565b60405180910390fd5b60045434101561099e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099590611621565b60405180910390fd5b5f4790505f612710600654836109b4919061166c565b6109be91906116da565b90505f81836109cd919061170a565b9050600354821015610a14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0b90611787565b60405180910390fd5b7f50ecfcc47f2c5b2a26f91422abf650476ec7f701c48b1cf6d1d6d4d51a872ed6838383604051610a47939291906117a5565b60405180910390a15f811115610bb1575f73ffffffffffffffffffffffffffffffffffffffff1660055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610ae6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9061184a565b60405180910390fd5b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682604051610b2c90611895565b5f6040518083038185875af1925050503d805f8114610b66576040519150601f19603f3d011682016040523d82523d5f602084013e610b6b565b606091505b5050905080610baf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba6906118f3565b60405180910390fd5b505b5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381b4e8b484600160149054906101000a900463ffffffff16600254876040518563ffffffff1660e01b8152600401610c2493929190611911565b60206040518083038185885af1158015610c40573d5f5f3e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190610c65919061195a565b90507f301fb78c068680a9fb5daa4ebadf5914ddc3a317f1fdc2c97f32740374d61e748360025483604051610c9c93929190611985565b60405180910390a150505050565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60045481565b60035481565b5f5f5f5f5f5f5f5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160149054906101000a900463ffffffff1660025460035460045460065460055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16975097509750975097509750975097509091929394959697565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e07906114c2565b60405180910390fd5b806003819055507f6ea576632a91ef2f8d4ee43600561b386f3c0254692977f0d33e17742bc5355881604051610e4691906113ad565b60405180910390a150565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ee0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed7906114c2565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610f4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f4590611a2a565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a38060015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461109b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611092906114c2565b60405180910390fd5b6127108111156110e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d790611a92565b60405180910390fd5b806006819055507fa8da92ecf88f6d9f058e5f86d614520d5f20a3ecf87914deb605f649bd63de878160405161111691906113ad565b60405180910390a150565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61114e82611125565b9050919050565b61115e81611144565b8114611168575f5ffd5b50565b5f8135905061117981611155565b92915050565b5f6020828403121561119457611193611121565b5b5f6111a18482850161116b565b91505092915050565b5f819050919050565b6111bc816111aa565b81146111c6575f5ffd5b50565b5f813590506111d7816111b3565b92915050565b5f602082840312156111f2576111f1611121565b5b5f6111ff848285016111c9565b91505092915050565b5f63ffffffff82169050919050565b61122081611208565b82525050565b5f6020820190506112395f830184611217565b92915050565b61124881611208565b8114611252575f5ffd5b50565b5f813590506112638161123f565b92915050565b5f819050919050565b61127b81611269565b8114611285575f5ffd5b50565b5f8135905061129681611272565b92915050565b5f5f604083850312156112b2576112b1611121565b5b5f6112bf85828601611255565b92505060206112d085828601611288565b9150509250929050565b5f819050919050565b5f6112fd6112f86112f384611125565b6112da565b611125565b9050919050565b5f61130e826112e3565b9050919050565b5f61131f82611304565b9050919050565b61132f81611315565b82525050565b5f6020820190506113485f830184611326565b92915050565b61135781611144565b82525050565b5f6020820190506113705f83018461134e565b92915050565b61137f81611269565b82525050565b5f6020820190506113985f830184611376565b92915050565b6113a7816111aa565b82525050565b5f6020820190506113c05f83018461139e565b92915050565b5f610100820190506113da5f83018b61134e565b6113e7602083018a611217565b6113f46040830189611376565b611401606083018861139e565b61140e608083018761139e565b61141b60a083018661139e565b61142860c083018561134e565b61143560e083018461134e565b9998505050505050505050565b5f82825260208201905092915050565b7f4665655661756c743a2063616c6c6572206973206e6f7420746865206f776e655f8201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b5f6114ac602183611442565b91506114b782611452565b604082019050919050565b5f6020820190508181035f8301526114d9816114a0565b9050919050565b7f4665655661756c743a207a65726f2061646472657373000000000000000000005f82015250565b5f611514601683611442565b915061151f826114e0565b602082019050919050565b5f6020820190508181035f83015261154181611508565b9050919050565b5f60408201905061155b5f830185611217565b6115686020830184611376565b9392505050565b7f4665655661756c743a206d696e746572206e6f742073657400000000000000005f82015250565b5f6115a3601883611442565b91506115ae8261156f565b602082019050919050565b5f6020820190508181035f8301526115d081611597565b9050919050565b7f4665655661756c743a20696e73756666696369656e74206665650000000000005f82015250565b5f61160b601a83611442565b9150611616826115d7565b602082019050919050565b5f6020820190508181035f830152611638816115ff565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611676826111aa565b9150611681836111aa565b925082820261168f816111aa565b915082820484148315176116a6576116a561163f565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6116e4826111aa565b91506116ef836111aa565b9250826116ff576116fe6116ad565b5b828204905092915050565b5f611714826111aa565b915061171f836111aa565b92508282039050818111156117375761173661163f565b5b92915050565b7f4665655661756c743a206d696e696d756d20616d6f756e74206e6f74206d65745f82015250565b5f611771602083611442565b915061177c8261173d565b602082019050919050565b5f6020820190508181035f83015261179e81611765565b9050919050565b5f6060820190506117b85f83018661139e565b6117c5602083018561139e565b6117d2604083018461139e565b949350505050565b7f4665655661756c743a206f7468657220726563697069656e74206e6f742073655f8201527f7400000000000000000000000000000000000000000000000000000000000000602082015250565b5f611834602183611442565b915061183f826117da565b604082019050919050565b5f6020820190508181035f83015261186181611828565b9050919050565b5f81905092915050565b50565b5f6118805f83611868565b915061188b82611872565b5f82019050919050565b5f61189f82611875565b9150819050919050565b7f4665655661756c743a207472616e73666572206661696c6564000000000000005f82015250565b5f6118dd601983611442565b91506118e8826118a9565b602082019050919050565b5f6020820190508181035f83015261190a816118d1565b9050919050565b5f6060820190506119245f830186611217565b6119316020830185611376565b61193e604083018461139e565b949350505050565b5f8151905061195481611272565b92915050565b5f6020828403121561196f5761196e611121565b5b5f61197c84828501611946565b91505092915050565b5f6060820190506119985f83018661139e565b6119a56020830185611376565b6119b26040830184611376565b949350505050565b7f4665655661756c743a206e6577206f776e657220697320746865207a65726f205f8201527f6164647265737300000000000000000000000000000000000000000000000000602082015250565b5f611a14602783611442565b9150611a1f826119ba565b604082019050919050565b5f6020820190508181035f830152611a4181611a08565b9050919050565b7f4665655661756c743a20696e76616c69642062707300000000000000000000005f82015250565b5f611a7c601583611442565b9150611a8782611a48565b602082019050919050565b5f6020820190508181035f830152611aa981611a70565b905091905056"); /// Build a genesis alloc entry for `FeeVault`. -pub(crate) fn build(config: &FeeVaultConfig) -> GenesisContract { +pub fn build(config: &FeeVaultConfig) -> GenesisContract { let mut storage = BTreeMap::new(); // Apply constructor default: bps 0 -> 10000 diff --git a/bin/ev-deployer/src/contracts/immutables.rs b/bin/ev-deployer/src/contracts/immutables.rs index 40c75f4..1d97624 100644 --- a/bin/ev-deployer/src/contracts/immutables.rs +++ b/bin/ev-deployer/src/contracts/immutables.rs @@ -10,7 +10,7 @@ use alloy_primitives::{Address, B256, U256}; /// A single immutable reference inside a bytecode blob. #[derive(Debug, Clone, Copy)] -pub(crate) struct ImmutableRef { +pub struct ImmutableRef { /// Byte offset into the **runtime** bytecode. pub start: usize, /// Number of bytes (always 32 for EVM words). @@ -22,7 +22,7 @@ pub(crate) struct ImmutableRef { /// # Panics /// /// Panics if any reference extends past the end of `bytecode`. -pub(crate) fn patch_bytes(bytecode: &mut [u8], refs: &[ImmutableRef], value: &[u8; 32]) { +pub fn patch_bytes(bytecode: &mut [u8], refs: &[ImmutableRef], value: &[u8; 32]) { for r in refs { assert!( r.start + r.length <= bytecode.len(), @@ -36,19 +36,19 @@ pub(crate) fn patch_bytes(bytecode: &mut [u8], refs: &[ImmutableRef], value: &[u } /// Convenience: patch with an ABI-encoded `address` (left-padded to 32 bytes). -pub(crate) fn patch_address(bytecode: &mut [u8], refs: &[ImmutableRef], addr: Address) { +pub fn patch_address(bytecode: &mut [u8], refs: &[ImmutableRef], addr: Address) { let word: B256 = B256::from(U256::from_be_bytes(addr.into_word().0)); patch_bytes(bytecode, refs, &word.0); } /// Convenience: patch with an ABI-encoded `uint32` (left-padded to 32 bytes). -pub(crate) fn patch_u32(bytecode: &mut [u8], refs: &[ImmutableRef], val: u32) { +pub fn patch_u32(bytecode: &mut [u8], refs: &[ImmutableRef], val: u32) { let word = B256::from(U256::from(val)); patch_bytes(bytecode, refs, &word.0); } /// Convenience: patch with an ABI-encoded `uint256`. -pub(crate) fn patch_u256(bytecode: &mut [u8], refs: &[ImmutableRef], val: U256) { +pub fn patch_u256(bytecode: &mut [u8], refs: &[ImmutableRef], val: U256) { let word = B256::from(val); patch_bytes(bytecode, refs, &word.0); } diff --git a/bin/ev-deployer/src/contracts/mailbox.rs b/bin/ev-deployer/src/contracts/mailbox.rs index 4f77458..3de51d5 100644 --- a/bin/ev-deployer/src/contracts/mailbox.rs +++ b/bin/ev-deployer/src/contracts/mailbox.rs @@ -74,7 +74,7 @@ const LOCAL_DOMAIN_REFS: &[ImmutableRef] = &[ ]; /// Build a genesis alloc entry for `Mailbox`. -pub(crate) fn build(config: &MailboxConfig, local_domain: u32) -> GenesisContract { +pub fn build(config: &MailboxConfig, local_domain: u32) -> GenesisContract { let mut bytecode = MAILBOX_BYTECODE.to_vec(); // Patch immutables diff --git a/bin/ev-deployer/src/contracts/merkle_tree_hook.rs b/bin/ev-deployer/src/contracts/merkle_tree_hook.rs index 0723ada..8ba8b2c 100644 --- a/bin/ev-deployer/src/contracts/merkle_tree_hook.rs +++ b/bin/ev-deployer/src/contracts/merkle_tree_hook.rs @@ -77,7 +77,7 @@ const LOCAL_DOMAIN_REFS: &[ImmutableRef] = &[ImmutableRef { }]; /// Build a genesis alloc entry for `MerkleTreeHook`. -pub(crate) fn build(config: &MerkleTreeHookConfig, local_domain: u32) -> GenesisContract { +pub fn build(config: &MerkleTreeHookConfig, local_domain: u32) -> GenesisContract { let mut bytecode = MERKLE_TREE_HOOK_BYTECODE.to_vec(); // Patch immutables diff --git a/bin/ev-deployer/src/contracts/mod.rs b/bin/ev-deployer/src/contracts/mod.rs index 72b5fca..3e7c12d 100644 --- a/bin/ev-deployer/src/contracts/mod.rs +++ b/bin/ev-deployer/src/contracts/mod.rs @@ -1,19 +1,20 @@ //! Contract bytecode and storage encoding. -pub(crate) mod admin_proxy; -pub(crate) mod fee_vault; -pub(crate) mod immutables; -pub(crate) mod mailbox; -pub(crate) mod merkle_tree_hook; -pub(crate) mod noop_ism; -pub(crate) mod permit2; -pub(crate) mod protocol_fee; +pub mod admin_proxy; +pub mod fee_vault; +pub mod immutables; +pub mod mailbox; +pub mod merkle_tree_hook; +pub mod noop_ism; +pub mod permit2; +pub mod protocol_fee; use alloy_primitives::{Address, Bytes, B256}; use std::collections::BTreeMap; /// A contract ready to be placed in genesis alloc. -pub(crate) struct GenesisContract { +#[derive(Debug)] +pub struct GenesisContract { /// The address to deploy at. pub address: Address, /// Runtime bytecode. diff --git a/bin/ev-deployer/src/contracts/noop_ism.rs b/bin/ev-deployer/src/contracts/noop_ism.rs index 9f17efe..51d7f94 100644 --- a/bin/ev-deployer/src/contracts/noop_ism.rs +++ b/bin/ev-deployer/src/contracts/noop_ism.rs @@ -27,7 +27,7 @@ use std::collections::BTreeMap; const NOOP_ISM_BYTECODE: &[u8] = &hex!("608060405234801561001057600080fd5b50600436106100415760003560e01c80636465e69f1461004657806393c4484714610065578063f7e83aee146100ae575b600080fd5b61004e600681565b60405160ff90911681526020015b60405180910390f35b6100a16040518060400160405280600681526020017f31312e302e33000000000000000000000000000000000000000000000000000081525081565b60405161005c91906100d6565b6100c66100bc36600461018c565b6001949350505050565b604051901515815260200161005c565b60006020808352835180602085015260005b81811015610104578581018301518582016040015282016100e8565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60008083601f84011261015557600080fd5b50813567ffffffffffffffff81111561016d57600080fd5b60208301915083602082850101111561018557600080fd5b9250929050565b600080600080604085870312156101a257600080fd5b843567ffffffffffffffff808211156101ba57600080fd5b6101c688838901610143565b909650945060208701359150808211156101df57600080fd5b506101ec87828801610143565b9598949750955050505056"); /// Build a genesis alloc entry for `NoopIsm`. -pub(crate) fn build(config: &NoopIsmConfig) -> GenesisContract { +pub fn build(config: &NoopIsmConfig) -> GenesisContract { GenesisContract { address: config.address, code: Bytes::from(NOOP_ISM_BYTECODE.to_vec()), diff --git a/bin/ev-deployer/src/contracts/permit2.rs b/bin/ev-deployer/src/contracts/permit2.rs index ee56f85..00a1380 100644 --- a/bin/ev-deployer/src/contracts/permit2.rs +++ b/bin/ev-deployer/src/contracts/permit2.rs @@ -68,7 +68,7 @@ const HASHED_NAME: B256 = B256::new(hex!( )); /// Build a genesis alloc entry for `Permit2`. -pub(crate) fn build(config: &Permit2Config, chain_id: u64) -> GenesisContract { +pub fn build(config: &Permit2Config, chain_id: u64) -> GenesisContract { let mut bytecode = PERMIT2_BYTECODE.to_vec(); // Patch _CACHED_CHAIN_ID diff --git a/bin/ev-deployer/src/contracts/protocol_fee.rs b/bin/ev-deployer/src/contracts/protocol_fee.rs index d7b2135..5d80d2d 100644 --- a/bin/ev-deployer/src/contracts/protocol_fee.rs +++ b/bin/ev-deployer/src/contracts/protocol_fee.rs @@ -56,7 +56,7 @@ const MAX_PROTOCOL_FEE_REFS: &[ImmutableRef] = &[ ]; /// Build a genesis alloc entry for `ProtocolFee`. -pub(crate) fn build(config: &ProtocolFeeConfig) -> GenesisContract { +pub fn build(config: &ProtocolFeeConfig) -> GenesisContract { let mut bytecode = PROTOCOL_FEE_BYTECODE.to_vec(); // Patch immutables diff --git a/bin/ev-deployer/src/genesis.rs b/bin/ev-deployer/src/genesis.rs index 05b9fd4..59cc6bf 100644 --- a/bin/ev-deployer/src/genesis.rs +++ b/bin/ev-deployer/src/genesis.rs @@ -9,7 +9,7 @@ use serde_json::{Map, Value}; use std::path::Path; /// Build the alloc JSON from config. -pub(crate) fn build_alloc(config: &DeployConfig) -> Value { +pub fn build_alloc(config: &DeployConfig) -> Value { let mut alloc = Map::new(); if let Some(ref ap_config) = config.contracts.admin_proxy { @@ -53,14 +53,15 @@ pub(crate) fn build_alloc(config: &DeployConfig) -> Value { } /// Build alloc and merge into an existing genesis JSON file. -pub(crate) fn merge_into( - config: &DeployConfig, - genesis_path: &Path, - force: bool, -) -> eyre::Result { +pub fn merge_into(config: &DeployConfig, genesis_path: &Path, force: bool) -> eyre::Result { let content = std::fs::read_to_string(genesis_path)?; let mut genesis: Value = serde_json::from_str(&content)?; + merge_alloc(config, &mut genesis, force)?; + Ok(genesis) +} +/// Merge deployer contracts into a genesis JSON value in memory. +pub fn merge_alloc(config: &DeployConfig, genesis: &mut Value, force: bool) -> eyre::Result<()> { let alloc = build_alloc(config); let genesis_alloc = genesis @@ -76,7 +77,7 @@ pub(crate) fn merge_into( genesis_alloc.insert(addr.clone(), entry.clone()); } - Ok(genesis) + Ok(()) } fn insert_contract(alloc: &mut Map, contract: &GenesisContract) { diff --git a/bin/ev-deployer/src/lib.rs b/bin/ev-deployer/src/lib.rs new file mode 100644 index 0000000..08bca34 --- /dev/null +++ b/bin/ev-deployer/src/lib.rs @@ -0,0 +1,9 @@ +//! EV Deployer — genesis alloc generator for ev-reth contracts. +//! +//! This crate provides both a CLI tool and a library for generating genesis +//! alloc entries from declarative TOML configurations. + +pub mod config; +pub mod contracts; +pub mod genesis; +pub mod output; diff --git a/bin/ev-deployer/src/main.rs b/bin/ev-deployer/src/main.rs index a5e6e3d..feda28f 100644 --- a/bin/ev-deployer/src/main.rs +++ b/bin/ev-deployer/src/main.rs @@ -1,11 +1,7 @@ //! EV Deployer — genesis alloc generator for ev-reth contracts. -mod config; -mod contracts; -mod genesis; -mod output; - use clap::{Parser, Subcommand}; +use ev_deployer::{config, genesis, output}; use std::path::PathBuf; /// EV Deployer: generate genesis alloc entries for ev-reth contracts. diff --git a/bin/ev-deployer/src/output.rs b/bin/ev-deployer/src/output.rs index 5e97dd4..47b5a09 100644 --- a/bin/ev-deployer/src/output.rs +++ b/bin/ev-deployer/src/output.rs @@ -4,7 +4,7 @@ use crate::config::DeployConfig; use serde_json::{Map, Value}; /// Build an address manifest JSON from config. -pub(crate) fn build_manifest(config: &DeployConfig) -> Value { +pub fn build_manifest(config: &DeployConfig) -> Value { let mut manifest = Map::new(); if let Some(ref ap) = config.contracts.admin_proxy { diff --git a/bin/ev-dev/Cargo.toml b/bin/ev-dev/Cargo.toml index 99a72d1..5a10743 100644 --- a/bin/ev-dev/Cargo.toml +++ b/bin/ev-dev/Cargo.toml @@ -15,6 +15,7 @@ path = "src/main.rs" [dependencies] # Core evolve crates ev-node = { path = "../../crates/node" } +ev-deployer = { path = "../ev-deployer" } evolve-ev-reth = { path = "../../crates/evolve" } # Reth CLI and core dependencies diff --git a/bin/ev-dev/src/main.rs b/bin/ev-dev/src/main.rs index 7ed4e65..6eeef39 100644 --- a/bin/ev-dev/src/main.rs +++ b/bin/ev-dev/src/main.rs @@ -7,12 +7,13 @@ use alloy_signer_local::{coins_bip39::English, MnemonicBuilder}; use clap::Parser; +use ev_deployer::{config::DeployConfig, genesis::merge_alloc, output::build_manifest}; use evolve_ev_reth::{ config::EvolveConfig, rpc::txpool::{EvolveTxpoolApiImpl, EvolveTxpoolApiServer}, }; use reth_ethereum_cli::Cli; -use std::io::Write; +use std::{io::Write, path::PathBuf}; use tracing::info; use ev_node::{EvolveArgs, EvolveChainSpecParser, EvolveNode}; @@ -55,6 +56,10 @@ struct EvDevArgs { /// Number of accounts to display (1..=20) #[arg(long, default_value_t = 10, value_parser = parse_accounts)] accounts: usize, + + /// Path to an ev-deployer TOML config to deploy contracts at genesis. + #[arg(long, value_name = "PATH")] + deploy_config: Option, } fn derive_keys(count: usize) -> Vec<(String, String)> { @@ -84,7 +89,7 @@ fn chain_id_from_genesis() -> u64 { .expect("genesis must have config.chainId") } -fn print_banner(args: &EvDevArgs) { +fn print_banner(args: &EvDevArgs, deploy_cfg: Option<&DeployConfig>) { let accounts = derive_keys(args.accounts); println!(); @@ -124,6 +129,20 @@ fn print_banner(args: &EvDevArgs) { println!("Mnemonic: {HARDHAT_MNEMONIC}"); println!("Derivation path: m/44'/60'/0'/0/{{index}}"); println!(); + + if let Some(cfg) = deploy_cfg { + let config_path = args.deploy_config.as_ref().unwrap(); + println!("Genesis Contracts (from {})", config_path.display()); + println!("=================="); + let manifest = build_manifest(cfg); + if let Some(obj) = manifest.as_object() { + for (name, addr) in obj { + println!(" {name:20} {addr}"); + } + } + println!(); + } + println!("WARNING: These accounts and keys are publicly known."); println!("Any funds sent to them on mainnet WILL BE LOST."); println!(); @@ -138,15 +157,39 @@ fn main() { let dev_args = EvDevArgs::parse(); + let deploy_cfg = dev_args.deploy_config.as_ref().map(|config_path| { + let mut cfg = DeployConfig::load(config_path) + .unwrap_or_else(|e| panic!("failed to load deploy config: {e}")); + + let genesis_chain_id = chain_id_from_genesis(); + if cfg.chain.chain_id != genesis_chain_id { + eprintln!( + "WARNING: deploy config chain_id ({}) differs from devnet genesis ({}), overriding to {}", + cfg.chain.chain_id, genesis_chain_id, genesis_chain_id + ); + cfg.chain.chain_id = genesis_chain_id; + } + cfg + }); + if !dev_args.silent { - print_banner(&dev_args); + print_banner(&dev_args, deploy_cfg.as_ref()); } + let genesis_json = if let Some(ref cfg) = deploy_cfg { + let mut genesis: serde_json::Value = + serde_json::from_str(DEVNET_GENESIS).expect("valid genesis JSON"); + merge_alloc(cfg, &mut genesis, true).expect("failed to merge deploy config into genesis"); + serde_json::to_string(&genesis).expect("failed to serialize merged genesis") + } else { + DEVNET_GENESIS.to_string() + }; + // Write genesis to a temp file that lives for the process duration let mut genesis_file = tempfile::NamedTempFile::new().expect("failed to create temp genesis file"); genesis_file - .write_all(DEVNET_GENESIS.as_bytes()) + .write_all(genesis_json.as_bytes()) .expect("failed to write genesis"); let genesis_path = genesis_file .path() diff --git a/justfile b/justfile index 757a5b9..941833a 100644 --- a/justfile +++ b/justfile @@ -38,6 +38,14 @@ build-all: build-deployer: {{cargo}} build --release --bin ev-deployer +# Install ev-dev to ~/.cargo/bin +install-ev-dev: + {{cargo}} install --path bin/ev-dev + +# Install ev-deployer to ~/.cargo/bin +install-ev-deployer: + {{cargo}} install --path bin/ev-deployer + # Testing ────────────────────────────────────────────── # Run all tests From 911e2179b877d7b226136b9833bed7d22c3495b1 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 19 Mar 2026 21:47:31 +0100 Subject: [PATCH 2/2] docs(ev-dev): add genesis contract deployment usage to README --- bin/ev-dev/README.md | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/bin/ev-dev/README.md b/bin/ev-dev/README.md index 39a615f..731a6e2 100644 --- a/bin/ev-dev/README.md +++ b/bin/ev-dev/README.md @@ -28,6 +28,7 @@ ev-dev [OPTIONS] | `--block-time` | `1` | Block time in seconds (`0` = mine on transaction) | | `--silent` | `false` | Suppress the startup banner | | `--accounts` | `10` | Number of accounts to display (1-20) | +| `--deploy-config` | — | Path to an ev-deployer TOML config to deploy contracts at genesis | ### Examples @@ -40,8 +41,38 @@ ev-dev --host 0.0.0.0 # Custom port, faster blocks ev-dev --port 9545 --block-time 2 + +# Start with genesis contracts deployed +ev-dev --deploy-config bin/ev-deployer/examples/devnet.toml ``` +## Genesis Contract Deployment + +You can deploy contracts into the genesis state by passing a `--deploy-config` flag pointing to an [ev-deployer](../ev-deployer/README.md) TOML config file. + +```bash +ev-dev --deploy-config path/to/deploy.toml +``` + +When a deploy config is provided, ev-dev will: + +1. Load and validate the config +2. Override the config's `chain_id` to match the devnet genesis (a warning is printed if they differ) +3. Merge the contract alloc entries into the genesis state before starting the node +4. Print the deployed contract addresses in the startup banner + +The startup banner will show an extra section: + +``` +Genesis Contracts (from path/to/deploy.toml) +================== + admin_proxy "0x000000000000000000000000000000000000Ad00" + fee_vault "0x000000000000000000000000000000000000FE00" + ... +``` + +See the [ev-deployer README](../ev-deployer/README.md) for full config reference and available contracts. + ## Chain Details | Property | Value | @@ -204,9 +235,10 @@ ev-dev includes all Evolve customizations out of the box: ev-dev is a thin wrapper around the full `ev-reth` node. On startup it: -1. Writes the embedded devnet genesis to a temp file -2. Creates a temporary data directory (clean state every run) -3. Launches `ev-reth` in `--dev` mode with networking disabled -4. Exposes HTTP and WebSocket RPC on the configured host/port +1. If `--deploy-config` is provided, loads the config and merges contract alloc entries into the genesis +2. Writes the (possibly extended) devnet genesis to a temp file +3. Creates a temporary data directory (clean state every run) +4. Launches `ev-reth` in `--dev` mode with networking disabled +5. Exposes HTTP and WebSocket RPC on the configured host/port Each run starts from a fresh genesis — there is no persistent state between restarts.