Skip to content

Commit 382fa0f

Browse files
authored
Merge branch 'main' into marko/precompile_proposer
2 parents 018cfd8 + 7bdb86e commit 382fa0f

22 files changed

Lines changed: 2515 additions & 610 deletions

Cargo.lock

Lines changed: 951 additions & 207 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ reth-tasks = { git = "https://github.com/paradigmxyz/reth.git", tag = "v2.2.0",
8686
revm = { version = "38.0.0", default-features = false }
8787

8888
# Alloy dependencies (aligned to reth v2.2.0)
89-
alloy = { version = "2.0.4", features = [
89+
alloy = { version = "2.0.5", features = [
9090
"contract",
9191
"providers",
9292
"provider-http",
@@ -105,13 +105,13 @@ alloy-rpc-types-engine = { version = "2.0.4", default-features = false }
105105
alloy-signer = { version = "2.0.4", default-features = false }
106106
alloy-signer-local = { version = "2.0.4", features = ["mnemonic"] }
107107
alloy-serde = { version = "2.0.4", default-features = false }
108-
alloy-primitives = { version = "1.5.6", default-features = false }
108+
alloy-primitives = { version = "1.6.0", default-features = false }
109109
alloy-consensus = { version = "2.0.4", default-features = false }
110110
alloy-consensus-any = { version = "2.0.4", default-features = false }
111111
alloy-rlp = { version = "0.3.13", default-features = false }
112112
alloy-genesis = { version = "2.0.4", default-features = false }
113113
alloy-rpc-types-txpool = { version = "2.0.4", default-features = false }
114-
alloy-sol-types = { version = "1.5.6", default-features = false }
114+
alloy-sol-types = { version = "1.6.0", default-features = false }
115115

116116
# Utility dependencies
117117
bytes = "1.10.1"

bin/ev-deployer/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ tokio = { workspace = true }
1818
clap = { workspace = true, features = ["derive", "env"] }
1919
serde = { workspace = true, features = ["derive"] }
2020
serde_json = { workspace = true }
21-
toml = "0.9"
21+
toml = "1.1"
2222
eyre = { workspace = true }
2323
rand = { workspace = true }
2424

bin/ev-deployer/README.md

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,12 @@ Both modes read the same TOML config. The `address` field in each contract secti
1616
## Quick Start
1717

1818
```bash
19-
# 1. Generate a config pre-populated for your chain
20-
ev-deployer init --chain-id 42170 --permit2 --output deploy.toml
19+
# Genesis: embed contracts into the chain's genesis state
20+
ev-deployer init genesis --chain-id 42170 --permit2 --deterministic-deployer --output genesis.toml
21+
ev-deployer genesis --config genesis.toml --merge-into genesis.json --output genesis-out.json
2122

22-
# 2a. Genesis mode: embed into genesis state
23-
ev-deployer genesis --config deploy.toml --merge-into genesis.json --output genesis-out.json
24-
25-
# 2b. Deploy mode: deploy to a live chain
23+
# Deploy: deploy contracts to a running chain via CREATE2
24+
ev-deployer init deploy --chain-id 42170 --permit2 --output deploy.toml
2625
ev-deployer deploy \
2726
--config deploy.toml \
2827
--rpc-url http://localhost:8545 \
@@ -40,31 +39,55 @@ The binary is output to `target/release/ev-deployer`.
4039

4140
## Commands
4241

43-
### `init`
42+
### `init genesis`
4443

45-
Generate a starter config file.
44+
Generate a starter config for **genesis mode** (contracts embedded at chain start). Includes `address` fields for each contract.
4645

4746
```bash
4847
# Bare template (all contracts commented out)
49-
ev-deployer init
48+
ev-deployer init genesis
5049

51-
# Pre-populated with chain ID, Permit2, and deterministic deployer
52-
ev-deployer init --chain-id 42170 --permit2 --deterministic-deployer
50+
# Pre-populated with Permit2 and deterministic deployer
51+
ev-deployer init genesis --chain-id 42170 --permit2 --deterministic-deployer
5352

5453
# Full config with all contracts
55-
ev-deployer init \
54+
ev-deployer init genesis \
5655
--chain-id 42170 \
5756
--permit2 \
57+
--deterministic-deployer \
5858
--admin-proxy-owner 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 \
59-
--output deploy.toml
59+
--output genesis.toml
6060
```
6161

6262
| Flag | Description |
6363
|------|-------------|
6464
| `--output <PATH>` | Write to file instead of stdout |
6565
| `--chain-id <ID>` | Set the chain ID (defaults to 0) |
6666
| `--permit2` | Enable Permit2 with its canonical address |
67-
| `--deterministic-deployer` | Enable the deterministic deployer (Nick's factory) with its canonical address |
67+
| `--deterministic-deployer` | Enable the deterministic deployer (Nick's factory) |
68+
| `--admin-proxy-owner <ADDR>` | Enable AdminProxy with the given owner |
69+
70+
### `init deploy`
71+
72+
Generate a starter config for **deploy mode** (contracts deployed via CREATE2 to a running chain). No `address` fields — addresses are computed deterministically. The deterministic deployer is not included in the config since it cannot be deployed via CREATE2 (it must already exist on-chain).
73+
74+
```bash
75+
# Config with Permit2
76+
ev-deployer init deploy --chain-id 42170 --permit2
77+
78+
# Full config
79+
ev-deployer init deploy \
80+
--chain-id 42170 \
81+
--permit2 \
82+
--admin-proxy-owner 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 \
83+
--output deploy.toml
84+
```
85+
86+
| Flag | Description |
87+
|------|-------------|
88+
| `--output <PATH>` | Write to file instead of stdout |
89+
| `--chain-id <ID>` | Set the chain ID (defaults to 0) |
90+
| `--permit2` | Enable Permit2 |
6891
| `--admin-proxy-owner <ADDR>` | Enable AdminProxy with the given owner |
6992

7093
### `genesis`
@@ -114,15 +137,17 @@ ev-deployer deploy \
114137
The deploy pipeline:
115138

116139
1. Connects to the RPC and verifies the chain ID matches the config.
117-
2. Checks that the deterministic deployer (`0x4e59b44847b379578588920ca78fbf26c0b4956c`) exists on-chain.
140+
2. Checks that the [deterministic deployer](https://github.com/Arachnid/deterministic-deployment-proxy) (`0x4e59b44847b379578588920ca78fbf26c0b4956c`) exists on-chain.
118141
3. Deploys each configured contract via CREATE2.
119142
4. Verifies that the on-chain bytecode matches the expected bytecode (including patched immutables).
120143

121-
The `address` field in the config is **ignored** in deploy mode — addresses come from the CREATE2 computation.
144+
Permit2 is deployed using the [canonical Uniswap salt](https://github.com/Uniswap/permit2/blob/main/script/DeployPermit2.s.sol), so it lands at its well-known address `0x000000000022D473030F116dDEE9F6B43aC78BA3` on any chain.
145+
146+
> **Using with ev-dev**: The deterministic deployer can be included in the ev-dev genesis via `ev-deployer init genesis --deterministic-deployer`, so `ev-deployer deploy` works against ev-dev. See the [ev-dev README](../ev-dev/README.md#live-contract-deployment-create2) for examples.
122147
123148
#### State file and resumability
124149

125-
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.
150+
The `--state` file tracks deployment progress and records which contracts have been deployed. If the process is interrupted, re-running with the same state file resumes where it left off. Contracts with well-known salts (e.g. Permit2) use their canonical salt; others use a random salt generated on first run.
126151

127152
Immutability rules protect against accidental misconfiguration on resume:
128153

bin/ev-deployer/src/contracts/permit2.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ pub(crate) const HASHED_NAME: B256 = B256::new(hex!(
7373
"9ac997416e8ff9d2ff6bebeb7149f65cdae5e32e2b90440b566bb3044041d36a"
7474
));
7575

76+
/// The CREATE2 salt used by Uniswap to deploy Permit2 at its canonical address
77+
/// (`0x000000000022D473030F116dDEE9F6B43aC78BA3`) via Nick's factory.
78+
///
79+
/// Source: <https://github.com/Uniswap/permit2/blob/main/script/DeployPermit2.s.sol>
80+
pub(crate) const PERMIT2_CANONICAL_SALT: B256 = B256::new(hex!(
81+
"0000000000000000000000000000000000000000d3af2663da51c10215000000"
82+
));
83+
7684
/// Build the expected runtime bytecode for a Permit2 deployed at `address` on `chain_id`.
7785
/// Used by the deploy pipeline to verify on-chain bytecode matches.
7886
pub(crate) fn expected_runtime_bytecode(chain_id: u64, address: Address) -> Vec<u8> {

bin/ev-deployer/src/deploy/create2.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ mod tests {
6262
assert_ne!(addr1, addr2);
6363
}
6464

65+
#[test]
66+
fn permit2_canonical_salt_produces_canonical_address() {
67+
use crate::contracts::permit2::{PERMIT2_CANONICAL_SALT, PERMIT2_INITCODE};
68+
let addr = compute_address(PERMIT2_CANONICAL_SALT, PERMIT2_INITCODE);
69+
let expected: Address = "0x000000000022D473030F116dDEE9F6B43aC78BA3"
70+
.parse()
71+
.unwrap();
72+
assert_eq!(addr, expected);
73+
}
74+
6575
#[test]
6676
fn factory_calldata_format() {
6777
let salt = B256::with_last_byte(0x42);

bin/ev-deployer/src/deploy/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! On-chain deployment pipeline: CREATE2 addressing, state tracking, and orchestration.
2+
13
pub mod create2;
24
pub mod deployer;
35
pub mod pipeline;

bin/ev-deployer/src/deploy/pipeline.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ pub async fn run(pipeline_cfg: &PipelineConfig, deployer: &dyn ChainDeployer) ->
6060
state
6161
};
6262

63-
let salt = state.create2_salt;
64-
6563
// ── Step 2: Deploy Permit2 ──
6664
if let Some(ref p2_config) = pipeline_cfg.config.contracts.permit2 {
6765
eprintln!("[3/4] Deploying Permit2...");
@@ -70,8 +68,9 @@ pub async fn run(pipeline_cfg: &PipelineConfig, deployer: &dyn ChainDeployer) ->
7068
eprintln!(" WARN: contracts.permit2.address is ignored in deploy mode");
7169
}
7270

71+
let permit2_salt = contracts::permit2::PERMIT2_CANONICAL_SALT;
7372
let initcode = contracts::permit2::PERMIT2_INITCODE.to_vec();
74-
let address = compute_address(salt, &initcode);
73+
let address = compute_address(permit2_salt, &initcode);
7574

7675
let expected_runtime = contracts::permit2::expected_runtime_bytecode(chain_id, address);
7776

@@ -81,7 +80,7 @@ pub async fn run(pipeline_cfg: &PipelineConfig, deployer: &dyn ChainDeployer) ->
8180
&DeployContractParams {
8281
name: "permit2",
8382
address,
84-
salt,
83+
salt: permit2_salt,
8584
initcode: &initcode,
8685
expected_runtime: &expected_runtime,
8786
state_path: &pipeline_cfg.state_path,

0 commit comments

Comments
 (0)