1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//! Constants for the `MegaETH` EVM.
//!
//! It groups the constants for different EVM specs as sub-modules.
/// Constants for the `EQUIVALENCE` spec.
pub mod equivalence {
use revm::interpreter::gas;
/// Constants inherited from `revm`.
pub use gas::{
BASE, BLOCKHASH, CALLVALUE, CALL_STIPEND, CODEDEPOSIT, COLD_ACCOUNT_ACCESS_COST,
COLD_SLOAD_COST, CREATE, KECCAK256WORD, LOG, LOGDATA, LOGTOPIC, NEWACCOUNT, SSTORE_RESET,
SSTORE_SET, STANDARD_TOKEN_COST, TOTAL_COST_FLOOR_PER_TOKEN, VERYLOW, WARM_SSTORE_RESET,
WARM_STORAGE_READ_COST,
};
pub use revm::primitives::STACK_LIMIT;
}
/// Constants for the `MINI_REX` spec.
pub mod mini_rex {
/// The maximum contract size for the `MINI_REX` spec.
pub const MAX_CONTRACT_SIZE: usize = 512 * 1024;
/// The additional initcode size for the `MINI_REX` spec. The initcode size is limited to
/// `MAX_CONTRACT_SIZE + ADDITIONAL_INITCODE_SIZE`.
pub const ADDITIONAL_INITCODE_SIZE: usize = 24 * 1024;
/// The maximum initcode size for the `MINI_REX` spec.
pub const MAX_INITCODE_SIZE: usize = MAX_CONTRACT_SIZE + ADDITIONAL_INITCODE_SIZE;
/// The maximum compute gas allowed per transaction for the `MINI_REX` spec.
pub const TX_COMPUTE_GAS_LIMIT: u64 = 1_000_000_000;
/// The base storage gas cost for setting a storage slot to a non-zero value for the `MINI_REX`
/// spec. Actual cost is dynamically scaled by SALT bucket capacity: `SSTORE_SET_GAS ×
/// (bucket_capacity / MIN_BUCKET_SIZE)`.
pub const SSTORE_SET_STORAGE_GAS: u64 = 2_000_000;
/// The base storage gas cost for creating a new account for the `MINI_REX` spec.
/// Actual cost is dynamically scaled by SALT bucket capacity: `NEW_ACCOUNT_GAS ×
/// (bucket_capacity / MIN_BUCKET_SIZE)`. Applied when transaction targets new account, CALL
/// with transfer to empty account, or CREATE operations.
pub const NEW_ACCOUNT_STORAGE_GAS: u64 = 2_000_000;
/// Storage gas cost per byte for code deposit during contract creation in `MINI_REX` spec.
pub const CODEDEPOSIT_STORAGE_GAS: u64 = 10_000;
/// The storage gas cost for `LOGDATA` for the `MINI_REX` spec, i.e., gas cost per byte for log
/// data.
pub const LOG_DATA_STORAGE_GAS: u64 = super::equivalence::LOGDATA * 10;
/// The storage gas cost for `LOGTOPIC` for the `MINI_REX` spec, i.e., gas cost per topic for
/// log.
pub const LOG_TOPIC_STORAGE_GAS: u64 = super::equivalence::LOGTOPIC * 10;
/// The additional gas cost for `CALLDATA` for the `MINI_REX` spec, i.e., gas cost per token
/// (one byte) for call data. This is charged on top of the calldata cost of standard EVM.
pub const CALLDATA_STANDARD_TOKEN_STORAGE_GAS: u64 =
super::equivalence::STANDARD_TOKEN_COST * 10;
/// The additional gas cost for EIP-7623 floor gas cost, i.e., gas cost per token (one byte)
/// for call data. This is charged on top of the floor cost of standard EVM.
pub const CALLDATA_STANDARD_TOKEN_STORAGE_FLOOR_GAS: u64 =
super::equivalence::TOTAL_COST_FLOOR_PER_TOKEN * 10;
/// The maximum amount of data allowed to generate from a block for the `MINI_REX` spec.
pub const BLOCK_DATA_LIMIT: u64 = 12 * 1024 * 1024 + 512 * 1024; // 12.5 MB
/// The maximum data size allowed per transaction for the `MINI_REX` spec.
/// Transactions exceeding this limit halt with `OutOfGas`, preserving remaining gas.
pub const TX_DATA_LIMIT: u64 = BLOCK_DATA_LIMIT * 25 / 100; // 25% of the block limit
/// The maximum amount of key-value updates allowed to generate from a block for the `MINI_REX`
/// spec.
pub const BLOCK_KV_UPDATE_LIMIT: u64 = 500_000;
/// The maximum amount of key-value updates allowed to generate from a transaction for the
/// `MINI_REX` spec.
pub const TX_KV_UPDATE_LIMIT: u64 = BLOCK_KV_UPDATE_LIMIT * 25 / 100; // 25% of the block limit
/// Gas limit after block environment or beneficiary data access.
/// When block environment data or beneficiary account data is accessed, the compute gas
/// is limited to force the transaction to complete quickly and prevent `DoS` attacks.
///
/// - **Pre-REX4**: This is an **absolute** cap on the transaction's total compute gas.
/// - **REX4+**: This is a **relative** cap — it limits post-access compute gas. The effective
/// limit becomes `current_usage + BLOCK_ENV_ACCESS_COMPUTE_GAS` at the point of access.
pub const BLOCK_ENV_ACCESS_COMPUTE_GAS: u64 = 20_000_000;
/// Gas limit after oracle contract access.
/// When oracle contract is accessed, the compute gas is limited to force the transaction
/// to complete quickly and prevent `DoS` attacks.
///
/// - **Pre-REX4**: This is an **absolute** cap on the transaction's total compute gas.
/// - **REX4+**: This is a **relative** cap — it limits post-access compute gas. The effective
/// limit becomes `current_usage + ORACLE_ACCESS_COMPUTE_GAS` at the point of access.
///
/// Note: If block environment was accessed first (20M compute gas limit), then oracle is
/// accessed, the compute gas will be further restricted to this lower limit (1M compute
/// gas).
pub const ORACLE_ACCESS_COMPUTE_GAS: u64 = 1_000_000;
}
/// Constants for the `REX2` spec.
pub mod rex2 {
/// Fixed overhead gas for the keylessDeploy operation.
/// This covers the cost of RLP decoding, signature recovery, and state filtering.
pub const KEYLESS_DEPLOY_OVERHEAD_GAS: u64 = 100_000;
}
/// Constants for the `REX3` spec.
pub mod rex3 {
/// Gas limit after oracle contract access for the `REX3` spec.
/// Increased from 1M (used in `MINI_REX` through `REX2`) to 20M, giving oracle-accessing
/// transactions more room for post-oracle computation.
pub const ORACLE_ACCESS_COMPUTE_GAS: u64 = 20_000_000;
}
/// Constants for the `REX4` spec.
pub mod rex4 {
/// Numerator of the fraction of parent's remaining resource budget forwarded to a child
/// frame. Applies to all four resource dimensions (data size, KV updates, compute gas,
/// state growth).
/// Child budget = `parent_remaining` * NUMERATOR / DENOMINATOR.
pub const FRAME_LIMIT_NUMERATOR: u64 = 98;
/// Denominator of the per-frame resource budget forwarding fraction.
pub const FRAME_LIMIT_DENOMINATOR: u64 = 100;
/// Additional call stipend for storage operations in CALL/CALLCODE with value transfer.
///
/// `MegaETH`'s 10x storage gas multiplier on LOG opcodes causes even a simple `LOG1` to cost
/// 4,500 gas (750 compute + 3,750 storage), exceeding the EVM's `CALL_STIPEND` of 2,300.
/// This breaks `transfer()` / `send()` to contracts that emit events in `receive()`.
///
/// When an internal CALL or CALLCODE transfers value (value > 0), the callee receives this
/// extra gas on top of the standard `CALL_STIPEND`.
/// The callee's compute gas limit remains at the original level (`forwarded_gas +
/// CALL_STIPEND`), so the extra gas can only be consumed by storage gas operations (e.g.,
/// the 10x LOG topic/data costs).
/// On return, unused `STORAGE_CALL_STIPEND` is burned — it is never returned to the caller.
pub const STORAGE_CALL_STIPEND: u64 = 23_000;
}
/// Constants for the `REX5` spec.
pub mod rex5 {
/// Floor for the gas limit assigned to REX5 pre-block system calls that opt
/// into the live block gas budget via
/// [`crate::MegaEvm::transact_system_call_with_gas_limit`] — currently the
/// `SequencerRegistry.applyPendingChanges()`, EIP-2935 history-storage, and
/// EIP-4788 beacon-roots pre-block calls.
///
/// The value (30M) matches the historical revm system-call default at the
/// time REX5 was specified — see the `gas_limit(30_000_000)` literal in
/// [`revm::handler::SystemCallTx::new_system_tx_with_caller`]'s `TxEnv` impl
/// (`revm-handler/src/system_call.rs`).
/// revm does not export this as a `pub const`, so we mirror the literal here
/// instead of aliasing it. Do NOT raise this value to follow upstream
/// changes — the floor must remain at the historical 30M to preserve
/// backward compatibility for REX5 chains whose block gas limit is smaller
/// than any new upstream default. Lifting it would silently increase the
/// minimum guaranteed budget and become observable via the `GAS` opcode
/// inside `applyPendingChanges()`.
///
/// Keeping the floor at the historical default ensures test harnesses or
/// chains configured with a sub-30M block gas limit still receive the
/// budget that pre-REX5 / EIP-2935 / EIP-4788 system calls have always
/// gotten.
pub const SYSTEM_CALL_GAS_LIMIT_FLOOR: u64 = 30_000_000;
}
/// Constants for the `REX` spec.
pub mod rex {
/// Additional storage gas cost added to transaction intrinsic gas for the `REX` spec.
/// This is charged on top of the base 21,000 intrinsic gas for all transactions.
pub const TX_INTRINSIC_STORAGE_GAS: u64 = 39_000;
/// The base storage gas cost for setting a storage slot to a non-zero value for the `REX` spec.
/// Actual cost is dynamically scaled by SALT bucket capacity: `SSTORE_SET_STORAGE_GAS_BASE ×
/// (bucket_capacity / MIN_BUCKET_SIZE - 1)`.
pub const SSTORE_SET_STORAGE_GAS_BASE: u64 = 20_000;
/// The base storage gas cost for creating a new account for the `REX` spec.
/// Actual cost is dynamically scaled by SALT bucket capacity: `NEW_ACCOUNT_STORAGE_GAS_BASE ×
/// (bucket_capacity / MIN_BUCKET_SIZE - 1)`.
pub const NEW_ACCOUNT_STORAGE_GAS_BASE: u64 = 25_000;
/// The base storage gas cost for creating a new contract for the `REX` spec.
/// Actual cost is dynamically scaled by SALT bucket capacity:
/// `CONTRACT_CREATION_STORAGE_GAS_BASE × (bucket_capacity / MIN_BUCKET_SIZE - 1)`.
pub const CONTRACT_CREATION_STORAGE_GAS_BASE: u64 = 32_000;
/// The maximum compute gas limit for a single transaction for the `REX` spec.
/// Transactions exceeding this limit fail on the compute-gas limit path.
/// The exact surface result depends on the current spec's top-level/frame-local semantics.
pub const TX_COMPUTE_GAS_LIMIT: u64 = 200_000_000;
/// The maximum data size limit for a single transaction for the `REX` spec.
/// Transactions exceeding this limit halt with `DataLimitExceeded`, preserving remaining gas.
pub const TX_DATA_LIMIT: u64 = 12 * 1024 * 1024 + 512 * 1024; // Same with the block data limit
/// The maximum key-value updates limit for a single transaction for the `REX` spec.
/// Transactions exceeding this limit halt with `KVUpdateLimitExceeded`, preserving remaining
/// gas.
pub const TX_KV_UPDATE_LIMIT: u64 = 500_000; // Same with the block kv update limit
/// The maximum state growth limit for a single transaction for the `REX` spec.
/// Transactions exceeding this limit halt with `StateGrowthLimitExceeded`, preserving remaining
/// gas.
pub const TX_STATE_GROWTH_LIMIT: u64 = 1000;
/// The maximum state growth limit for a block for the `REX` spec.
/// Blocks exceeding this limit halt with `StateGrowthLimitExceeded`, preserving remaining
/// gas.
pub const BLOCK_STATE_GROWTH_LIMIT: u64 = 1000;
}