Skip to content

Commit 6b85563

Browse files
committed
Revert "refactor(ev-deployer): remove AdminProxy contract from part 1"
This reverts commit 089ef22.
1 parent 089ef22 commit 6b85563

9 files changed

Lines changed: 289 additions & 32 deletions

File tree

bin/ev-deployer/README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ EV Deployer uses a TOML config file to define what contracts to include and how
1818
[chain]
1919
chain_id = 1234
2020

21-
[contracts]
21+
[contracts.admin_proxy]
22+
address = "0x000000000000000000000000000000000000Ad00"
23+
owner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
2224
```
2325

2426
### Config reference
@@ -29,6 +31,13 @@ chain_id = 1234
2931
|------------|------|-------------|
3032
| `chain_id` | u64 | Chain ID |
3133

34+
#### `[contracts.admin_proxy]`
35+
36+
| Field | Type | Description |
37+
|-----------|---------|---------------------------|
38+
| `address` | address | Address to deploy at |
39+
| `owner` | address | Owner (must not be zero) |
40+
3241
## Usage
3342

3443
### Generate genesis alloc
@@ -67,6 +76,28 @@ Write a JSON mapping of contract names to their configured addresses:
6776
ev-deployer genesis --config deploy.toml --addresses-out addresses.json
6877
```
6978

79+
Output:
80+
81+
```json
82+
{
83+
"admin_proxy": "0x000000000000000000000000000000000000Ad00"
84+
}
85+
```
86+
87+
### Look up a contract address
88+
89+
```bash
90+
ev-deployer compute-address --config deploy.toml --contract admin_proxy
91+
```
92+
93+
## Contracts
94+
95+
| Contract | Description |
96+
|----------------|-----------------------------------------------------|
97+
| `admin_proxy` | Proxy contract with owner-based access control |
98+
99+
Runtime bytecodes are embedded in the binary — no external toolchain is needed at deploy time.
100+
70101
## Testing
71102

