Skip to content

Commit 603ec51

Browse files
authored
Merge branch 'main' into marko/permissioned
2 parents d8c57b6 + fd3cc2a commit 603ec51

File tree

12 files changed

+753
-12
lines changed

12 files changed

+753
-12
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,31 @@ Implementation details:
269269
- No runtime environment variables are required; the chainspec carries the policy alongside other fork settings
270270
- When not configured, the EVM operates normally with standard fee burning
271271

272+
### Custom EIP-1559 Parameters (Custom Networks Only)
273+
274+
ev-reth also lets you override EIP-1559 base fee parameters through the same `evolve` stanza in
275+
your chainspec. This is consensus-critical: all nodes must use the same values.
276+
277+
```json
278+
"config": {
279+
...,
280+
"evolve": {
281+
"baseFeeMaxChangeDenominator": 8,
282+
"baseFeeElasticityMultiplier": 2,
283+
"initialBaseFeePerGas": 1000000000
284+
}
285+
}
286+
```
287+
288+
Notes:
289+
290+
- `baseFeeMaxChangeDenominator` and `baseFeeElasticityMultiplier` override the EIP-1559 formula.
291+
- `initialBaseFeePerGas` only applies when `londonBlock` is `0` (London at genesis). It updates the
292+
genesis `baseFeePerGas` value; if London is activated later, the initial base fee remains
293+
hardcoded to the EIP-1559 constant.
294+
- The node will fail fast if these values are invalid or inconsistent.
295+
- See `docs/eip1559-configuration.md` for recommended values at 100ms block times.
296+
272297
### Custom Contract Size Limit
273298

