Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions bin/ev-deployer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -18,14 +18,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, Default)]
pub(crate) struct ContractsConfig {
pub struct ContractsConfig {
/// `AdminProxy` contract config (optional).
pub admin_proxy: Option<AdminProxyConfig>,
/// `Permit2` contract config (optional).
Expand All @@ -34,7 +34,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.
Expand All @@ -43,14 +43,14 @@ pub(crate) struct AdminProxyConfig {

/// `Permit2` configuration (Uniswap token approval manager).
#[derive(Debug, Deserialize)]
pub(crate) struct Permit2Config {
pub struct Permit2Config {
/// 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> {
pub fn load(path: &Path) -> eyre::Result<Self> {
let content = std::fs::read_to_string(path)?;
let config: Self = toml::from_str(&content)?;
config.validate()?;
Expand Down
2 changes: 1 addition & 1 deletion bin/ev-deployer/src/contracts/admin_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions bin/ev-deployer/src/contracts/immutables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use alloy_primitives::{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).
Expand All @@ -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(),
Expand All @@ -36,7 +36,7 @@ pub(crate) fn patch_bytes(bytecode: &mut [u8], refs: &[ImmutableRef], value: &[u
}

/// 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);
}
Expand Down
9 changes: 5 additions & 4 deletions bin/ev-deployer/src/contracts/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
//! Contract bytecode and storage encoding.

pub(crate) mod admin_proxy;
pub(crate) mod immutables;
pub(crate) mod permit2;
pub mod admin_proxy;
pub mod immutables;
pub mod permit2;

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.
Expand Down
2 changes: 1 addition & 1 deletion bin/ev-deployer/src/contracts/permit2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 8 additions & 7 deletions bin/ev-deployer/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -26,14 +26,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<Value> {
pub fn merge_into(config: &DeployConfig, genesis_path: &Path, force: bool) -> eyre::Result<Value> {
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
Expand All @@ -57,7 +58,7 @@ pub(crate) fn merge_into(
genesis_alloc.insert(canonical, entry.clone());
}

Ok(genesis)
Ok(())
}

fn normalize_addr(addr: &str) -> String {
Expand Down
9 changes: 9 additions & 0 deletions bin/ev-deployer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
6 changes: 1 addition & 5 deletions bin/ev-deployer/src/main.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
2 changes: 1 addition & 1 deletion bin/ev-deployer/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions bin/ev-dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 36 additions & 4 deletions bin/ev-dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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 |
Expand Down Expand Up @@ -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.
Loading
Loading