72103
```bash
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
[chain]
22
chain_id = 1234
33

4-
[contracts]
4+
[contracts.admin_proxy]
5+
address = "0x000000000000000000000000000000000000Ad00"
6+
owner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"

bin/ev-deployer/src/config.rs

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! TOML config types, parsing, and validation.
22
3+
use alloy_primitives::Address;
34
use serde::Deserialize;
45
use std::path::Path;
56

@@ -22,8 +23,20 @@ pub(crate) struct ChainConfig {
2223
}
2324

2425
/// All contract configurations.
25-
#[derive(Debug, Deserialize, Default)]
26-
pub(crate) struct ContractsConfig {}
26+
#[derive(Debug, Deserialize)]
27+
pub(crate) struct ContractsConfig {
28+
/// `AdminProxy` contract config (optional).
29+
pub admin_proxy: Option<AdminProxyConfig>,
30+
}
31+
32+
/// `AdminProxy` configuration.
33+
#[derive(Debug, Deserialize)]
34+
pub(crate) struct AdminProxyConfig {
35+
/// Address to deploy at.
36+
pub address: Address,
37+
/// Owner address.
38+
pub owner: Address,
39+
}
2740

2841
impl DeployConfig {
2942
/// Load and validate config from a TOML file.
@@ -36,6 +49,13 @@ impl DeployConfig {
3649

3750
/// Validate config values.
3851
fn validate(&self) -> eyre::Result<()> {
52+
if let Some(ref ap) = self.contracts.admin_proxy {
53+
eyre::ensure!(
54+
!ap.owner.is_zero(),
55+
"admin_proxy.owner must not be the zero address"
56+
);
57+
}
58+
3959
Ok(())
4060
}
4161
}
@@ -50,10 +70,42 @@ mod tests {
5070
[chain]
5171
chain_id = 1234
5272
53-
[contracts]
73+
[contracts.admin_proxy]
74+
address = "0x000000000000000000000000000000000000Ad00"
75+
owner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
5476
"#;
5577
let config: DeployConfig = toml::from_str(toml).unwrap();
5678
assert_eq!(config.chain.chain_id, 1234);
79+
assert!(config.contracts.admin_proxy.is_some());
80+
config.validate().unwrap();
81+
}
82+
83+
#[test]
84+
fn reject_zero_owner() {
85+
let toml = r#"
86+
[chain]
87+
chain_id = 1
88+
89+
[contracts.admin_proxy]
90+
address = "0x000000000000000000000000000000000000Ad00"
91+
owner = "0x0000000000000000000000000000000000000000"
92+
"#;
93+
let config: DeployConfig = toml::from_str(toml).unwrap();
94+
assert!(config.validate().is_err());
95+
}
96+
97+
#[test]
98+
fn admin_proxy_only() {
99+
let toml = r#"
100+
[chain]
101+
chain_id = 1
102+
103+
[contracts.admin_proxy]
104+
address = "0x000000000000000000000000000000000000Ad00"
105+
owner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
106+
"#;
107+
let config: DeployConfig = toml::from_str(toml).unwrap();
57108
config.validate().unwrap();
109+
assert!(config.contracts.admin_proxy.is_some());
58110
}
59111
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//! `AdminProxy` bytecode and storage encoding.
2+
3+
use crate::{config::AdminProxyConfig, contracts::GenesisContract};
4+
use alloy_primitives::{hex, Bytes, B256, U256};
5+
use std::collections::BTreeMap;
6+
7+
/// `AdminProxy` runtime bytecode compiled with solc 0.8.33 (`cbor_metadata=false`).
8+
/// Regenerate with: `cd contracts && forge inspect AdminProxy deployedBytecode`
9+
const ADMIN_PROXY_BYTECODE: &[u8] = &hex!("60806040526004361061007e575f3560e01c80638da5cb5b1161004d5780638da5cb5b1461012d578063e30c397814610157578063f2fde38b14610181578063fa4bb79d146101a957610085565b806318dfb3c7146100895780631cff79cd146100c557806379ba5097146101015780638b5298541461011757610085565b3661008557005b5f5ffd5b348015610094575f5ffd5b506100af60048036038101906100aa9190610cf8565b6101e5565b6040516100bc9190610ea1565b60405180910390f35b3480156100d0575f5ffd5b506100eb60048036038101906100e69190610f70565b6104d9565b6040516100f89190611015565b60405180910390f35b34801561010c575f5ffd5b5061011561066c565b005b348015610122575f5ffd5b5061012b6107ed565b005b348015610138575f5ffd5b506101416108b4565b60405161014e9190611044565b60405180910390f35b348015610162575f5ffd5b5061016b6108d8565b6040516101789190611044565b60405180910390f35b34801561018c575f5ffd5b506101a760048036038101906101a2919061105d565b6108fd565b005b3480156101b4575f5ffd5b506101cf60048036038101906101ca91906110bb565b610aa4565b6040516101dc9190611015565b60405180910390f35b60605f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461026c576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8282905085859050146102ab576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8484905067ffffffffffffffff8111156102c8576102c761112c565b5b6040519080825280602002602001820160405280156102fb57816020015b60608152602001906001900390816102e65790505b5090505f5f90505b858590508110156104d0575f5f87878481811061032357610322611159565b5b9050602002016020810190610338919061105d565b73ffffffffffffffffffffffffffffffffffffffff1686868581811061036157610360611159565b5b90506020028101906103739190611192565b604051610381929190611230565b5f604051808303815f865af19150503d805f81146103ba576040519150601f19603f3d011682016040523d82523d5f602084013e6103bf565b606091505b50915091508161040657806040517fa5fa8d2b0000000000000000000000000000000000000000000000000000000081526004016103fd9190611015565b60405180910390fd5b87878481811061041957610418611159565b5b905060200201602081019061042e919061105d565b73ffffffffffffffffffffffffffffffffffffffff167fc96720f35dd524e76ea92971ce13d08e9a17816bf3b0008a7083e6032354ebb587878681811061047857610477611159565b5b905060200281019061048a9190611192565b8460405161049a93929190611274565b60405180910390a2808484815181106104b6576104b5611159565b5b602002602001018190525050508080600101915050610303565b50949350505050565b60605f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610560576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f8573ffffffffffffffffffffffffffffffffffffffff168585604051610589929190611230565b5f604051808303815f865af19150503d805f81146105c2576040519150601f19603f3d011682016040523d82523d5f602084013e6105c7565b606091505b50915091508161060e57806040517fa5fa8d2b0000000000000000000000000000000000000000000000000000000081526004016106059190611015565b60405180910390fd5b8573ffffffffffffffffffffffffffffffffffffffff167fc96720f35dd524e76ea92971ce13d08e9a17816bf3b0008a7083e6032354ebb586868460405161065893929190611274565b60405180910390a280925050509392505050565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106f2576040517f1853971c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f60015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610872576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610982576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109e7576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff165f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60605f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b2b576040517f30cd747100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5f8673ffffffffffffffffffffffffffffffffffffffff16848787604051610b55929190611230565b5f6040518083038185875af1925050503d805f8114610b8f576040519150601f19603f3d011682016040523d82523d5f602084013e610b94565b606091505b509150915081610bdb57806040517fa5fa8d2b000000000000000000000000000000000000000000000000000000008152600401610bd29190611015565b60405180910390fd5b8673ffffffffffffffffffffffffffffffffffffffff167fc96720f35dd524e76ea92971ce13d08e9a17816bf3b0008a7083e6032354ebb5878784604051610c2593929190611274565b60405180910390a28092505050949350505050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112610c6357610c62610c42565b5b8235905067ffffffffffffffff811115610c8057610c7f610c46565b5b602083019150836020820283011115610c9c57610c9b610c4a565b5b9250929050565b5f5f83601f840112610cb857610cb7610c42565b5b8235905067ffffffffffffffff811115610cd557610cd4610c46565b5b602083019150836020820283011115610cf157610cf0610c4a565b5b9250929050565b5f5f5f5f60408587031215610d1057610d0f610c3a565b5b5f85013567ffffffffffffffff811115610d2d57610d2c610c3e565b5b610d3987828801610c4e565b9450945050602085013567ffffffffffffffff811115610d5c57610d5b610c3e565b5b610d6887828801610ca3565b925092505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610de182610d9f565b610deb8185610da9565b9350610dfb818560208601610db9565b610e0481610dc7565b840191505092915050565b5f610e1a8383610dd7565b905092915050565b5f602082019050919050565b5f610e3882610d76565b610e428185610d80565b935083602082028501610e5485610d90565b805f5b85811015610e8f5784840389528151610e708582610e0f565b9450610e7b83610e22565b925060208a01995050600181019050610e57565b50829750879550505050505092915050565b5f6020820190508181035f830152610eb98184610e2e565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610eea82610ec1565b9050919050565b610efa81610ee0565b8114610f04575f5ffd5b50565b5f81359050610f1581610ef1565b92915050565b5f5f83601f840112610f3057610f2f610c42565b5b8235905067ffffffffffffffff811115610f4d57610f4c610c46565b5b602083019150836001820283011115610f6957610f68610c4a565b5b9250929050565b5f5f5f60408486031215610f8757610f86610c3a565b5b5f610f9486828701610f07565b935050602084013567ffffffffffffffff811115610fb557610fb4610c3e565b5b610fc186828701610f1b565b92509250509250925092565b5f82825260208201905092915050565b5f610fe782610d9f565b610ff18185610fcd565b9350611001818560208601610db9565b61100a81610dc7565b840191505092915050565b5f6020820190508181035f83015261102d8184610fdd565b905092915050565b61103e81610ee0565b82525050565b5f6020820190506110575f830184611035565b92915050565b5f6020828403121561107257611071610c3a565b5b5f61107f84828501610f07565b91505092915050565b5f819050919050565b61109a81611088565b81146110a4575f5ffd5b50565b5f813590506110b581611091565b92915050565b5f5f5f5f606085870312156110d3576110d2610c3a565b5b5f6110e087828801610f07565b945050602085013567ffffffffffffffff81111561110157611100610c3e565b5b61110d87828801610f1b565b93509350506040611120878288016110a7565b91505092959194509250565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f5ffd5b5f5ffd5b5f5ffd5b5f5f833560016020038436030381126111ae576111ad611186565b5b80840192508235915067ffffffffffffffff8211156111d0576111cf61118a565b5b6020830192506001820236038313156111ec576111eb61118e565b5b509250929050565b5f81905092915050565b828183375f83830152505050565b5f61121783856111f4565b93506112248385846111fe565b82840190509392505050565b5f61123c82848661120c565b91508190509392505050565b5f6112538385610fcd565b93506112608385846111fe565b61126983610dc7565b840190509392505050565b5f6040820190508181035f83015261128d818587611248565b905081810360208301526112a18184610fdd565b905094935050505056");
10+
11+
/// Build a genesis alloc entry for `AdminProxy`.
12+
pub(crate) fn build(config: &AdminProxyConfig) -> GenesisContract {
13+
let mut storage = BTreeMap::new();
14+
15+
// Slot 0: owner (address left-padded to 32 bytes)
16+
let owner_value = B256::from(U256::from_be_bytes(config.owner.into_word().0));
17+
storage.insert(B256::ZERO, owner_value);
18+
19+
GenesisContract {
20+
address: config.address,
21+
code: Bytes::from_static(ADMIN_PROXY_BYTECODE),
22+
storage,
23+
}
24+
}
25+
26+
#[cfg(test)]
27+
mod tests {
28+
use super::*;
29+
use alloy_primitives::address;
30+
use std::{path::PathBuf, process::Command};
31+
32+
#[test]
33+
fn golden_admin_proxy_storage() {
34+
let config = AdminProxyConfig {
35+
address: address!("000000000000000000000000000000000000Ad00"),
36+
owner: address!("f39Fd6e51aad88F6F4ce6aB8827279cffFb92266"),
37+
};
38+
let contract = build(&config);
39+
40+
let expected_slot0: B256 =
41+
"0x000000000000000000000000f39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
42+
.parse()
43+
.unwrap();
44+
assert_eq!(contract.storage[&B256::ZERO], expected_slot0);
45+
}
46+
47+
#[test]
48+
#[ignore = "requires forge CLI"]
49+
fn admin_proxy_bytecode_matches_solidity_source() {
50+
let contracts_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
51+
.ancestors()
52+
.nth(2)
53+
.unwrap()
54+
.join("contracts");
55+
56+
let output = Command::new("forge")
57+
.args(["inspect", "AdminProxy", "deployedBytecode", "--root"])
58+
.arg(&contracts_root)
59+
.output()
60+
.expect("forge not found");
61+
62+
assert!(
63+
output.status.success(),
64+
"forge inspect failed: {}",
65+
String::from_utf8_lossy(&output.stderr)
66+
);
67+
68+
let forge_hex = String::from_utf8(output.stdout)
69+
.unwrap()
70+
.trim()
71+
.trim_start_matches("0x")
72+
.to_lowercase();
73+
74+
let hardcoded_hex = hex::encode(ADMIN_PROXY_BYTECODE);
75+
76+
assert_eq!(
77+
forge_hex, hardcoded_hex,
78+
"AdminProxy bytecode mismatch! Update the constant with: cd contracts && forge inspect AdminProxy deployedBytecode"
79+
);
80+
}
81+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Contract bytecode and storage encoding.
22
3+
pub(crate) mod admin_proxy;
4+
35
use alloy_primitives::{Address, Bytes, B256};
46
use std::collections::BTreeMap;
57

0 commit comments

Comments
 (0)