Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
89eccaa
feat: add ev-deployer CLI for genesis contract allocation
randygrok Mar 13, 2026
0c8f54e
test: add bytecode verification tests for ev-deployer contracts
randygrok Mar 13, 2026
2ba2b80
docs: add ev-deployer README with config and usage guide
randygrok Mar 13, 2026
a540858
fix(ci): serialize bytecode verification tests to avoid solc race con…
randygrok Mar 13, 2026
b9e2670
style: apply cargo fmt to ev-deployer
randygrok Mar 13, 2026
18ed817
ci(ev-deployer): split workflow into separate bytecode and unit test …
randygrok Mar 13, 2026
f7d0e71
style: fix fmt and clippy lint errors in ev-deployer
randygrok Mar 16, 2026
46ea9a6
feat(ev-deployer): add MerkleTreeHook contract with immutable bytecod…
randygrok Mar 18, 2026
e5f4eb9
Merge branch 'main' into ev-deployer-part1-core
randygrok Mar 18, 2026
be1b241
Merge remote-tracking branch 'origin/main' into ev-deployer-part1-core
randygrok Mar 19, 2026
7e19222
ci(ev-deployer): add e2e genesis test to CI workflow
randygrok Mar 19, 2026
e9fa70e
Merge remote-tracking branch 'origin/ev-deployer-part1-core' into ev-…
randygrok Mar 19, 2026
946026d
ci(ev-deployer): install soldeer deps before bytecode verification
randygrok Mar 19, 2026
9dd5011
test(ev-deployer): add MerkleTreeHook verification to e2e genesis test
randygrok Mar 19, 2026
217be0c
fix(ev-deployer): escape brackets in doc comments to fix rustdoc
randygrok Mar 19, 2026
67151c3
feat(ev-deployer): add Permit2 contract support
randygrok Mar 19, 2026
56548ec
docs(ev-deployer): add comment explaining canonical Permit2 address
randygrok Mar 19, 2026
fa8a428
merge: resolve e2e test conflicts with ev-deployer-merkle-tree-hook
randygrok Mar 19, 2026
bfa5a23
style(ev-deployer): fix fmt, clippy and rustdoc warnings in permit2
randygrok Mar 19, 2026
4da01ea
feat(ev-deployer): add Mailbox, NoopIsm, and ProtocolFee genesis cont…
randygrok Mar 19, 2026
3faa629
fix(ev-deployer): regenerate Mailbox and ProtocolFee bytecodes from c…
randygrok Mar 19, 2026
eb413d1
merge: resolve conflicts with ev-deployer-merkle-tree-hook (mailbox, …
jgimeno Mar 19, 2026
aeffc0d
fix(ev-deployer): address PR review feedback
jgimeno Mar 19, 2026
a2d194e
merge(ev-deployer): integrate ev-deployer-part1-core duplicate addres…
jgimeno Mar 19, 2026
e8a39f8
refactor(ev-deployer): remove FeeVault contract from part 1
randygrok Mar 24, 2026
089ef22
refactor(ev-deployer): remove AdminProxy contract from part 1
randygrok Mar 24, 2026
6b85563
Revert "refactor(ev-deployer): remove AdminProxy contract from part 1"
randygrok Mar 24, 2026
93b3eaa
fix(ev-deployer): make [contracts] section optional in config
randygrok Mar 24, 2026
70111fd
feat(ev-deployer): add init command to generate starter config
randygrok Mar 24, 2026
fa0e71f
fix(ev-deployer): clean up command ordering and stale fee_vault refer…
randygrok Mar 24, 2026
1acd3c8
docs(ev-deployer): document init command in README
randygrok Mar 24, 2026
cb838e8
merge(ev-deployer): integrate ev-deployer-part1-core keeping all cont…
randygrok Mar 24, 2026
ee68354
fix(ev-deployer): remove extra blank lines from merge to pass rustfmt
randygrok Mar 24, 2026
ef5ac9e
docs(ev-deployer): document all supported contracts in README and ini…
randygrok Mar 24, 2026
65bbf9e
fix(ev-deployer): normalize alloc keys for collision detection
randygrok Mar 24, 2026
08c9eb4
style(ev-deployer): fix fmt and clippy lint in genesis.rs
randygrok Mar 25, 2026
46b75bf
Merge remote-tracking branch 'origin/ev-deployer-part1-core' into ev-…
randygrok Mar 25, 2026
e365cfe
merge: resolve e2e test conflict with ev-deployer-merkle-tree-hook (p…
randygrok Mar 25, 2026
7f9e238
docs(ev-deployer): add Permit2 to init template and README
randygrok Mar 25, 2026
b1e5ae3
fix(ev-deployer): use case-insensitive grep in e2e genesis address ch…
randygrok Mar 25, 2026
5d2be71
refactor(ev-deployer): remove Hyperlane contracts, keep only AdminPro…
randygrok Mar 27, 2026
c32b633
merge: integrate main into ev-deployer-part3-permit2
randygrok Mar 27, 2026
04beb6b
refactor(contracts): remove Hyperlane dependency from FeeVault
randygrok Mar 27, 2026
c6e679b
style(contracts): fix forge fmt formatting
randygrok Mar 27, 2026
cae3723
docs: clarify FeeVault is optional, document when to use it vs plain …
randygrok Mar 27, 2026
4653ccc
fix(ev-deployer): validate permit2 zero-address and duplicate deploy …
randygrok Mar 30, 2026
221aa28
style(ev-deployer): remove unnecessary #[allow(dead_code)] from confi…
randygrok Mar 30, 2026
877c66b
chore(ev-deployer): add permit2 config tests and update contracts skill
randygrok Mar 30, 2026
588a46a
style(ev-deployer): fix rustfmt formatting in config.rs
randygrok Mar 30, 2026
8e8bf8c
docs(ev-deployer): use full canonical Permit2 address in config refer…
randygrok Mar 30, 2026
6070a3b
refactor(ev-deployer): make address optional in contract configs
randygrok Mar 30, 2026
3c74168
feat(ev-deployer): add initcode constants for live deployment
randygrok Mar 30, 2026
1f7e2cc
feat(ev-deployer): add CREATE2 address computation module
randygrok Mar 30, 2026
826c10d
feat(ev-deployer): add deploy state file with immutability checks
randygrok Mar 30, 2026
f9054b7
feat(ev-deployer): add ChainDeployer trait and LiveDeployer
randygrok Mar 30, 2026
2b90e82
feat(ev-deployer): add deploy pipeline with mock-tested flow
randygrok Mar 30, 2026
0c67446
feat(ev-deployer): wire up deploy subcommand in CLI
randygrok Mar 30, 2026
308ac0e
docs(ev-deployer): update init template for deploy mode
randygrok Mar 30, 2026
cbdaaa2
style(ev-deployer): fix rustfmt formatting
randygrok Mar 30, 2026
58dd78a
chore: update Cargo.lock for ev-deployer deploy dependencies
randygrok Mar 30, 2026
868bd3a
fix(ev-deployer): address clippy lints and nightly rustfmt imports
randygrok Mar 30, 2026
77c098b
fix(ev-deployer): remove AdminProxy from deploy pipeline
randygrok Mar 30, 2026
922af60
fix(ev-deployer): use atomic writes for deploy state file
randygrok Mar 30, 2026
bb35228
feat(ev-deployer): add CLI flags to init command
randygrok Mar 31, 2026
48a4d39
feat(ev-deployer): add template builder with parameterized tests
randygrok Mar 31, 2026
9771899
feat(ev-deployer): wire parameterized init into CLI
randygrok Mar 31, 2026
9c2fcb6
docs(ev-deployer): rewrite README as comprehensive user guide
randygrok Mar 31, 2026
71afcec
fix(ev-deployer): address clippy lints and rustfmt in init module
randygrok Mar 31, 2026
2b9485c
feat(ev-deployer): add deterministic deployer as genesis contract
randygrok Mar 31, 2026
0c324a2
style(ev-deployer): apply rustfmt to deterministic deployer
randygrok Apr 2, 2026
adf04f4
Merge branch 'main' into ev-deployer-part3-permit2
randygrok Apr 8, 2026
b3f746d
Merge remote-tracking branch 'origin/main' into ev-deployer-part3-per…
randygrok Apr 13, 2026
17bd295
docs: clarify callFee is zero-fee safe in FeeVault doc
randygrok Apr 13, 2026
a3beb2b
Merge branch 'ev-deployer-part3-permit2' into chipped-walker
randygrok Apr 14, 2026
35cee5f
fix(ev-deployer): make deterministic_deployer::build a const fn
randygrok Apr 14, 2026
0bb8cd5
feat(ev-deployer): part 4 – integrate ev-deployer into ev-dev (#183)
randygrok May 12, 2026
68f3529
Merge remote-tracking branch 'origin/main' into ev-deployer-part3a
randygrok May 12, 2026
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
7 changes: 7 additions & 0 deletions Cargo.lock

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

6 changes: 6 additions & 0 deletions bin/ev-deployer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@ authors.workspace = true

[dependencies]
alloy-primitives = { workspace = true, features = ["serde"] }
alloy = { workspace = true }
alloy-rpc-types-eth = { workspace = true }
alloy-signer-local = { workspace = true }
async-trait = { workspace = true }
tokio = { workspace = true }
clap = { workspace = true, features = ["derive", "env"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
toml = "0.9"
eyre = { workspace = true }
rand = { workspace = true }

[dev-dependencies]
tempfile = { workspace = true }
Expand Down
182 changes: 126 additions & 56 deletions bin/ev-deployer/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
# EV Deployer

CLI tool for generating genesis alloc entries for ev-reth contracts. It reads a declarative TOML config and produces the JSON needed to embed contracts into a chain's genesis state.
CLI tool for deploying ev-reth contracts. It reads a declarative TOML config and either embeds contracts into a chain's genesis state or deploys them to a live chain via CREATE2.

## Modes of Operation

EV Deployer has two deployment modes:

| Mode | When to use | What it does |
|------|-------------|-------------|
| **genesis** | Before the chain starts | Produces JSON alloc entries to embed contracts into the genesis state. No RPC needed. |
| **deploy** | On a running chain | Deploys contracts via CREATE2 through the deterministic deployer. Requires RPC + signer. |

Both modes read the same TOML config. The `address` field in each contract section is used by `genesis` to place the contract at that exact address. In `deploy` mode, addresses are computed deterministically via CREATE2 and the config `address` is ignored.

## Quick Start

```bash
# 1. Generate a config pre-populated for your chain
ev-deployer init --chain-id 42170 --permit2 --output deploy.toml

# 2a. Genesis mode: embed into genesis state
ev-deployer genesis --config deploy.toml --merge-into genesis.json --output genesis-out.json

# 2b. Deploy mode: deploy to a live chain
ev-deployer deploy \
--config deploy.toml \
--rpc-url http://localhost:8545 \
--private-key 0x... \
--state deploy-state.json
```

## Building

Expand All @@ -10,98 +38,140 @@ just build-deployer

The binary is output to `target/release/ev-deployer`.

## Configuration
## Commands

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.
### `init`

### Config reference
Generate a starter config file.

#### `[chain]`
```bash
# Bare template (all contracts commented out)
ev-deployer init

# Pre-populated with chain ID, Permit2, and deterministic deployer
ev-deployer init --chain-id 42170 --permit2 --deterministic-deployer

# Full config with all contracts
ev-deployer init \
--chain-id 42170 \
--permit2 \
--admin-proxy-owner 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 \
--output deploy.toml
```

| Field | Type | Description |
|------------|------|-------------|
| `chain_id` | u64 | Chain ID |
| Flag | Description |
|------|-------------|
| `--output <PATH>` | Write to file instead of stdout |
| `--chain-id <ID>` | Set the chain ID (defaults to 0) |
| `--permit2` | Enable Permit2 with its canonical address |
| `--deterministic-deployer` | Enable the deterministic deployer (Nick's factory) with its canonical address |
| `--admin-proxy-owner <ADDR>` | Enable AdminProxy with the given owner |

#### `[contracts.admin_proxy]`
### `genesis`

| Field | Type | Description |
|-----------|---------|---------------------------|
| `address` | address | Address to deploy at |
| `owner` | address | Owner (must not be zero) |
Generate genesis alloc JSON from a config.

#### `[contracts.permit2]`
```bash
# Print alloc to stdout
ev-deployer genesis --config deploy.toml

| Field | Type | Description |
|-----------|---------|----------------------------------------------------------|
| `address` | address | Address to deploy at (canonical: `0x000000000022D473030F116dDEE9F6B43aC78BA3`) |
# Write to file
ev-deployer genesis --config deploy.toml --output alloc.json

## Usage
# Merge into an existing genesis file
ev-deployer genesis --config deploy.toml --merge-into genesis.json --output genesis-out.json

### Generate a starter config
# Overwrite existing addresses when merging
ev-deployer genesis --config deploy.toml --merge-into genesis.json --output genesis-out.json --force

```bash
ev-deployer init --output deploy.toml
# Also export an address manifest
ev-deployer genesis --config deploy.toml --addresses-out addresses.json
```

This creates a TOML config template with all supported contracts commented out and documented.
In genesis mode, every configured contract must have an `address` field.

### Generate genesis alloc
### `deploy`

Print alloc JSON to stdout:
Deploy contracts to a live chain via CREATE2.

```bash
ev-deployer genesis --config deploy.toml
ev-deployer deploy \
--config deploy.toml \
--rpc-url http://localhost:8545 \
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
--state deploy-state.json \
--addresses-out addresses.json
```

Write to a file:
| Flag | Env var | Description |
|------|---------|-------------|
| `--config <PATH>` | | Path to the TOML config |
| `--rpc-url <URL>` | `EV_DEPLOYER_RPC_URL` | RPC endpoint of the target chain |
| `--private-key <HEX>` | `EV_DEPLOYER_PRIVATE_KEY` | Hex-encoded private key for signing |
| `--state <PATH>` | | Path to the state file (created if absent) |
| `--addresses-out <PATH>` | | Write a JSON address manifest |

```bash
ev-deployer genesis --config deploy.toml --output alloc.json
```
The deploy pipeline:

### Merge into an existing genesis file
1. Connects to the RPC and verifies the chain ID matches the config.
2. Checks that the deterministic deployer (`0x4e59b44847b379578588920ca78fbf26c0b4956c`) exists on-chain.
3. Deploys each configured contract via CREATE2.
4. Verifies that the on-chain bytecode matches the expected bytecode (including patched immutables).

Insert the generated entries into an existing `genesis.json`. The merged result is written to `--output` (or stdout if `--output` is omitted):
The `address` field in the config is **ignored** in deploy mode — addresses come from the CREATE2 computation.

```bash
ev-deployer genesis --config deploy.toml --merge-into genesis.json --output genesis-out.json
```
#### State file and resumability

If an address already exists in the genesis, the command fails. Use `--force` to overwrite:
The `--state` file tracks deployment progress. On first run it generates a random CREATE2 salt and records which contracts have been deployed. If the process is interrupted, re-running with the same state file resumes where it left off.

```bash
ev-deployer genesis --config deploy.toml --merge-into genesis.json --output genesis-out.json --force
```
Immutability rules protect against accidental misconfiguration on resume:

### Export address manifest
- The `chain_id` cannot change between runs.
- A contract that was configured in the original run cannot be removed.
- New contracts can be added to subsequent runs.

Write a JSON mapping of contract names to their configured addresses:
### `compute-address`

Look up the configured address for a contract.

```bash
ev-deployer genesis --config deploy.toml --addresses-out addresses.json
ev-deployer compute-address --config deploy.toml --contract permit2
```

Output:
## Config Reference

```json
{
"admin_proxy": "0x000000000000000000000000000000000000Ad00",
"permit2": "0x000000000022D473030F116dDEE9F6B43aC78BA3"
}
```
### `[chain]`

### Look up a contract address
| Field | Type | Description |
|-------|------|-------------|
| `chain_id` | u64 | Chain ID |

```bash
ev-deployer compute-address --config deploy.toml --contract admin_proxy
```
### `[contracts.admin_proxy]`

| Field | Type | Description |
|-------|------|-------------|
| `address` | address | Address to deploy at (required for genesis, ignored for deploy) |
| `owner` | address | Owner address (must not be zero) |

### `[contracts.permit2]`

| Field | Type | Description |
|-------|------|-------------|
| `address` | address | Address to deploy at (canonical: `0x000000000022D473030F116dDEE9F6B43aC78BA3`). Required for genesis, ignored for deploy. |

### `[contracts.deterministic_deployer]`

| Field | Type | Description |
|-------|------|-------------|
| `address` | address | Address (canonical: `0x4e59b44847b379578588920cA78FbF26c0B4956C`). Required for genesis. Genesis-only — not used in deploy mode. |

## Contracts

| Contract | Description |
|---------------|----------------------------------------------------|
| `admin_proxy` | Proxy contract with owner-based access control |
| `permit2` | Uniswap canonical token approval manager |
| Contract | Description |
|----------|-------------|
| `admin_proxy` | Transparent proxy with owner-based access control |
| `permit2` | Uniswap canonical token approval manager (same address on all chains) |
| `deterministic_deployer` | Nick's CREATE2 factory — genesis-only, needed on post-merge chains |

Runtime bytecodes are embedded in the binary — no external toolchain is needed at deploy time.

Expand Down
Loading
Loading