fix(runtime): add fuel metering for engine-metered precompiles#276
fix(runtime): add fuel metering for engine-metered precompiles#276
Conversation
NITRO_VERIFIER, OAUTH2_VERIFIER, WASM_RUNTIME, and WEBAUTHN_VERIFIER were executing without charging gas because they don't self-meter via `_charge_fuel` syscall. Changes: - Add ENGINE_METERED_PRECOMPILES list and is_engine_metered_precompile() - Create wasmtime engine with consume_fuel=true and syscall_fuel_params - Pass consume_fuel flag through executor to SystemRuntime - Set fuel limit before execution and read remaining fuel after
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughPer-contract fuel metering added: types expose engine‑metered precompiles; build sets per-contract Changes
sequenceDiagram
participant Build as Build Process
participant Types as Types/Genesis
participant Executor as Runtime Executor
participant SysRT as SystemRuntime
participant WasmEngine as Wasmtime Engine
Build->>Types: is_engine_metered_precompile(address)
Types-->>Build: consume_fuel (bool)
Build->>Build: set per-contract compilation config (consume_fuel)
Executor->>Executor: resolve BytecodeOrHash (address/hash)
Executor->>SysRT: SystemRuntime::new(module, import_linker, code_hash, ctx, consume_fuel)
SysRT->>SysRT: compiled_module(code_hash, rwasm_module, consume_fuel)
alt consume_fuel = true
SysRT->>WasmEngine: use wasmtime_engine_with_consume_fuel()
else consume_fuel = false
SysRT->>WasmEngine: use wasmtime_engine()
end
SysRT->>WasmEngine: execute (reset/apply fuel if engine‑metered)
WasmEngine-->>SysRT: result or OutOfFuel trap
SysRT-->>Executor: return result / trap mapping
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Criterion results (vs baseline)Heads-up: runner perf is noisy; treat deltas as a smoke check. |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
crates/runtime/src/runtime/system_runtime.rs (2)
123-155:⚠️ Potential issue | 🟡 MinorCache key should include
consume_fuel.
COMPILED_MODULESis keyed only bycode_hash. If a module is ever compiled with differentconsume_fuelsettings, the cached module could be reused with the wrong engine, leading to incorrect metering or a panic when setting fuel.🔧 Suggested fix
- static COMPILED_MODULES: OnceLock<RwLock<HashMap<B256, Module>>> = OnceLock::new(); + static COMPILED_MODULES: OnceLock<RwLock<HashMap<(B256, bool), Module>>> = OnceLock::new(); let compiled_modules = COMPILED_MODULES.get_or_init(|| RwLock::new(HashMap::new())); + let cache_key = (code_hash, consume_fuel); // Fast path: read lock lookup. { let guard = compiled_modules.read().unwrap(); - if let Some(module) = guard.get(&code_hash) { + if let Some(module) = guard.get(&cache_key) { return module.clone(); } } // Slow path: compile and insert under write lock (with re-check). let mut guard = compiled_modules.write().unwrap(); - if let Some(module) = guard.get(&code_hash) { + if let Some(module) = guard.get(&cache_key) { return module.clone(); } ... - guard.insert(code_hash, module.clone()); + guard.insert(cache_key, module.clone());
262-293:⚠️ Potential issue | 🟡 MinorRemove debug logging from the hot execution path.
eprintln!on every execution will be noisy and adds overhead. Prefer a feature‑gated or structured logger.🔧 Suggested fix
- eprintln!("DEBUG: consume fuel");
🤖 Fix all issues with AI agents
In `@crates/genesis/build.rs`:
- Around line 89-101: The cache key must include the fuel instrumentation flag
so compiled artifacts for the same wasm bytecode but different fuel modes don't
clash: change the lookup and insertion on cache for GENESIS_CONTRACTS to use a
composite key of (contract.wasm_bytecode, should_charge_fuel) instead of only
contract.wasm_bytecode, compute should_charge_fuel via
is_engine_metered_precompile(address) before checking cache, and then continue
to call
default_compilation_config().with_consume_fuel(should_charge_fuel).with_builtins_consume_fuel(should_charge_fuel)
when compiling and store that compiled result under the composite key.
In `@crates/runtime/src/runtime/system_runtime.rs`:
- Around line 409-414: The remaining_fuel method currently prints a debug
eprintln! on the hot path; remove that eprintln! (or gate it behind a
non-hot-path debug facility) so remaining_fuel only returns the fuel.
Specifically, edit remaining_fuel to stop calling eprintln! with
compiled_runtime.store.data().fuel_limit and fuel; instead either drop the print
entirely or replace it with a conditional debug log (e.g., log::trace! or
cfg!(debug_assertions)) so compiled_runtime, store.get_fuel, and
store.data().fuel_limit are not written to stderr on every call.
In `@e2e/src/fuel.rs`:
- Around line 29-32: The seed balance uses a float-to-int cast which can lose
precision: replace U256::from(1e18 as u128) with an integer literal or other
integer constructor to avoid going through f64; update the call at
ctx.add_balance(caller, U256::from(...)) (related symbols: caller, ctx,
add_balance, U256, Address::ZERO) to use a precise integer like
1000000000000000000u128 (or construct the U256 via a safe helper) so the balance
is exact.
| for (address, contract) in GENESIS_CONTRACTS { | ||
| if cache.contains_key(contract.wasm_bytecode) { | ||
| continue; | ||
| } | ||
| // Most system precompiles manage fuel internally via `_charge_fuel` syscall. | ||
| // However, some precompiles (NITRO_VERIFIER, OAUTH2_VERIFIER, WASM_RUNTIME, | ||
| // WEBAUTHN_VERIFIER) don't self-meter, so they need fuel instrumentation. | ||
| let should_charge_fuel = is_engine_metered_precompile(address); | ||
|
|
||
| let config = default_compilation_config() | ||
| .with_consume_fuel(should_charge_fuel) | ||
| .with_builtins_consume_fuel(should_charge_fuel); | ||
|
|
There was a problem hiding this comment.
Include fuel mode in the compile cache key.
The cache is keyed only by contract.wasm_bytecode, but consume_fuel depends on the address. If the same bytecode is ever reused by both engine‑metered and self‑metered precompiles, the first compiled variant would be reused with the wrong fuel settings. Consider keying by (bytecode, should_charge_fuel) and updating the later lookup accordingly.
🔧 Suggested fix
- let mut cache = HashMap::new();
+ let mut cache: HashMap<(&'static [u8], bool), (B256, Bytes)> = HashMap::new();
- for (address, contract) in GENESIS_CONTRACTS {
- if cache.contains_key(contract.wasm_bytecode) {
+ for (address, contract) in GENESIS_CONTRACTS {
+ let should_charge_fuel = is_engine_metered_precompile(address);
+ let cache_key = (contract.wasm_bytecode, should_charge_fuel);
+ if cache.contains_key(&cache_key) {
continue;
}
- // Most system precompiles manage fuel internally via `_charge_fuel` syscall.
- // However, some precompiles (NITRO_VERIFIER, OAUTH2_VERIFIER, WASM_RUNTIME,
- // WEBAUTHN_VERIFIER) don't self-meter, so they need fuel instrumentation.
- let should_charge_fuel = is_engine_metered_precompile(address);
+ // Most system precompiles manage fuel internally via `_charge_fuel` syscall.
+ // However, some precompiles (NITRO_VERIFIER, OAUTH2_VERIFIER, WASM_RUNTIME,
+ // WEBAUTHN_VERIFIER) don't self-meter, so they need fuel instrumentation.
let config = default_compilation_config()
.with_consume_fuel(should_charge_fuel)
.with_builtins_consume_fuel(should_charge_fuel);
...
- cache.insert(contract.wasm_bytecode, result.clone());
+ cache.insert(cache_key, result.clone());- let (rwasm_bytecode_hash, rwasm_bytecode) =
- rwasm_artifacts.get(contract.wasm_bytecode).unwrap().clone();
+ let should_charge_fuel = is_engine_metered_precompile(address);
+ let (rwasm_bytecode_hash, rwasm_bytecode) = rwasm_artifacts
+ .get(&(contract.wasm_bytecode, should_charge_fuel))
+ .unwrap()
+ .clone();🤖 Prompt for AI Agents
In `@crates/genesis/build.rs` around lines 89 - 101, The cache key must include
the fuel instrumentation flag so compiled artifacts for the same wasm bytecode
but different fuel modes don't clash: change the lookup and insertion on cache
for GENESIS_CONTRACTS to use a composite key of (contract.wasm_bytecode,
should_charge_fuel) instead of only contract.wasm_bytecode, compute
should_charge_fuel via is_engine_metered_precompile(address) before checking
cache, and then continue to call
default_compilation_config().with_consume_fuel(should_charge_fuel).with_builtins_consume_fuel(should_charge_fuel)
when compiling and store that compiled result under the composite key.
There was a problem hiding this comment.
@dmitry123, thanks for confirming! Since this could affect correctness if the same bytecode is ever shared between differently-metered precompiles, would you like to address it in this PR, or would you prefer to track it as a follow-up issue?
| let caller = Address::ZERO; | ||
| let mut ctx = EvmTestingContext::default().with_full_genesis(); | ||
| ctx.add_balance(caller, U256::from(1e18 as u128)); | ||
|
|
There was a problem hiding this comment.
Avoid float‑to‑int cast for the seed balance.
1e18 as u128 goes through f64 and can lose precision. Use an integer literal instead.
🐛 Suggested fix
- ctx.add_balance(caller, U256::from(1e18 as u128));
+ ctx.add_balance(caller, U256::from(1_000_000_000_000_000_000u128));🤖 Prompt for AI Agents
In `@e2e/src/fuel.rs` around lines 29 - 32, The seed balance uses a float-to-int
cast which can lose precision: replace U256::from(1e18 as u128) with an integer
literal or other integer constructor to avoid going through f64; update the call
at ctx.add_balance(caller, U256::from(...)) (related symbols: caller, ctx,
add_balance, U256, Address::ZERO) to use a precise integer like
1000000000000000000u128 (or construct the U256 via a safe helper) so the balance
is exact.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/runtime/src/runtime/system_runtime.rs (1)
123-156:⚠️ Potential issue | 🟠 MajorInclude
consume_fuelin the compiled-module cache key.
COMPILED_MODULESis keyed only bycode_hash, but the compiled module’s engine configuration differs based onconsume_fuel. If the samecode_hashis ever used in both modes, the cache can return a module built with the wrong fuel configuration, disabling (or incorrectly enabling) engine metering.🔧 Proposed fix (separate cache entries by mode)
- static COMPILED_MODULES: OnceLock<RwLock<HashMap<B256, Module>>> = OnceLock::new(); + static COMPILED_MODULES: OnceLock<RwLock<HashMap<(B256, bool), Module>>> = OnceLock::new(); - if let Some(module) = guard.get(&code_hash) { + if let Some(module) = guard.get(&(code_hash, consume_fuel)) { return module.clone(); } - if let Some(module) = guard.get(&code_hash) { + if let Some(module) = guard.get(&(code_hash, consume_fuel)) { return module.clone(); } - guard.insert(code_hash, module.clone()); + guard.insert((code_hash, consume_fuel), module.clone());
🤖 Fix all issues with AI agents
In `@crates/runtime/src/runtime/system_runtime.rs`:
- Around line 504-531: The engine is built with syscall_fuel_params derived from
a static import_linker_v1_preview() inside wasmtime_engine_with_consume_fuel(),
which can diverge from the import_linker passed into SystemRuntime::new();
change the design so syscall_fuel_params are computed from the same ImportLinker
used for instantiation: either (a) move the engine construction out of
wasmtime_engine_with_consume_fuel() into code that receives the ImportLinker
from SystemRuntime::new() and call build_syscall_fuel_params(import_linker)
there, or (b) add an explicit assertion in SystemRuntime::new() that the passed
import_linker equals import_linker_v1_preview() and document this invariant;
update references to build_syscall_fuel_params,
wasmtime_engine_with_consume_fuel, and SystemRuntime::new accordingly so the
engine and instantiation always use the same ImportLinker for fuel parameter
calculation.
| /// Returns the shared Wasmtime engine instance with fuel metering enabled. | ||
| /// | ||
| /// Used for engine-metered precompiles (NITRO, OAUTH2, WASM_RUNTIME, WEBAUTHN). | ||
| /// These precompiles don't self-meter via `_charge_fuel` syscall, so the engine | ||
| /// must automatically charge fuel for: | ||
| /// - wasm instructions (via `consume_fuel=true`) | ||
| /// - syscall/builtin calls (via `syscall_fuel_params`) | ||
| /// | ||
| /// TODO(d1r1): move to rwasm crate - add async_support parameter to | ||
| /// factory_wasmtime_engine_with_linker and reuse it here | ||
| fn wasmtime_engine_with_consume_fuel() -> &'static Engine { | ||
| static ENGINE: OnceLock<Engine> = OnceLock::new(); | ||
| ENGINE.get_or_init(|| { | ||
| let import_linker = fluentbase_types::import_linker_v1_preview(); | ||
|
|
||
| let mut cfg = Config::new(); | ||
| cfg.strategy(Strategy::Cranelift); | ||
| cfg.collector(wasmtime::Collector::Null); | ||
| cfg.max_wasm_stack(N_MAX_STACK_SIZE * size_of::<u32>()); | ||
| cfg.async_support(false); // Must be false for sync instantiate()/call() | ||
| cfg.wasm_memory64(false); | ||
| cfg.memory_init_cow(false); | ||
| cfg.cranelift_opt_level(OptLevel::Speed); | ||
| cfg.parallel_compilation(true); | ||
| cfg.consume_fuel(true); | ||
| cfg.syscall_fuel_params(build_syscall_fuel_params(&import_linker)); | ||
|
|
||
| Engine::new(&cfg).unwrap() |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for all SystemRuntime::new call sites and related linker usage
rg -n -C5 'SystemRuntime::new\(' --type rustRepository: fluentlabs-xyz/fluentbase
Length of output: 927
🏁 Script executed:
#!/bin/bash
# Search for import_linker_v1_preview usage across the codebase
rg -n -C3 'import_linker_v1_preview' --type rustRepository: fluentlabs-xyz/fluentbase
Length of output: 4490
🏁 Script executed:
#!/bin/bash
# Find the SystemRuntime::new signature to understand its parameters
rg -n 'fn new\(' crates/runtime/src/runtime/system_runtime.rs -A 10Repository: fluentlabs-xyz/fluentbase
Length of output: 528
🏁 Script executed:
#!/bin/bash
# Get the full context around wasmtime_engine_with_consume_fuel function and its usage
cat -n crates/runtime/src/runtime/system_runtime.rs | sed -n '504,531p'Repository: fluentlabs-xyz/fluentbase
Length of output: 1581
🏁 Script executed:
#!/bin/bash
# Check if SystemRuntime::new stores or uses the passed import_linker parameter
ast-grep --pattern 'fn new($_, import_linker: $_) {
$$$
}'Repository: fluentlabs-xyz/fluentbase
Length of output: 51
🏁 Script executed:
#!/bin/bash
# Get the full SystemRuntime::new implementation
cat -n crates/runtime/src/runtime/system_runtime.rs | sed -n '180,240p'Repository: fluentlabs-xyz/fluentbase
Length of output: 2859
🏁 Script executed:
#!/bin/bash
# Check if import_linker is stored or used in SystemRuntime struct
rg -n 'struct SystemRuntime' crates/runtime/src/runtime/system_runtime.rs -A 20Repository: fluentlabs-xyz/fluentbase
Length of output: 1091
🏁 Script executed:
#!/bin/bash
# Check how import_linker is used after being passed to new()
rg -n 'import_linker' crates/runtime/src/runtime/system_runtime.rs -B 2 -A 2Repository: fluentlabs-xyz/fluentbase
Length of output: 2284
🏁 Script executed:
#!/bin/bash
# Check what RuntimeFactoryExecutor stores and how it's initialized
cat -n crates/runtime/src/executor.rs | sed -n '100,140p'Repository: fluentlabs-xyz/fluentbase
Length of output: 1490
Ensure syscall fuel params match the actual ImportLinker.
The engine's syscall_fuel_params are computed from a static import_linker_v1_preview() at engine creation time (line 517), while SystemRuntime::new() accepts a separate import_linker parameter for instantiation. If the two differ, fuel metering will charge incorrect costs. Currently all callers pass import_linker_v1_preview(), but this coupling is fragile: derive syscall_fuel_params from the linker passed to SystemRuntime::new(), or guarantee via documentation/assertion that the linker is always import_linker_v1_preview().
🤖 Prompt for AI Agents
In `@crates/runtime/src/runtime/system_runtime.rs` around lines 504 - 531, The
engine is built with syscall_fuel_params derived from a static
import_linker_v1_preview() inside wasmtime_engine_with_consume_fuel(), which can
diverge from the import_linker passed into SystemRuntime::new(); change the
design so syscall_fuel_params are computed from the same ImportLinker used for
instantiation: either (a) move the engine construction out of
wasmtime_engine_with_consume_fuel() into code that receives the ImportLinker
from SystemRuntime::new() and call build_syscall_fuel_params(import_linker)
there, or (b) add an explicit assertion in SystemRuntime::new() that the passed
import_linker equals import_linker_v1_preview() and document this invariant;
update references to build_syscall_fuel_params,
wasmtime_engine_with_consume_fuel, and SystemRuntime::new accordingly so the
engine and instantiation always use the same ImportLinker for fuel parameter
calculation.
| // If fuel metering is enabled, set the fuel limit before execution. | ||
| // The store is reused, so we must reset fuel for each new call. | ||
| if self.consume_fuel { | ||
| eprintln!("DEBUG: consume fuel"); |
There was a problem hiding this comment.
Remove println(s) from the code
| for (address, contract) in GENESIS_CONTRACTS { | ||
| if cache.contains_key(contract.wasm_bytecode) { | ||
| continue; | ||
| } | ||
| // Most system precompiles manage fuel internally via `_charge_fuel` syscall. | ||
| // However, some precompiles (NITRO_VERIFIER, OAUTH2_VERIFIER, WASM_RUNTIME, | ||
| // WEBAUTHN_VERIFIER) don't self-meter, so they need fuel instrumentation. | ||
| let should_charge_fuel = is_engine_metered_precompile(address); | ||
|
|
||
| let config = default_compilation_config() | ||
| .with_consume_fuel(should_charge_fuel) | ||
| .with_builtins_consume_fuel(should_charge_fuel); | ||
|
|
| if let Err(trap_code) = result.as_ref() { | ||
| // OutOfFuel is expected for engine-metered precompiles when fuel is exhausted. | ||
| if *trap_code == TrapCode::OutOfFuel { | ||
| return Err(TrapCode::OutOfFuel); |
There was a problem hiding this comment.
Hm, yes, but we should guarantee that it never happens inside stateful runtimes (evm, svm, etc). Maybe it's better to add a comment here indicating that this is true only for stateless contracts. Statefullness means it stores intermediary state inside memory (aka can do interurptions).
| /// | ||
| /// TODO(d1r1): move to rwasm crate - add async_support parameter to | ||
| /// factory_wasmtime_engine_with_linker and reuse it here | ||
| fn wasmtime_engine_with_consume_fuel() -> &'static Engine { |
There was a problem hiding this comment.
Why not reuse an existing method but with an extra consume_fuel flag?
Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz>
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
contracts/eip2935/tests.rs (1)
69-89:⚠️ Potential issue | 🟡 MinorComment claims no mutation, but
clone()shares state.
TestingContextImpl::cloneusesRc<RefCell<...>>, so input/caller/block updates mutate the shared context. Either update the comment or deep-clone if isolation is intended.📝 Suggested doc update
-/// This helper does **not** mutate the provided `sdk` in-place. Instead, it clones it, -/// configures the call parameters (input/caller/block number), runs the entrypoint, and then -/// extracts the output. +/// This helper clones the context handle (shared `Rc`), so it mutates shared state. +/// Each call overwrites input/caller/block_number on the shared context before execution, +/// then runs the entrypoint and extracts the output.
🧹 Nitpick comments (1)
crates/testing/src/host.rs (1)
87-89: Clarify fuel vs gas units forconsumed_fuel.
This accessor returns raw fuel units; a short doc note helps prevent misuse as gas.📝 Suggested doc clarification
+ /// Returns fuel consumed in fuel units (not gas). Divide by FUEL_DENOM_RATE to get gas. pub fn consumed_fuel(&self) -> u64 { self.inner.borrow().consumed_fuel }
Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
crates/runtime/src/runtime/system_runtime.rs (2)
128-156:⚠️ Potential issue | 🔴 CriticalCache key must include
consume_fuelto avoid returning wrong module.The
COMPILED_MODULEScache uses onlycode_hashas the key, but modules are now compiled differently based onconsume_fuel. If the samecode_hashis first compiled withconsume_fuel=falseand later requested withconsume_fuel=true, the cache will return the wrong module (without fuel metering enabled).🐛 Proposed fix to use composite cache key
- pub fn compiled_module( - code_hash: B256, - rwasm_module: RwasmModule, - consume_fuel: bool, - ) -> Module { - static COMPILED_MODULES: OnceLock<RwLock<HashMap<B256, Module>>> = OnceLock::new(); + pub fn compiled_module( + code_hash: B256, + rwasm_module: RwasmModule, + consume_fuel: bool, + ) -> Module { + static COMPILED_MODULES: OnceLock<RwLock<HashMap<(B256, bool), Module>>> = OnceLock::new(); let compiled_modules = COMPILED_MODULES.get_or_init(|| RwLock::new(HashMap::new())); + let cache_key = (code_hash, consume_fuel); // Fast path: read lock lookup. { let guard = compiled_modules.read().unwrap(); - if let Some(module) = guard.get(&code_hash) { + if let Some(module) = guard.get(&cache_key) { return module.clone(); } } // Slow path: compile and insert under write lock (with re-check). let mut guard = compiled_modules.write().unwrap(); - if let Some(module) = guard.get(&code_hash) { + if let Some(module) = guard.get(&cache_key) { return module.clone(); } // ... compilation logic ... - guard.insert(code_hash, module.clone()); + guard.insert(cache_key, module.clone()); module }
100-107:⚠️ Potential issue | 🔴 CriticalThread-local runtime cache also needs
consume_fuelin key.Same issue as
COMPILED_MODULES: theCOMPILED_RUNTIMEScache uses onlycode_hashas the key. If the same code is executed with differentconsume_fuelsettings, the cached runtime with the wrong fuel configuration will be returned.🐛 Proposed fix
thread_local! { - pub static COMPILED_RUNTIMES: RefCell<HashMap<B256, Rc<RefCell<CompiledRuntime>>>> = + pub static COMPILED_RUNTIMES: RefCell<HashMap<(B256, bool), Rc<RefCell<CompiledRuntime>>>> = RefCell::new(HashMap::new()); }And update the lookup/insert in
new():let compiled_runtime = COMPILED_RUNTIMES.with_borrow_mut(|compiled_runtimes| { - if let Some(compiled_runtime) = compiled_runtimes.get(&code_hash).cloned() { + let cache_key = (code_hash, consume_fuel); + if let Some(compiled_runtime) = compiled_runtimes.get(&cache_key).cloned() { return compiled_runtime; } // ... instantiation logic ... - compiled_runtimes.insert(code_hash, compiled_runtime.clone()); + compiled_runtimes.insert(cache_key, compiled_runtime.clone()); compiled_runtime });Also applies to: 187-226
🤖 Fix all issues with AI agents
In `@e2e/src/universal_token.rs`:
- Around line 493-497: The test assertion uses hex! with a "0x" prefix which the
hex-literal macro rejects; update the hex literal in the assertion comparing
result.output() to remove the "0x" prefix inside the hex!("...") call (i.e.,
change hex!("0x4e48...") to hex!("4e48...") in the assert_eq! that compares
result.output().unwrap_or_default().as_ref()) so it matches other hex! usages in
universal_token.rs.
| assert!(!result.is_success()); | ||
| assert_eq!( | ||
| result, | ||
| ExecutionResult::Revert { | ||
| gas_used: 22_210, | ||
| output: hex!( | ||
| "0x4e487b7100000000000000000000000000000000000000000000000000000000e450d38c" | ||
| ) | ||
| .into() | ||
| } | ||
| result.output().unwrap_or_default().as_ref(), | ||
| hex!("0x4e487b7100000000000000000000000000000000000000000000000000000000e450d38c") | ||
| ); |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
hex! macro Rust hex literals 0x prefix support
💡 Result:
-
hex_literal::hex!(RustCrypto “hex-literal”) does not support a0xprefix. Its input strings may contain only hex digits plus a small set of ignored formatting characters (e.g., whitespace; in newer versions also:). Any other character (likex) is unsupported and will cause a compile-time error. [1], [2]- So write
hex!("DEADBEEF"), nothex!("0xDEADBEEF"). [1], [2]
- So write
-
If you specifically want
0x...-prefixed hex strings, use a different macro/crate that supports it, e.g.:hexlit::hex!, which showshex!("0xDEADBEEF")working in its docs. [3]hexhex::hex_literal!, which also documentshex_literal!("0xc0ffee"). [4]
Sources:
[1] https://docs.rs/hex-literal/latest
[2] https://docs.rs/hex-literal/
[3] https://docs.rs/hexlit
[4] https://docs.rs/hexhex
🏁 Script executed:
# Find the file and check other hex! usages
fd -t f universal_token.rs -x wc -l {}Repository: fluentlabs-xyz/fluentbase
Length of output: 148
🏁 Script executed:
# Search for other hex! macro usages in the file to see the pattern
rg "hex!\(" e2e/src/universal_token.rs -A 1 | head -40Repository: fluentlabs-xyz/fluentbase
Length of output: 764
Remove the 0x prefix from the hex literal—it will cause a compile-time error.
The hex! macro from hex-literal does not support the 0x prefix. All other usages in this file omit it (e.g., hex!("000000...")); this is the only occurrence with the prefix.
Fix
- hex!("0x4e487b7100000000000000000000000000000000000000000000000000000000e450d38c")
+ hex!("4e487b7100000000000000000000000000000000000000000000000000000000e450d38c")🤖 Prompt for AI Agents
In `@e2e/src/universal_token.rs` around lines 493 - 497, The test assertion uses
hex! with a "0x" prefix which the hex-literal macro rejects; update the hex
literal in the assertion comparing result.output() to remove the "0x" prefix
inside the hex!("...") call (i.e., change hex!("0x4e48...") to hex!("4e48...")
in the assert_eq! that compares result.output().unwrap_or_default().as_ref()) so
it matches other hex! usages in universal_token.rs.
Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@contracts/eip2935/lib.rs`:
- Around line 124-128: The comment above the error-return is wrong: change the
comment referring to "Storage write" to correctly indicate that sdk.storage() is
a read operation (e.g., "Storage read can't fail..."). Also fix the fuel units
when charging on success: multiply GAS_RETRIEVE_SUCCESS_BRANCH by
FUEL_DENOM_RATE when calling sdk.charge_fuel (i.e., use result.fuel_consumed +
GAS_RETRIEVE_SUCCESS_BRANCH * FUEL_DENOM_RATE) so units match; update the
sdk.charge_fuel call accordingly.
- Line 86: The code adds GAS_SUBMIT_SUCCESS_BRANCH (EVM gas units) directly to
result.fuel_consumed (already in fuel units), causing under-charging; update the
call to sdk.charge_fuel so the gas constant is converted by FUEL_DENOM_RATE
(i.e., add GAS_SUBMIT_SUCCESS_BRANCH * FUEL_DENOM_RATE or use the same
conversion helper pattern as charge_and_panic) and ensure any necessary
casts/checked multiplication to match the fuel type; adjust within the scope of
the sdk.charge_fuel(...) invocation that references result.fuel_consumed and
GAS_SUBMIT_SUCCESS_BRANCH.
| if !result.status.is_ok() { | ||
| // Storage write here can't fail, even if it fails, it causes trap and charges all gas available | ||
| return Err(result.status); | ||
| } | ||
| // Load the hash. | ||
| let hash_key = user_requested_block_number % U256::from(EIP2935_HISTORY_SERVE_WINDOW); | ||
| let hash_value = sdk.storage(&hash_key).ok()?; | ||
| sdk.write(hash_value.to_be_bytes::<{ U256::BYTES }>()); | ||
| sdk.charge_fuel(result.fuel_consumed + GAS_RETRIEVE_SUCCESS_BRANCH); |
There was a problem hiding this comment.
Same unit mismatch and incorrect comment.
Two issues in this block:
-
Line 125: Comment says "Storage write" but
sdk.storage()is a read operation (copy-paste from line 83). -
Line 128: Same unit mismatch as line 86 —
GAS_RETRIEVE_SUCCESS_BRANCHshould be multiplied byFUEL_DENOM_RATE.
🐛 Proposed fix
let result = sdk.storage(&slot);
if !result.status.is_ok() {
- // Storage write here can't fail, even if it fails, it causes trap and charges all gas available
+ // Storage read here can't fail, even if it fails, it causes trap and charges all gas available
return Err(result.status);
}
- sdk.charge_fuel(result.fuel_consumed + GAS_RETRIEVE_SUCCESS_BRANCH);
+ sdk.charge_fuel(result.fuel_consumed + GAS_RETRIEVE_SUCCESS_BRANCH * FUEL_DENOM_RATE);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if !result.status.is_ok() { | |
| // Storage write here can't fail, even if it fails, it causes trap and charges all gas available | |
| return Err(result.status); | |
| } | |
| // Load the hash. | |
| let hash_key = user_requested_block_number % U256::from(EIP2935_HISTORY_SERVE_WINDOW); | |
| let hash_value = sdk.storage(&hash_key).ok()?; | |
| sdk.write(hash_value.to_be_bytes::<{ U256::BYTES }>()); | |
| sdk.charge_fuel(result.fuel_consumed + GAS_RETRIEVE_SUCCESS_BRANCH); | |
| if !result.status.is_ok() { | |
| // Storage read here can't fail, even if it fails, it causes trap and charges all gas available | |
| return Err(result.status); | |
| } | |
| sdk.charge_fuel(result.fuel_consumed + GAS_RETRIEVE_SUCCESS_BRANCH * FUEL_DENOM_RATE); |
🤖 Prompt for AI Agents
In `@contracts/eip2935/lib.rs` around lines 124 - 128, The comment above the
error-return is wrong: change the comment referring to "Storage write" to
correctly indicate that sdk.storage() is a read operation (e.g., "Storage read
can't fail..."). Also fix the fuel units when charging on success: multiply
GAS_RETRIEVE_SUCCESS_BRANCH by FUEL_DENOM_RATE when calling sdk.charge_fuel
(i.e., use result.fuel_consumed + GAS_RETRIEVE_SUCCESS_BRANCH * FUEL_DENOM_RATE)
so units match; update the sdk.charge_fuel call accordingly.
Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz>
Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz>
| /// ------------------------------ | ||
| /// Gas accounting (Prague fork) | ||
| /// ------------------------------ | ||
| /// These are "entry-to-throw" gas totals for the *read* path reverts, | ||
| /// derived from the exact opcode sequences in the EVM snippet. | ||
| /// | ||
| /// Throw tail in snippet: | ||
| /// JUMPDEST (1) + PUSH0 (3) + PUSH0 (3) + REVERT (0) = 7 | ||
| /// | ||
| /// Prefix gate (caller != SYSADDR; jump not taken): | ||
| /// CALLER(2) + PUSH20(3) + EQ(3) + JUMPI(10) = 18 | ||
| /// | ||
| /// Length check block: | ||
| /// PUSH1(3) + CALLDATASIZE(2) + SUB(3) + JUMPI(10) = 18 | ||
| /// | ||
| /// Future-block check block: | ||
| /// PUSH0(3) + CALLDATALOAD(3) + PUSH1(3) + NUMBER(2) + SUB(3) | ||
| /// + DUP2(3) + GT(3) + JUMPI(10) = 30 | ||
| /// | ||
| /// Too-old check block: | ||
| /// PUSH(3) + DUP2(3) + NUMBER(2) + SUB(3) + GT(3) + JUMPI(10) = 24 | ||
| /// | ||
| /// Totals: | ||
| /// - Bad length: 18 + 18 + 7 = 43 | ||
| /// - Future block: 18 + 18 + 30 + 7 = 73 | ||
| /// - Too old block: 18 + 18 + 30 + 24 + 7 = 97 | ||
| const GAS_BAD_BLOCK_INPUT_BRANCH: u64 = 43; | ||
| const GAS_INVALID_BLOCK_BRANCH: u64 = 73; | ||
| const GAS_BLOCK_TOO_OLD_BRANCH: u64 = 97; | ||
| const GAS_RETRIEVE_SUCCESS_BRANCH: u64 = 113; | ||
| const GAS_SUBMIT_SUCCESS_BRANCH: u64 = 41; |
There was a problem hiding this comment.
https://ethereum.org/developers/docs/evm/opcodes/
GAS_BAD_BLOCK_INPUT_BRANCH = 21 + 21 + 5 = 47
GAS_INVALID_BLOCK_BRANCH = 21 + 21 + 32 + 5 = 79
GAS_BLOCK_TOO_OLD_BRANCH = 21 + 21 + 32 + 27 + 5 = 106
GAS_RETRIEVE_SUCCESS_BRANCH = 21 + 21 + 32 + 27 + 24 = 125
GAS_SUBMIT_SUCCESS_BRANCH = 21 + 22 = 43
; --- prefix gate: if caller == 0xffff..fffe jump to write-path @0x46 ---
caller ; 2
push20 0xfffffffffffffffffffffffffffffffffffffffe ; 3
eq ; 3
push1 0x46 ; 3
jumpi ; 10
; prefix subtotal = 21
; --- read-path length gate: if (calldatasize - 0x20) != 0 then revert @0x42 ---
push1 0x20 ; 3
calldatasize ; 2
sub ; 3
push1 0x42 ; 3
jumpi ; 10
; length-check subtotal = 21
; --- load arg (slot selector / block number) from calldata[0:32] ---
push0 ; 2
calldataload ; 3
; --- future-block gate: if arg > (number - 1) then revert @0x42 ---
push1 0x01 ; 3
number ; 2
sub ; 3
dup2 ; 3
gt ; 3
push1 0x42 ; 3
jumpi ; 10
; future-check subtotal = 32
; --- too-old gate: if (number - arg) > 0x1fff then revert @0x42 ---
push2 0x1fff ; 3
dup2 ; 3
number ; 2
sub ; 3
gt ; 3
push1 0x42 ; 3
jumpi ; 10
; too-old subtotal = 27
; --- read: sload[(arg mod 0x1fff)] and return it as 32 bytes ---
push2 0x1fff ; 3
swap1 ; 3
mod ; 5
sload ; syscall
push0 ; 2
mstore ; 3 + memory expansion (3)
push1 0x20 ; 3
push0 ; 2
return ; 0 + memory expansion (0)
; --- revert handler @0x42 ---
jumpdest ; 1
push0 ; 2
push0 ; 2
revert ; 0
; throw-tail subtotal = 5
; --- write-path @0x46: store (arg mod (number-1) mod 0x1fff) into s[ (number-1) mod 0x1fff ] ---
jumpdest ; 1
push0 ; 2
calldataload ; 3
push2 0x1fff ; 3
push1 0x01 ; 3
number ; 2
sub ; 3
mod ; 5
sstore ; syscall
stop ; 0
| let hash_key = user_requested_block_number % U256::from(EIP2935_HISTORY_SERVE_WINDOW); | ||
| let hash_value = sdk.storage(&hash_key).ok()?; | ||
| sdk.write(hash_value.to_be_bytes::<{ U256::BYTES }>()); | ||
| sdk.charge_fuel(result.fuel_consumed + GAS_RETRIEVE_SUCCESS_BRANCH * FUEL_DENOM_RATE); |
There was a problem hiding this comment.
Note that fuel_consumed is always 0 for system precompiles
impl<API: NativeAPI + CryptoAPI> StorageAPI for SystemContextImpl<API> {
fn write_storage(&mut self, slot: U256, value: U256) -> SyscallResult<()> {
self.state.storage.write_storage(slot, value);
// Note: Storage write here can't fail, that's why we always return `Ok`
SyscallResult::default()
}
fn storage(&self, slot: &U256) -> SyscallResult<U256> {
if let Some(value) = self.state.storage.storage(slot) {
return SyscallResult::new(*value, 0, 0, ExitCode::Ok);
};
debug_log!("a missing storage slot detected at: {}", slot);
// We return here a `MissingStorageSlot`, but this error should be at user-level, because
// an attacker might intentionally pass incorrect params into the function
SyscallResult::new(U256::ZERO, 0, 0, ExitCode::MissingStorageSlot)
}
}There was a problem hiding this comment.
This also means that universal token runtime do not charge for any SLOADs / SSTOREs performed as the slot reads / writes occur outside of the program (in the executor)
fluentbase/crates/revm/src/executor.rs
Line 604 in d978625
There was a problem hiding this comment.
Ideally for sloads and sstores we should charge the gas in the executor, just before the sloads and sstore operations happen.
There was a problem hiding this comment.
How about the universal token runtime, the sloads and sstores there are not metered
There was a problem hiding this comment.
We don't charge for Universal Token, because of 2 reasons:
- it's cheap (~100 gas per storage read since the contract enforces access lists that makes all storage slots warm by default)
- it's just an implementtion detail where we can change the way how storage is managed, for example, by using metadata storage that we already have (a linear storage)
Are there any real risks if we keep these storage ops free of charge?
Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz>
Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz>
Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz>
Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz>
… list preparation now) Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz>
* docs(contracts): fix incorrect link (#189) * fix: migrate wasm to the latest version (#193) * fix: migrate wasm to the latest version * fix: update lock files Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * feat(sdk-derive): add constructor macro and docs * refactor(router): remove function_id attribute from generated code Remove function_id attributes from generated impl blocks and eliminate the unnecessary import statement. The function_id attributes are already processed during macro expansion and don't need to be present in the final generated code. This change makes the generated code cleaner and removes the dependency on an empty proc macro that was only acting as a placeholder. * fix(constructor): fix undefined variable error in deploy method Fix the deploy method generation that was incorrectly referencing undefined variables (param0, param1, param2) in the else branch. The shared generate_deploy_body method now properly handles all parameter counts without conditional branches. Refactor duplicate code between router and constructor macros into a shared method in ParsedMethod for better maintainability. * refactor(derive): unify Contract and Storage macros Remove redundant Contract implementation and unify it with Storage macro. Both macros now share the same underlying implementation, with Contract for main contracts and Storage for nested structures. BREAKING CHANGE: The old Contract macro implementation has been replaced. Projects using #[derive(Contract)] should still work but now use the Storage implementation under the hood. * chore: bump to v0.4.6-dev * feat(universal-token): universal token implementation for cross-runtime interaction (#180) * feat(svm): extract erc20 available actions to reuse inside spl-token processing * feat(svm): fix root Makefile; fix cargo.toml of solana-program-state-usage * feat(universal-token): universal token: refactor; get rid of custom logic (reuse as much token2022 logic as possible); added authorization validation and significantly simplified accounts reconstruction logic, instruction type validation, action type validation; adapted unite tests from token2022; added e2e tests demonstrating token creation, initialisation, transfers etc; added e2e tests showing work through solana app (using cpi) * feat(universal-token): support multiple universal token contracts per address when creating through solana app * feat(universal-token): split some svm codebase for reuse * feat(universal-token): added events logging through emit_log for all significant events * feat(universal-token): added ABI mappings + e2e tests * feat(universal-token): added ABI mappings * feat(universal-token): added ABI mappings * feat(universal-token): added ABI mappings * feat(universal-token): added benchmark * feat(universal-token): fix benchmark * feat(universal-token): refactor abi params * feat(universal-token): fix tests * feat(universal-token): added approve and revoke ABIs * feat(universal-token): added the rest ABI mappings, some tests, parameters ser/deser impls * feat(universal-token): tests for approve, set-authority, burn * feat(universal-token): tests for freeze, thaw * feat(universal-token): tests for close_account * feat(universal-token): small fixes * feat(universal-token): sync params for signatures; added support for allowance * feat(universal-token): added support for requesting account decimals * feat(universal-token): small fixes * feat(universal-token): disable error text output checks in e2e * feat(universal-token): cover error text output checks in e2e with feature * feat(universal-token): replace some expects with error mapping * feat(universal-token): cleanup * feat(universal-token): fix bench * feat(universal-token): fix typo * feat(universal-token): fix balance for bench * feat(universal-token): change settings for benches * feat(universal-token): cleanup * feat(universal-token): rename * feat(universal-token): cleanup * feat(universal-token): more tests for svm using universal token * added more test for universal token when working through svm cpi; fix deps problem when building solana_program example * feat(build): add standalone constructor macro support for abi generation - Parse #[constructor] attributes in addition to #[router] - Extract struct definitions from constructor parameters - Prioritize standalone constructors over router-embedded ones - Maintain backward compatibility with existing router-only contracts * refactor(runtime): new runtime & runtime bug fixes (#191) * refactor(runtime): make runtime lock-free, fix issue with warming up cache from a different thread, make import-linker arc, add warmup for all evm precompiled contracts in evm-e2e tests Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: fix bug with removing fuel opcodes for runtime contracts, new execution runtime w/ wasmtime disabled, fix passing full evm e2e testing suite Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * feat(runtime): new execution runtime, add bench pipeline, run wasmtime & rwasm tests in CI/CD, new revm-rwasm with `RwasmModule` cache, temporarly disable incepstor, add heap reset extern function, fix wasmtime warmups Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * ci: fix running bench Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * ci: fix running bench Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore(runtime): add docs for runtime crate Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * ci: fix benches Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * ci: update criterion (it has baseline option) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * ci: ignore tests in benches Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * ci: fix running benches Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * ci: let's build w/o baseline Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(revm): fix revm inspector (now it extracts stack params that are important for explorer internal transfer indexing) (#196) * fix(revm): fix revm inspector (now it extracts stack params that are important for explorer internal transfer indexing) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: disable blake2f tests from good coverage tests Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: bump version to v0.4.7-dev Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: loosing stack for inspector in release mode (#197) * chore: bump version to v0.4.8-dev * fix: add missing reset `call_id` function (#198) * fix: missing `call_id` reset for system calls (#199) * chore: bump version to v0.4.9-dev, update rwasm dependency (w/ disabled wasmtime parallel builds) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * feat: implement new runtime upgrade (#200) * fix: bump version to v0.4.10-dev * feat(weierstrass-curves): new crypto runtime (#201) * feat(runtime): refactoring weierstrass curves: bls, bn254, and 256k1/r1 * feat(e2e): fixed the svm compatibility * feat(runtime): remove redundant curve implementations, tests pass * feat(runtime)!: refactoring SyscallWeierstrassPairingAssign * fix(contracts/bn256): removed unused imports * fix(evn-e2e): disabled wasmtime feature * refactor: rename weierstrass into ecc (less misleading) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(runtime): clean up the ecc syshandlers * fix(runtime): removed the commented snippets * refactor(runtime): moved fp/fp2 ops away from ecc Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor(runtime): reimplemented ed25519 ops in the runtime Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor(runtime): move edwards, refactor ecrecover, implement u256 mul ops, remove bigmodexp, make keccak256 self-free Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor(runtime): add tower fields fp1/fp2 support Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore(runtime): fix warnings Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore(runtime): fix compilation Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor(runtime): move types into sdk, remove types crate, add new crypto crate for optimized crypto ops Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(crypto): expose mods Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore(crypto): rename `MathAPI` into `CryptoAPI` Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor(sdk): return types crate back, refactor hashing func, refactor crypto builtins Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor(sdk): fix cycle dependency, missing features, warnings, replace hashing function with the ones from new crypto crate Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(sdk): remove impossible test Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(contracts): update ecrecover to make it work Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor: update hashing, add new tests, reimplement hashing functions for eth Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(sha256): fix bug with incorrect endianess for sha256 compress/extend, enable new sha256 precompile Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: adjust block fuel for wasm applications, move Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(e2e): fix running router tests, tiny refactored artifacts Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor(runtime): new syscalls for unconstrained execution and for fd write, rename remaining host syscalls to the new naming format, add uint25 syscalls into native-api Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * feat(runtime): add rwasm-patches, Weierstrass add, double * refactor(runtime): benches fix Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor(runtime): a giant refactoring of all syscalls to make sure all params are aligned, remove all syscalls we can't support, reformat all constants Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: incorrect number of params for tower fields Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: encoding weierstrass point result, compatibility with evm bn256 tests Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: contract/bls12381 -> revm_precompile + rwasm-patches * fix: contracts/bn256 uses the runtime implementation for add * fix(types): fix _ed25519_decompress and _ed25519_add signatures * fix(contracts): add the validation for the bn254_add input data --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> Co-authored-by: Dmitry Savonin <nwtsoas@gmail.com> * feat(build): reduce docker image size and persist vol - mv example project creation to the dockerfile - remove redundunt tools from docker image - fix sccache usage * chore: migrate rwasm, revm deps to crates.io * fix(webauthn): handle secp256r1 precompile errors properly * fix(runtime): remove unused module param from engine.resume * refactor(docker): simplify build and improve cache warming - Add sdk_version input for manual builds - Auto-extract version from Cargo.toml for tagged releases - Improve cache warming with sccache and realistic dummy contract - Remove unused build args and submodule checkout - Streamline Dockerfile stages * ci: temporary disable cache * ci: fix version and sdk derivation for manual workflow dispatch * ci: fix version and sdk derivation for manual workflow dispatch * ci: fix branch or version passing * ci: fix branch or version passing * ci: disable cache export * chore: bump version to the v0.4.11-dev * fix(syscall): propagate database errors in BLOCKHASH syscall (#209) Context: BLOCKHASH was silently converting database errors to zero hash using 'unwrap_or(B256::ZERO)', violating EVM spec which requires zero only for out-of-range blocks, not database failures. Change: Replace 'ctx.block_hash().unwrap_or()' with 'ctx.db_mut().block_hash()?' to propagate errors. Add comprehensive test suite with FailingMockDatabase to verify error propagation. Rationale: Database I/O errors are fatal and must surface to caller. Masking them as successful zero results breaks error handling and makes debugging impossible. Verification: Added 4 tests covering database error propagation, future blocks, and blocks older than 256. Test 'test_block_hash_database_error_is_propagated' explicitly verifies Err() is returned for DB failures. Risk: Existing code relying on silent error suppression will now receive Err() instead of Ok(zero). This is correct behavior per EVM spec. * chore(deps): bump actions/download-artifact from 5 to 6 (#228) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 6. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump actions/upload-artifact from 4 to 5 (#227) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore: remove fluentbase-cli as it's no longer needed (#230) Remove the fluentbase-cli binary and all its dependencies. The CLI was mainly used for contract verification, which has been moved to the blockscout-rs/fluent-verifier service. * chore(deps): bump actions/setup-node from 5 to 6 (#212) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 5 to 6. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump actions/checkout from 4 to 5 (#203) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump dawidd6/action-download-artifact from 3 to 11 (#202) Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 3 to 11. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](https://github.com/dawidd6/action-download-artifact/compare/v3...v11) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-version: '11' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * refactor: new gas/fuel calculation model (#217) * fix: new gas/fuel calculation model (all gas checks happen inside revm, but we sync diff in evm runtime), don't sync refunds with evm (now they're managed inside revm runtime), interruption return total gas spent, remove `is_gas_free` check from the runtime, halt execution in-case of OOG for syscalls, new rwasm where value/stack potential vulnerability is not possible physically, remove `charge_fuel_manually` system builtin from NativeAPI (we keep it only for backward compatibility), add e2e tests for interruption OOG checks, add new balance example Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: remove unused comment Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: update rwasm with fixed `try_consume_fuel` for wasmtime mode Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: don't use wasmtime by default for evm e2e tests * chore: run tests in makefile on make Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: don't wipe output or return data during the interruption (#218) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(syscall): handle ed25519 decompression failure gracefully (#213) Replace 'decompress().expect()' with pattern matching to prevent panic on invalid Y coordinates. Returns 'ExitCode::MalformedBuiltinParams' instead of crashing the VM. Prevents DoS attacks where untrusted callers provide invalid curve points (e.g., Y=2 which is not on Ed25519 curve). Verification: Added test with mathematically invalid Y coordinate that confirms error return instead of panic. * fix(runtime): fix offset overflow in input/output system builtins (#223) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(syscall): prevent gas abuse in EXTCODECOPY by enforcing offset an… (#208) * fix(syscall): prevent gas abuse in EXTCODECOPY by enforcing offset and length Context: Gas abuse vulnerability allowed requesting small length but receiving full bytecode, bypassing gas charges. Additionally, offset parameter was ignored, causing incorrect data copies and storage mismatches. Change: - Syscall now applies offset and length correctly, returns exact requested bytes with zero padding - Gas charged for requested length (not actual bytecode size) prevents abuse - Opcode handler updated to use syscall data directly without re-applying offset - Added comprehensive unit tests covering gas abuse scenarios and edge cases Rationale: Enforcing offset/length in syscall prevents attackers from paying for 10 bytes but receiving full contract bytecode. EVM-compatible padding ensures correct storage values and maintains protocol semantics. Verification: - Unit tests validate gas charging matches requested length even when bytecode is shorter - Integration tests 'extCodeCopyBounds' and 'ExtCodeCopyTestsParis' now pass - Gas formula verified: base_cost (100/2600) + 3 * ceil(length/32) Impact: Fixes critical gas abuse vector and storage corruption issues. No breaking changes to legitimate usage patterns. * chore: fix fmt issues * test(syscall): remove redundant code_copy test cases * fix(syscall): add static context checks to metadata syscalls (#211) Context: Three metadata syscalls were missing 'is_static' validation, allowing state modifications during STATICCALL contexts, which violates EVM semantics where static calls must be read-only. Change: Added 'StateChangeDuringStaticCall' guards to: - SYSCALL_ID_METADATA_CREATE (before 'set_code') - SYSCALL_ID_METADATA_WRITE (before metadata modification) - SYSCALL_ID_METADATA_STORAGE_WRITE (before 'sstore') Rationale: Aligns metadata syscalls with existing pattern used in STORAGE_WRITE, EMIT_LOG, DESTROY_ACCOUNT, and CREATE operations. Prevents malicious contracts from persisting changes through view/pure functions. Verification: Checks placed after parameter validation but before any journal mutations, consistent with other state-changing syscalls. Impact: Contracts attempting metadata mutations during STATICCALL will now correctly revert with StateChangeDuringStaticCall error. * fix(syscall): replace metadata partial write with full rewrite (#210) Context: Previous implementation used resize() with offset+length which caused unintended truncation when writing shorter data than existing metadata, leading to silent data loss. Change: SYSCALL_ID_METADATA_WRITE now performs full metadata replacement instead of offset-based partial writes. Offset parameter is parsed but ignored for backward compatibility. Rationale: - Eliminates truncation bug where resize(offset+length) would silently delete trailing bytes - Prevents DoS via large offset values causing memory exhaustion - Simplifies logic by removing complex offset handling - Matches actual usage pattern (always full rewrites in practice) Verification: Added regression test that fails on old version (offset=2 produces 4 bytes) but passes on new version (full rewrite produces 4 bytes as intended). Impact: Calls using non-zero offset will now ignore the offset and perform full replacement. Users needing partial updates must implement read-modify-write pattern. Co-authored-by: Dmitry Savonin <3367605+dmitry123@users.noreply.github.com> * fix(runtime): prevent call_id collision across transaction boundaries (#214) Change: Clear recoverable_runtimes HashMap in reset_call_id_counter() to prevent dangling runtimes from failed transactions. Added overflow protection for call_id allocation and debug_assert to detect collisions. Replaced AtomicU32 with u32 since single-threaded access is guaranteed. Rationale: Failed transactions left runtimes in HashMap. When next transaction reset counter to 1, it could collide with dangling call_id, causing HashMap.insert() to silently overwrite old runtime. This led to memory leaks and potential security issues where resume() could execute wrong runtime context. Verification: Added test_call_id_overflow() for overflow handling. * audit(fix-weierstrass-decompress): fix weierstrass syscall implementations (#222) * fix(runtime): fix weierstrass decompress, remove `bn254_decompress` as it's not-supported, fix incorrect secp256k/r1 consts and compressed key encoding format Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(runtime): fix using incorrect function for secp256r1 Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: incorrect input param index (#229) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * feat(runtime): add LRU cache with memory limits to module factory (#216) Context: Module factory was using unbounded HashMap causing memory leaks as compiled modules accumulated without eviction Change: Replace HashMap with schnellru LruMap for both RwasmModule and wasmtime::Module caches. Implement ModuleMemoryLimiter with SizeEstimator trait for accurate memory tracking. Switch from RwLock to Mutex since LRU requires mutable access on get() Rationale: LRU eviction prevents unbounded memory growth while keeping hot modules cached. Generic ModuleMemoryLimiter<V> with SizeEstimator trait allows different size calculations for RwasmModule (sum of sections) vs wasmtime::Module (image_range). Mutex is faster than RwLock when all operations need write access Verification: Added tests for memory limit enforcement, eviction ordering, and LRU access pattern updates Impact: Memory usage capped at 1 GB per cache (2 GB total). Older unused modules will be evicted automatically. Co-authored-by: Dmitry Savonin <3367605+dmitry123@users.noreply.github.com> * fix(syscall): prevent frontrun attacks in metadata account creation (#204) Context: SYSCALL_ID_METADATA_CREATE was vulnerable to frontrunning where attacker could send funds to derived address before creation, causing legitimate create to fail on is_empty() check. Change: Modified collision detection in SYSCALL_ID_METADATA_CREATE to check only code_hash and nonce, excluding balance from emptiness check. This allows creation even if address has received funds. Rationale: Balance-based emptiness check enables DoS via frontrunning. Checking code_hash != KECCAK_EMPTY and nonce != 0 ensures address has no deployed code while allowing pre-funded accounts. Verification: Added test_metadata_create() that creates ownable account with pre-funded balance and verifies correct derivation, owner assignment, and metadata preservation. Risk: Accounts can now be created at addresses with existing balance. This is intentional and matches Ethereum CREATE2 behavior. Co-authored-by: Dmitry Savonin <3367605+dmitry123@users.noreply.github.com> * chore: clean evm e2e debug print (#221) * refactor(address): rename 'calc_create4_address' to 'calc_create_metadata_address' (#205) Context: The function name 'create4' was misleading and didn't clearly convey its purpose of deriving metadata-specific addresses. * fix: fix compilation because of create4 function call Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(runtime): disable `write_fd` syscall since it can cause node panic (#231) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(runtime): fix sub underflow for fp1/fp2 ops (#225) * fix(runtime): fix sub underflow for fp1/fp2 ops Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: return malformed builtin params in case of underflow inside fp1/fp2 ops Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(runtime): fix missing malformed builin params check for fp2 ops Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(runtime): remove todo from fp1 syscall Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(runtime): add check for add of the same point for weierstrass curve (#224) * fix(runtime): add check for add of the same point for weierstrass curve Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(runtime): add mod overflow check for weierstrass add operations (to make sure underflow can't happen) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(revm): unwrap code hash after bytecode check (#232) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(revm): make sure context is clear after wasm deployment (#233) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore(runtime): fix BE/LE confusion for wierstrass decompress operations (add comments, docs, and convert before doing syscall) (#234) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> Co-authored-by: d1r1 <61736932+d1r1@users.noreply.github.com> * fix(fuel): add quadratic fuel charging for EXEC input to prevent DoS (#239) * fix: reduce FUEL_DENOM_RATE from 1000 to 20 for production Context: Previous FUEL_DENOM_RATE of 1000 was based on outdated benchmarks. New measurements show WebAssembly instructions are ~20x faster than EVM instructions, not 1000x. Change: Updated FUEL_DENOM_RATE constant in crates/types/src/lib.rs from 1000 to 20 for production builds. Added 'fluent-testnet' feature flag across workspace to preserve legacy rate (1000) for backward compatibility with existing testnet deployments. Rationale: Corrects gas cost calculations to match actual performance characteristics. Feature flag prevents breaking existing testnet infrastructure during transition period. Verification: Benchmarks confirm 20x performance ratio. Feature propagation tested through build system. Risk: Changes gas consumption calculations for all WASM contract executions Impact: mainnet (new default), testnet (preserved via feature flag) BREAKING CHANGE: Production FUEL_DENOM_RATE reduced by 50x affects gas costs for all WASM contracts. Testnet preserves old behavior with fluent-testnet feature. * feat(gas): enable upper-rounding for fuel denomination charging Context: Deprecated record_denominated_cost and record_denominated_refund methods used floor division, causing undercharging (e.g., 25 fuel → 1 gas instead of 2). Change: Replaced deprecated methods with direct gas recording in executor.rs. Production uses ceiling division (fuel+rate-1)/rate for costs, floor division fuel/rate for refunds. Testnet (fluent-testnet feature) preserves legacy floor division for backward compatibility. Added cfg-if dependency for conditional compilation. Rationale: Ceiling division prevents undercharging by always rounding up gas costs. Floor division for refunds prevents over-refunding. Feature flag maintains testnet compatibility during transition. Impact: Production charges gas accurately with ceiling rounding. Testnet unchanged with fluent-testnet feature. * test: clarify CALL_FUEL_COST in builtin gas tests Replace magic +1 with explicit CALL_FUEL_COST constant to show that every WASM call instruction consumes 1 fuel unit, added by the rwasm translator during compilation. * feat: rebase to the new gas strategy * fix(fuel): add quadratic fuel charging for EXEC input to prevent DoS Previously, EXEC syscall charged constant fuel regardless of input size, allowing attackers to submit massive payloads (up to 32MB) while paying minimal gas. This created a DoS vector where nodes performed O(L) memory operations nearly for free. Changes: - Add quadratic fuel charging for EXEC input using EVM memory expansion formula: fuel = (3×words + words²/512) × FUEL_DENOM_RATE - Define FUEL_MAX_QUADRATIC_X = 1.25MB safe limit to prevent i32 overflow - Add comprehensive test verifying gas costs match EVM Yellow Paper spec The fix ensures gas costs scale appropriately with input size, preventing economic mismatch between metered and actual resource consumption. * fix(block_fuel): improve fuel calculation limits and add missing crypto costs - Update FUEL_MAX_LINEAR_X from 256KB to 128MB with proper derivation documenting i32 overflow constraints in WASM runtime - Add fuel costs for secp256r1 curve operations (ADD, DOUBLE, DECOMPRESS) - Add fuel costs for BLS12381 DECOMPRESS and DOUBLE operations - Handle ENTER_UNCONSTRAINED, EXIT_UNCONSTRAINED, and WRITE_FD syscalls - Remove catch-all _ => no_fuel!() pattern for exhaustive matching * fix(types): use MAX_WORDS in linear_fuel compile-time overflow check The compile-time check incorrectly used x directly instead of words, causing assertion failure with large FUEL_MAX_LINEAR_X values. Now consistent with quadratic_fuel macro and runtime calculation. * test(e2e): update overflow test value for new FUEL_MAX_LINEAR_X limit Increase test value from 300KB to 135MB to exceed the new 128MB limit. * fix: audit code maintenance fixes (#243) * fix(syscall): validate exact address length in METADATA_ACCOUNT_OWNER Change address length check from >= 20 to == 20 to reject malformed input data with trailing bytes. * fix(runtime): add #[must_use] to try_consume_fuel Prevents callers from accidentally ignoring fuel consumption errors. * perf(syscall): skip unnecessary resize in pad_to_be Only resize when len > bytes.len() to avoid redundant allocations. * docs(syscall): document argument constraints for weierstrass operations Add input format, validation behavior, and safety requirements for add, double, and decompress curve point functions. * fix(precompiles): pass caller's spec to inner EthPrecompiles Previously used SpecId::default() which could cause runtime behavior to diverge from expected fork settings. * refactor(runtime): move TestingStore to testing crate TestingStore contains unwrap/unreachable patterns that are acceptable for test infrastructure but not production code. Move it to the testing crate where it belongs. * fix(runtime): replace unreachable!() with exhaustive match in syscall dispatcher Remove wildcard match arm that used unreachable!() for unknown syscalls. The match is now exhaustive, providing compile-time guarantees that all SysFuncIdx variants are handled. Also handle disabled WRITE_FD syscall explicitly by returning TrapCode::UnreachableCodeReached instead of commenting it out. * fix(syscall): fix blake3 function naming typo and consistency Rename syscall_hashing_blak3_handler to syscall_hashing_blake3_handler and inner function to syscall_hashing_blake3_impl for consistency with other hashing functions. * fix(syscall): add endianness guard for keccak256_permute Add compile-time checks to prevent compilation on big-endian platforms where transmute in into_lanes_le/from_lanes_le would produce incorrect results. * fix(security): gate calldata-based precompile dispatch to testnet-only (#240) * fix: reduce FUEL_DENOM_RATE from 1000 to 20 for production Context: Previous FUEL_DENOM_RATE of 1000 was based on outdated benchmarks. New measurements show WebAssembly instructions are ~20x faster than EVM instructions, not 1000x. Change: Updated FUEL_DENOM_RATE constant in crates/types/src/lib.rs from 1000 to 20 for production builds. Added 'fluent-testnet' feature flag across workspace to preserve legacy rate (1000) for backward compatibility with existing testnet deployments. Rationale: Corrects gas cost calculations to match actual performance characteristics. Feature flag prevents breaking existing testnet infrastructure during transition period. Verification: Benchmarks confirm 20x performance ratio. Feature propagation tested through build system. Risk: Changes gas consumption calculations for all WASM contract executions Impact: mainnet (new default), testnet (preserved via feature flag) BREAKING CHANGE: Production FUEL_DENOM_RATE reduced by 50x affects gas costs for all WASM contracts. Testnet preserves old behavior with fluent-testnet feature. * feat(gas): enable upper-rounding for fuel denomination charging Context: Deprecated record_denominated_cost and record_denominated_refund methods used floor division, causing undercharging (e.g., 25 fuel → 1 gas instead of 2). Change: Replaced deprecated methods with direct gas recording in executor.rs. Production uses ceiling division (fuel+rate-1)/rate for costs, floor division fuel/rate for refunds. Testnet (fluent-testnet feature) preserves legacy floor division for backward compatibility. Added cfg-if dependency for conditional compilation. Rationale: Ceiling division prevents undercharging by always rounding up gas costs. Floor division for refunds prevents over-refunding. Feature flag maintains testnet compatibility during transition. Impact: Production charges gas accurately with ceiling rounding. Testnet unchanged with fluent-testnet feature. * test: clarify CALL_FUEL_COST in builtin gas tests Replace magic +1 with explicit CALL_FUEL_COST constant to show that every WASM call instruction consumes 1 fuel unit, added by the rwasm translator during compilation. * feat: rebase to the new gas strategy * fix(security): gate calldata-based precompile dispatch to testnet-only Restrict UPDATE_GENESIS_AUTH and calldata-based precompile dispatch behind 'fluent-testnet' feature flag to address audit findings. This prevents: - Arbitrary bytecode deployment if privileged key is compromised - Non-standard precompile invocation via calldata prefix (violates EIP-1352) Changes: - Add feature gates to frame_init() handler - Update fuel_to_gas for mainnet ceiling division - Disable affected tests (multicall, update_account) on mainnet - Add comprehensive security documentation Related: Audit recommendation to remove functionality for mainnet --------- Co-authored-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(features): rm fluent-testing from features list * feat(reusable-store): move system interruption processing outside of contracts entry for evm contract (#219) * feat(reusable-store): move rust flags into .cargo config instead of build script, new evm & modexp runtime that supports reusable stores, implemented halted frames (only for system runtimes), add serde for interruption params, add error code `CreateContractStartingWithEF`, verify input params before parsing them inside syscall (to avoid potential memory ddos attack), pass params into syscall as offset/length instead of bytes, decompose entrypoint macro for better flexiability, new debug macro (more details, alloc-free, decompoiles in release) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * feat(reusable-store): reduce default stack size to 1mb, moved precomiles to the new system runtime (blake2f, bls12381, bn256, ecrecover, eip7951, identity, kzg, modexp, ripemd160, sha256), disable several spam tests because of stack limits Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(reusable-store): fix potential stack leak in case of `OutOfFuel` trap code (replace with exit code) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(reusable-store): fix incorrect input length for metadata copy Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: put update account test under `fluent-testnet` feature Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: remove unused assert Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> Co-authored-by: Dmitry Savonin <nwtsoas@gmail.com> * chore(deps): bump actions/checkout from 5 to 6 (#238) Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(feat/svm-under-feature): put svm under feature (#237) * feat(reusable-store): move rust flags into .cargo config instead of build script, new evm & modexp runtime that supports reusable stores, implemented halted frames (only for system runtimes), add serde for interruption params, add error code `CreateContractStartingWithEF`, verify input params before parsing them inside syscall (to avoid potential memory ddos attack), pass params into syscall as offset/length instead of bytes, decompose entrypoint macro for better flexiability, new debug macro (more details, alloc-free, decompoiles in release) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * feat(reusable-store): reduce default stack size to 1mb, moved precomiles to the new system runtime (blake2f, bls12381, bn256, ecrecover, eip7951, identity, kzg, modexp, ripemd160, sha256), disable several spam tests because of stack limits Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(reusable-store): fix potential stack leak in case of `OutOfFuel` trap code (replace with exit code) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(reusable-store): fix incorrect input length for metadata copy Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * feat(feat/svm-under-feature): put svm under feature * fix: update revm-primities dep Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: update lock files * chore: fix incorrect merge * fix: fix missing feature for update account test Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> Co-authored-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: warning fixes * feat: add calculate_syscall_fuel function * feat: rework import linker to syscall params * feat: rework import linker with macros * chore: change patcher to tmp branch * test: turn off fuel consuming for wasmtime in evm-e2e tests * fix(block_fuel): improve fuel calculation limits and add missing crypto costs - Update FUEL_MAX_LINEAR_X from 256KB to 128MB with proper derivation documenting i32 overflow constraints in WASM runtime - Add fuel costs for secp256r1 curve operations (ADD, DOUBLE, DECOMPRESS) - Add fuel costs for BLS12381 DECOMPRESS and DOUBLE operations - Handle ENTER_UNCONSTRAINED, EXIT_UNCONSTRAINED, and WRITE_FD syscalls - Remove catch-all _ => no_fuel!() pattern for exhaustive matching * feat: add quadratic fuel for syscalls * chore: fix dependencies * feat: add quadratic and fuel max consts to fluentbase types crate exports * feat: update rwasm to current branch * feat(v102): migrated revm to version v102 (#248) * feat(v102): migrated revm to version v102 Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * feat(v102): disable debug print Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: add fatal execution code for OOM and other cases inside system runtime (#245) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: add veridise audit report Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * feat(sdk-derive): event derive macro for solidity-compatible logs (#246) - #[derive(Event)] generates emit() for EVM logs - #[indexed] for topic fields, #[anonymous] for no-signature events - compile-time selector, runtime encoding via SolidityABI - replaces alloy-sol-types in ERC20 example * chore(deps): bump codecov/codecov-action from 5.5.1 to 5.5.2 (#250) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.5.1 to 5.5.2. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v5.5.1...v5.5.2) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: 5.5.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: building contracts w/o workspace, new universal token contract, make code storage 32-byte, tiny sdk types refactoring, remove universal token perf, a lot of universal token bug fixes, remove token2022 universal token implementation (#241) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> Co-authored-by: Dmitry Savonin <nwtsoas@gmail.com> * chore(deps): bump actions/upload-artifact from 5 to 6 (#253) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump actions/download-artifact from 6 to 7 (#254) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6 to 7. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(sdk-derive): add #[slot(expr)] attribute for explicit storage pos (#252) * feat(sdk-derive): add #[slot(expr)] attribute for explicit storage positioning Support explicit storage slot placement via #[slot(U256)] field attribute. Fields with explicit slots bypass auto-layout and are excluded from SLOTS constant. Also adds eip1967_slot! and erc7201_slot! compile-time helper macros. * test(sdk-derive): fix snapshots * fix: rollback bls12-381 to the original ethereum implementation (keep old one inside legacy.rs file) (#251) * fix: rollback bls12-381 to the original ethereum implementation (keep old one inside legacy.rs file) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: add pre-check for gas & input size for bls12-381 precompiles Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: update lock file --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore(webauthn): remove redundant check for closing quote (#256) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(evm): fix wrapping mul for evm call-opcodes (#255) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: fix syscall metadata copy potential crash (#249) * fix: fix syscall metadata copy potential crash Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: add `is_static` check for metadata-write syscalls Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: fix bytecode hard-cap check for create/create2 syscalls Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: remove redundant `StateChangeDuringStaticCall` check Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(revm): fix metadata syscall overflow Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore(fairblock): remove fairblock from repository (#260) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: fix project compilation Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: update rwasm to the latest with gas strategy fixes * chore: update rwasm branch to the devel * chore: small sdk fixes (#257) * chore: small sdk fixes Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: enable EIP-7951, add more docs and comments for genesis config Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: add docs & comments, rename `RwasmRuntime` into `ContractRuntime`, remove unsused code (like `GlobalExecutor` or interruption state inside `SystemRuntime`) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: remove `inter_process_lock.rs` since it's unused Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(universal-token): universal token bug fixes (#258) * fix(universal-token): fix incorrect token/symbol ABI encoding, fix missing `is_static` check for mutable methods, formated errors to be openzeppelin-complaint, add missing `is_zero` checks for transfers, fix incorrect error and signatures for ERC20, fix incorrect padding for event logs, fix missing storage slots for constructor, improved unit tests coverage Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(universal-token): don't charge allowance if `U256::MAX` was approved Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(universal-token): new test for checking that partial storages writes are not possible Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore(deps): bump dawidd6/action-download-artifact from 11 to 12 (#262) Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 11 to 12. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](https://github.com/dawidd6/action-download-artifact/compare/v11...v12) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-version: '12' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(oom): add OOM handler and e2e test for OOM case (#259) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(eip2935): bug fixes and refactoring (#263) * fix(eip2935): fix BE encoding for input/output, migrate contract to new system runtime, add unit tests for eip2935 system contract, deprecate `system_entrypoint` macro, fix e2e unit tests for eip2935 Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(eip2935): remove unused debug comment Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(eip2935): fix warning Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(runtime): fix weierstrass double crash in case of modulus overflow (#265) Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(module-factory): LRU cache replacement triggers eviction (#266) - on_replace now allows LRU eviction instead of rejecting - Add zero-size item rejection to prevent limit bypass - Use saturating arithmetic to prevent overflow/underflow - Assert max_bytes > 0 on construction - Fix on_grow to always allow table growth - Expand test coverage for edge cases * feat(gas-charged-before-cold-state-operations): logic validating cold load cost upfront to prevent misuse (#267) * feat(gas-charged-before-cold-state-operations): added logic validating cold load cost upfront to prevent missuse * feat(gas-charged-before-cold-state-operations): rewrote to keep compatibility * feat(gas-charged-before-cold-state-operations): gas limit fixes for e2e tests * feat(gas-charged-before-cold-state-operations): modified gas checks for SYSCALL_ID_STORAGE_WRITE * feat(gas-charged-before-cold-state-operations): added/fixed gas checks for SYSCALL_ID_CODE_HASH, SYSCALL_ID_CODE_COPY, SYSCALL_ID_CODE_SIZE * feat(gas-charged-before-cold-state-operations): calculated max possible values for gas in gas pre-checks for SYSCALL_ID_CODE_COPY and SYSCALL_ID_CODE_SIZE * feat(gas-charged-before-cold-state-operations): replaced gas pre-checks with load_account_info_skip_cold_load for CODE_COPY CODE_HASH CODE_SIZE BALANCE * feat(gas-charged-before-cold-state-operations): gas pre-check rewrite for SYSCALL_ID_DESTROY_ACCOUNT * feat(gas-charged-before-cold-state-operations): reimplemented gas pre-checks for SYSCALL_ID_CALL by reusing contents of load_account_delegated * feat(gas-charged-before-cold-state-operations): unified and spread gas-checked version of Journal::load_account_delegated() accross staticcall, delegatecall and callcode * feat(gas-charged-before-cold-state-operations): reuse process_journal_load_result and renamings; removed redundand checks for staticcall callcode and delegatecall * chore: fix warning and import format Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * fix(revm): incorrect db error mapping Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> Co-authored-by: Stas Stepanov <stepanovstanisl@gmail.com> Co-authored-by: Dmitry Savonin <nwtsoas@gmail.com> * fix: replace unsafe unreachable hint with exit code error (#268) * fix(contracts): audit nitro contract (#261) * fix: Missing check for certificate critical extensions in nitro precompile#17 + tests * fix: Missing check for certificate timestamp validity in nitro precompile#16 * fix: Missing validation of attestation document for nitro precompile#15 * fix: auditor's comments * refactor(migrate-system-contracts-to-new-runtime): migrating system contracts to new system runtime (#264) * refactor: migrate blake2f to new system runtime v2, fix bug with crashing node with oom in case of system runtime trap Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor: migrate all evm systme contracts to new system runtime v2, fix bug with loosing return data in case of precompile error Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor: migrate nitro, oauth2, wasm, webauthn to the new system runtime Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: fix compilation warnings, update sp1-curves to the latest version Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * chore: fix nitro warning unused variable * fix: don't allow to use fatal exit codes inside wasm contracts Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor: rename `HostTestingContext` to `TestingContextImpl` to match other naming conventions Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> * refactor(evm): migrate evm runtime to new system runtime v2, fix compilation warnings Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * refactor(evm): remove old system runtime Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * refactor: tiny refactor of revm, add new comments/docs, move tests into separate file, don't forward balances and access lists into system contracts (not in use), tiny improvements Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix/(testnet-runtime-upgrade): fix running fluent-testnet unit tests (#270) * fix(revm): fix revm compilation for fluent-testnet feature flag, fix update account unit tests Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: add fluent-testnet tests into makefile, add new ci/cd pipeline for running fluent-testnet unit tests Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> --------- Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * feat(module-size-is-not-explicitly-bounded): added module size check for wasm contract (#269) * feat(module-size-is-not-explicitly-bounded): added manual checks for contract size into the contract * feat(module-size-is-not-explicitly-bounded): added manual checks for contract size into the contract * feat(module-size-is-not-explicitly-bounded): lost features and functionality * feat(module-size-is-not-explicitly-bounded): fixed problem with feature propagation and small changes to text errors * feat(module-size-is-not-explicitly-bounded): fix for feature miss for release profile * feat(module-size-is-not-explicitly-bounded): cover test with cfg(test) * feat(module-size-is-not-explicitly-bounded): increased RWASM_MAX_CODE_SIZE test value to pass existing tests * feat(module-size-is-not-explicitly-bounded): increased RWASM_MAX_CODE_SIZE test value to pass existing tests * feat(module-size-is-not-explicitly-bounded): removed redundant comment + fixed params for test_locals_amplification_find_limit * feat(module-size-is-not-explicitly-bounded): removed testing-enabled feature * chore: remove extra constant, e2e test fixes Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * feat(module-size-is-not-explicitly-bounded): fix space * fix(wasm): use exit code instead of panic, add comment for constant Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> --------- Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> Co-authored-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix: incorrect method for extend from slice in `write_fd.rs` (#273) * fix: incorrect method for extend from slice in `write_fd.rs` * fix: add test proving that oauth2 crash doesn't happen Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix: replace atomic u64 with u32 Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * chore: warning fixes Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * chore: fix print for build script Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> --------- Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix(runtime): add fuel metering for engine-metered precompiles (#276) * fix(runtime): add fuel metering for engine-metered precompiles NITRO_VERIFIER, OAUTH2_VERIFIER, WASM_RUNTIME, and WEBAUTHN_VERIFIER were executing without charging gas because they don't self-meter via `_charge_fuel` syscall. Changes: - Add ENGINE_METERED_PRECOMPILES list and is_engine_metered_precompile() - Create wasmtime engine with consume_fuel=true and syscall_fuel_params - Pass consume_fuel flag through executor to SystemRuntime - Set fuel limit before execution and read remaining fuel after * fix(runtime): rm debugging logs * fix(eip2935): enable gas for EIP-2935 system smart contract Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix(universal-token): enable fuel metering for universal token Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix(eip2935): fix gas charge for success branches Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * chore: tiny comment fixes Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix(eip2935): missing denom rate multiplication Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix(eip2935): fix incorrect gas charge for eip2935 contract Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix(wasm): fix panic if wasm compilation runs out of fuel Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix(wasm): fix panic if wasm compilation runs unexpected error Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix: charge gas for warmed operations with universal token and eip2935 Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix: remove double gas charge for eip2935 (it's charged during access list preparation now) Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> --------- Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> Co-authored-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * chore(deps): bump dawidd6/action-download-artifact from 12 to 14 (#275) Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 12 to 14. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](https://github.com/dawidd6/action-download-artifact/compare/v12...v14) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-version: '14' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(new-rwasm-runtime): new wasmtime runtime (#277) * fix(runtime): add fuel metering for engine-metered precompiles NITRO_VERIFIER, OAUTH2_VERIFIER, WASM_RUNTIME, and WEBAUTHN_VERIFIER were executing without charging gas because they don't self-meter via `_charge_fuel` syscall. Changes: - Add ENGINE_METERED_PRECOMPILES list and is_engine_metered_precompile() - Create wasmtime engine with consume_fuel=true and syscall_fuel_params - Pass consume_fuel flag through executor to SystemRuntime - Set fuel limit before execution and read remaining fuel after * fix(runtime): rm debugging logs * refactor(runtime): integrate new rwasm runtime (bring `no_std` support into runtime crate), fix incorrect tests for block fuel calculation, disable one failing evm test, enable wasmtime for evm execution by default, tiny fixes Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * chore: fix several typos and compilation warnings Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * feat: integrate new rwasm runtime into revm runtime Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * chore: apply suggestion from @coderabbitai[bot] Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> Co-authored-by: d1r1 <me@d1r1.me> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * feat: switch rwasm to the latest devel version, replace tiny-keccak with migrated repository Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * feat: migrate revm to v103 (#279) * feat: migrate revm to v103 Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * chore: update revm-rwasm and wasm to the latest version --------- Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix: replace panics with ExitCode and fix typos in write_fd (#274) * fix: use gas constants from revm v103 (#280) Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix: disable svm at workspace level, bridge compatibility with reth v1.10, new fluent binary (#281) * fix: disable svm at workspace level, bridge compatibility with reth v1.10 Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * feat: migrate fluent node binary with genesis config into fluentbase repository Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * feat: add docker files and makefile for building fluent binary Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * feat: remove json feature from sol-types Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * feat: replace reth with new version Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: add workflow for building fluent node with dry-run dispatch mode Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: remove sccache wrapper * ci: fix release pipeline Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: enforce rust toolchain 1.90.0 Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: enforce rust toolchain 1.92.0 Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: enforce rust toolchain 1.90.0 Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: enforce rust toolchain 1.92.0 Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: enforce rust toolchain 1.92.0 Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: enforce rust toolchain 1.92.0 Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: replace slashes with dashes for version Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: fix incorrect artifact path Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: fix missing gpg signature for fluent binary Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: enable apple aarch64 and amd64 builds Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: disable apple aarch64 and amd64 builds for now Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * feat: download genesis files from github releases, remove genesis from repo Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix: tiny fixes for ci and docker builds Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> --------- Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix(reqwest-native-tls): enable native tls for reqwest (#283) * fix: enable native tls for reqwest * chore: change println logs for fluent Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> --------- Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: fix missing openssl dev for amd64 (#284) * ci: fix missing openssl dev for amd64 * ci: fix openssl install Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: fix openssl install Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: replace native-tls with rustls Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: add missing pkgconfig Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: add docker pipeline, use native-tls for reqwest Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: downgrade reqwest to use ring tls instead of aws Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: fix incorrect build directory Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * ci: fix missing fluent artifact to be stored inside release Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> * fix: fix running benches Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> --------- Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> --------- Signed-off-by: Dmitry Savonin <nwtsoas@gmail.com> Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: Dmitry Savonin <dmitry@fluentlabs.xyz> Co-authored-by: Jaye Turner <jayeturnerjatu@gmail.com> Co-authored-by: d1r1 <me@d1r1.me> Co-authored-by: d1r1 <61736932+d1r1@users.noreply.github.com> Co-authored-by: Stanislav Stepanov <105381376+bfdays@users.noreply.github.com> Co-authored-by: chillhacker <85485830+chillhacker@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stanislav Stepanov <stanislav@fluentlabs.xyz> Co-authored-by: easy <shinbogdan@gmail.com> Co-authored-by: Stanislav Stepanov <truebfday@gmail.com> Co-authored-by: Stas Stepanov <stepanovstanisl@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Emirhan Yıldız <yildiz.emrhn@gmail.com>
NITRO_VERIFIER, OAUTH2_VERIFIER, WASM_RUNTIME, and WEBAUTHN_VERIFIER were executing without charging gas because they don't self-meter via
_charge_fuelsyscall.Changes:
Summary by CodeRabbit
New Features
Bug Fixes / Behavior
Tests
Chores