274299
By default, Ethereum enforces a 24KB contract size limit per [EIP-170](https://eips.ethereum.org/EIPS/eip-170). If your network requires larger contracts, `ev-reth` supports configuring a custom limit via the chainspec.

bin/ev-reth/src/main.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ use evolve_ev_reth::{
1010
config::EvolveConfig,
1111
rpc::txpool::{EvolveTxpoolApiImpl, EvolveTxpoolApiServer},
1212
};
13-
use reth_ethereum_cli::{chainspec::EthereumChainSpecParser, Cli};
13+
use reth_ethereum_cli::Cli;
1414
use reth_tracing_otlp::layer as otlp_layer;
1515
use tracing::info;
1616
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
1717

18-
use ev_node::{log_startup, EvolveArgs, EvolveNode};
18+
use ev_node::{log_startup, EvolveArgs, EvolveChainSpecParser, EvolveNode};
1919

2020
#[global_allocator]
2121
static ALLOC: reth_cli_util::allocator::Allocator = reth_cli_util::allocator::new_allocator();
@@ -47,8 +47,8 @@ fn main() {
4747
init_otlp_tracing();
4848
}
4949

50-
if let Err(err) = Cli::<EthereumChainSpecParser, EvolveArgs>::parse().run(
51-
|builder, _evolve_args| async move {
50+
if let Err(err) =
51+
Cli::<EvolveChainSpecParser, EvolveArgs>::parse().run(|builder, _evolve_args| async move {
5252
log_startup();
5353
let handle = builder
5454
.node(EvolveNode::new())
@@ -67,8 +67,8 @@ fn main() {
6767

6868
info!("=== EV-RETH: Node launched successfully with ev-reth payload builder ===");
6969
handle.node_exit_future.await
70-
},
71-
) {
70+
})
71+
{
7272
eprintln!("Error: {err:?}");
7373
std::process::exit(1);
7474
}

contracts/script/GenerateAdminProxyAlloc.s.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ contract GenerateAdminProxyAlloc is Script {
5252
console.log(' "alloc": {');
5353
console.log(' "000000000000000000000000000000000000Ad00": {');
5454
console.log(' "balance": "0x0",');
55-
console.log(' "code": "0x%s",', vm.toString(runtimeCode));
55+
console.log(' "code": "%s",', vm.toString(runtimeCode));
5656
console.log(' "storage": {');
57-
console.log(' "0x0": "0x%s"', vm.toString(ownerSlotValue));
57+
console.log(' "0x0": "%s"', vm.toString(ownerSlotValue));
5858
console.log(" }");
5959
console.log(" }");
6060
console.log(" }");
@@ -100,9 +100,9 @@ contract GenerateAdminProxyAllocJSON is Script {
100100
// Output minimal JSON that can be merged into genesis
101101
string memory json = string(
102102
abi.encodePacked(
103-
'{"000000000000000000000000000000000000Ad00":{"balance":"0x0","code":"0x',
103+
'{"000000000000000000000000000000000000Ad00":{"balance":"0x0","code":"',
104104
vm.toString(runtimeCode),
105-
'","storage":{"0x0":"0x',
105+
'","storage":{"0x0":"',
106106
vm.toString(ownerSlotValue),
107107
'"}}}'
108108
)
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.24;
3+
4+
import {Script, console} from "forge-std/Script.sol";
5+
import {FeeVault} from "../src/FeeVault.sol";
6+
7+
abstract contract FeeVaultAllocBase is Script {
8+
struct Config {
9+
address feeVaultAddress;
10+
address owner;
11+
uint32 destinationDomain;
12+
bytes32 recipientAddress;
13+
uint256 minimumAmount;
14+
uint256 callFee;
15+
uint256 bridgeShareBpsRaw;
16+
uint256 bridgeShareBps;
17+
address otherRecipient;
18+
address hypNativeMinter;
19+
bytes32 salt;
20+
address deployer;
21+
}
22+
23+
function loadConfig() internal view returns (Config memory cfg) {
24+
cfg.owner = vm.envAddress("OWNER");
25+
cfg.destinationDomain = uint32(vm.envOr("DESTINATION_DOMAIN", uint256(0)));
26+
cfg.recipientAddress = vm.envOr("RECIPIENT_ADDRESS", bytes32(0));
27+
cfg.minimumAmount = vm.envOr("MINIMUM_AMOUNT", uint256(0));
28+
cfg.callFee = vm.envOr("CALL_FEE", uint256(0));
29+
cfg.bridgeShareBpsRaw = vm.envOr("BRIDGE_SHARE_BPS", uint256(0));
30+
cfg.otherRecipient = vm.envOr("OTHER_RECIPIENT", address(0));
31+
cfg.hypNativeMinter = vm.envOr("HYP_NATIVE_MINTER", address(0));
32+
cfg.feeVaultAddress = vm.envOr("FEE_VAULT_ADDRESS", address(0));
33+
cfg.deployer = vm.envOr("DEPLOYER", address(0));
34+
cfg.salt = vm.envOr("SALT", bytes32(0));
35+
36+
require(cfg.owner != address(0), "OWNER required");
37+
require(cfg.bridgeShareBpsRaw <= 10000, "BRIDGE_SHARE_BPS > 10000");
38+
39+
cfg.bridgeShareBps = cfg.bridgeShareBpsRaw == 0 ? 10000 : cfg.bridgeShareBpsRaw;
40+
41+
if (cfg.feeVaultAddress == address(0) && cfg.deployer != address(0)) {
42+
bytes32 initCodeHash = keccak256(
43+
abi.encodePacked(
44+
type(FeeVault).creationCode,
45+
abi.encode(
46+
cfg.owner,
47+
cfg.destinationDomain,
48+
cfg.recipientAddress,
49+
cfg.minimumAmount,
50+
cfg.callFee,
51+
cfg.bridgeShareBpsRaw,
52+
cfg.otherRecipient
53+
)
54+
)
55+
);
56+
cfg.feeVaultAddress = address(
57+
uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), cfg.deployer, cfg.salt, initCodeHash))))
58+
);
59+
}
60+
61+
require(cfg.feeVaultAddress != address(0), "FEE_VAULT_ADDRESS or DEPLOYER required");
62+
}
63+
64+
function computeSlots(Config memory cfg)
65+
internal
66+
pure
67+
returns (
68+
bytes32 slot0,
69+
bytes32 slot1,
70+
bytes32 slot2,
71+
bytes32 slot3,
72+
bytes32 slot4,
73+
bytes32 slot5,
74+
bytes32 slot6
75+
)
76+
{
77+
slot0 = bytes32(uint256(uint160(cfg.hypNativeMinter)));
78+
slot1 = bytes32((uint256(cfg.destinationDomain) << 160) | uint256(uint160(cfg.owner)));
79+
slot2 = cfg.recipientAddress;
80+
slot3 = bytes32(cfg.minimumAmount);
81+
slot4 = bytes32(cfg.callFee);
82+
slot5 = bytes32(uint256(uint160(cfg.otherRecipient)));
83+
slot6 = bytes32(cfg.bridgeShareBps);
84+
}
85+
86+
function addressKey(address addr) internal pure returns (string memory) {
87+
bytes memory full = bytes(vm.toString(addr));
88+
bytes memory key = new bytes(40);
89+
// Fixed-length copy for address key without 0x prefix.
90+
for (uint256 i = 0; i < 40; i++) {
91+
key[i] = full[i + 2];
92+
}
93+
return string(key);
94+
}
95+
}
96+
97+
/// @title GenerateFeeVaultAlloc
98+
/// @notice Generates genesis alloc JSON for deploying FeeVault at a deterministic address
99+
/// @dev Run with: OWNER=0x... forge script script/GenerateFeeVaultAlloc.s.sol -vvv
100+
contract GenerateFeeVaultAlloc is FeeVaultAllocBase {
101+
function run() external view {
102+
Config memory cfg = loadConfig();
103+
bytes memory runtimeCode = type(FeeVault).runtimeCode;
104+
105+
(bytes32 slot0, bytes32 slot1, bytes32 slot2, bytes32 slot3, bytes32 slot4, bytes32 slot5, bytes32 slot6) =
106+
computeSlots(cfg);
107+
108+
console.log("========== FeeVault Genesis Alloc ==========");
109+
console.log("FeeVault address:", cfg.feeVaultAddress);
110+
console.log("Owner:", cfg.owner);
111+
console.log("Destination domain:", cfg.destinationDomain);
112+
console.log("Bridge share bps (raw):", cfg.bridgeShareBpsRaw);
113+
console.log("Bridge share bps (effective):", cfg.bridgeShareBps);
114+
console.log("");
115+
116+
if (cfg.bridgeShareBpsRaw == 0) {
117+
console.log("NOTE: BRIDGE_SHARE_BPS=0 defaults to 10000 (constructor behavior).");
118+
}
119+
if (cfg.bridgeShareBps < 10000 && cfg.otherRecipient == address(0)) {
120+
console.log("WARNING: OTHER_RECIPIENT is zero but bridge share < 10000.");
121+
}
122+
if (cfg.hypNativeMinter == address(0)) {
123+
console.log("NOTE: HYP_NATIVE_MINTER is zero; set it before calling sendToCelestia().");
124+
}
125+
console.log("");
126+
127+
console.log("Add this to your genesis.json 'alloc' section:");
128+
console.log("");
129+
console.log("{");
130+
console.log(' "alloc": {');
131+
console.log(' "%s": {', addressKey(cfg.feeVaultAddress));
132+
console.log(' "balance": "0x0",');
133+
console.log(' "code": "%s",', vm.toString(runtimeCode));
134+
console.log(' "storage": {');
135+
console.log(' "0x0": "%s",', vm.toString(slot0));
136+
console.log(' "0x1": "%s",', vm.toString(slot1));
137+
console.log(' "0x2": "%s",', vm.toString(slot2));
138+
console.log(' "0x3": "%s",', vm.toString(slot3));
139+
console.log(' "0x4": "%s",', vm.toString(slot4));
140+
console.log(' "0x5": "%s",', vm.toString(slot5));
141+
console.log(' "0x6": "%s"', vm.toString(slot6));
142+
console.log(" }");
143+
console.log(" }");
144+
console.log(" }");
145+
console.log("}");
146+
console.log("");
147+
console.log("Raw bytecode length:", runtimeCode.length);
148+
console.log("=============================================");
149+
}
150+
}
151+
152+
/// @title GenerateFeeVaultAllocJSON
153+
/// @notice Outputs just the JSON snippet for easy copy-paste
154+
/// @dev Run with: OWNER=0x... forge script script/GenerateFeeVaultAlloc.s.sol:GenerateFeeVaultAllocJSON -vvv
155+
contract GenerateFeeVaultAllocJSON is FeeVaultAllocBase {
156+
function run() external view {
157+
Config memory cfg = loadConfig();
158+
bytes memory runtimeCode = type(FeeVault).runtimeCode;
159+
160+
(bytes32 slot0, bytes32 slot1, bytes32 slot2, bytes32 slot3, bytes32 slot4, bytes32 slot5, bytes32 slot6) =
161+
computeSlots(cfg);
162+
163+
string memory json = string(
164+
abi.encodePacked(
165+
'{"',
166+
addressKey(cfg.feeVaultAddress),
167+
'":{"balance":"0x0","code":"',
168+
vm.toString(runtimeCode),
169+
'","storage":{"0x0":"',
170+
vm.toString(slot0),
171+
'","0x1":"',
172+
vm.toString(slot1),
173+
'","0x2":"',
174+
vm.toString(slot2),
175+
'","0x3":"',
176+
vm.toString(slot3),
177+
'","0x4":"',
178+
vm.toString(slot4),
179+
'","0x5":"',
180+
vm.toString(slot5),
181+
'","0x6":"',
182+
vm.toString(slot6),
183+
'"}}}'
184+
)
185+
);
186+
187+
console.log(json);
188+
}
189+
}

crates/node/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ ev-revm = { path = "../ev-revm" }
1717
# Reth dependencies
1818
reth-node-builder.workspace = true
1919
reth-chainspec.workspace = true
20+
reth-cli.workspace = true
2021
reth-ethereum = { workspace = true, features = ["node", "cli", "pool"] }
2122
reth-ethereum-forks.workspace = true
2223
reth-ethereum-payload-builder.workspace = true
@@ -52,6 +53,7 @@ alloy-primitives.workspace = true
5253
alloy-eips.workspace = true
5354
alloy-consensus.workspace = true
5455
alloy-evm.workspace = true
56+
alloy-genesis.workspace = true
5557

5658
# Core dependencies
5759
eyre.workspace = true
@@ -73,7 +75,6 @@ reth-transaction-pool.workspace = true
7375
reth-consensus.workspace = true
7476
reth-tasks.workspace = true
7577
reth-tracing.workspace = true
76-
alloy-genesis.workspace = true
7778
tempfile.workspace = true
7879
hex = "0.4"
7980

0 commit comments

Comments
 (0)