linera-io/linera-protocol · critical
Returned AccountInfo should have code: Some(...) and so code
Error message
Returned AccountInfo should have code: Some(...) and so code_by_hash_ref should never be called
What it means
This Database implementation for Revm deliberately always returns AccountInfo with code: Some(...), so the engine never needs to resolve bytecode by hash — code_by_hash_ref is left as a loud unreachable panic. Seeing it means Revm requested bytecode by hash, which happens when some code path returned code: None or when a different Revm version exercises the DB differently than the design assumed.
Source
Thrown at linera-execution/src/evm/database.rs:818
let modules = self.modules.lock().unwrap();
let application_id = address_to_user_application_id(address);
modules.contains_key(&application_id)
};
self.inner.read_basic_ref(
InnerDatabase::<Runtime>::get_contract_account_info,
address,
is_newly_created,
)
}
/// There are two ways to implement the trait:
/// * Returns entries with "code: Some(...)"
/// * Returns entries with "code: None".
///
/// Since we choose the first design, `code_by_hash_ref` is not needed. There
/// is an example in the Revm source code of this kind.
fn code_by_hash_ref(&self, _code_hash: B256) -> Result<Bytecode, ExecutionError> {
panic!("Returned AccountInfo should have code: Some(...) and so code_by_hash_ref should never be called");
}
/// Accesses the storage by the relevant remote access function.
fn storage_ref(&self, address: Address, index: U256) -> Result<U256, ExecutionError> {
self.inner.read_storage(
InnerDatabase::<Runtime>::get_contract_storage_value,
address,
index,
)
}
fn block_hash_ref(&self, number: u64) -> Result<B256, ExecutionError> {
Ok(keccak256(number.to_string().as_bytes()))
}
}
impl<Runtime> Database for ContractDatabase<Runtime>
whereView on GitHub (pinned to 6c226ddcb3)
Solutions
- Pin/keep the revm and alloy versions this Database was designed against; if upgrading, audit the change notes for code-by-hash behavior.
- If your fork of basic_ref ever returns code: None, make it return the full bytecode instead — the panic is the designed tripwire for exactly that.
- As a last resort, implement code_by_hash_ref by fetching bytecode from the contract storage instead of panicking.
Example fix
// before (design invariant broken)
fn basic_ref(&self, address: Address) -> ... { AccountInfo { code: None, ... } } // -> code_by_hash_ref panics
// after (restore invariant)
fn basic_ref(&self, address: Address) -> ... { AccountInfo { code: Some(self.load_bytecode(address)?), ... } } Defensive patterns
Strategy: validation
Validate before calling
# Build/CI check: keep revm & alloy at the validated versions cargo update --dry-run 2>/dev/null | grep -E 'revm|alloy' || echo 'pinned OK' # and a smoke test executing EXTCODEHASH-heavy contracts in CI to trip the panic early
Type guard
// Invariant check (test-only): every account exposed to revm must carry inline code assert!(matches!(db.basic_ref(addr)?, Some(info) if info.code.is_some()));
Prevention
- Pin revm/alloy in Cargo.lock and review their changelogs for code-by-hash behavior before any bump.
- Keep basic_ref returning code: Some(bytecode) — the panic is the tripwire for code: None leaks.
- Run an EVM integration test covering EXTCODEHASH/EXTCODESIZE after every dependency upgrade.
When it happens
Trigger: Upgrading the revm/alloy crates to a version whose interpreter calls code_by_hash_ref (e.g. after basic_ref changes or EXT*CODEHASH handling changes); any modification to basic_ref that starts returning code: None for some accounts; a revm feature (state overrides, block caching) that lazily fetches code.
Common situations: Routine dependency bumps of revm/alloy re-enabling a code path the Linera DB explicitly declined to implement; refactors of the account-loading code; introducing a new execution mode (e.g. state override sets) that stores code by hash.
Related errors
- Returned AccountInfo should have code: Some(...) and so code
- owner should be different from spender
- invalid block export configuration: {message}
- An Evm runtime is required to load user applications. Please
- transaction {tx_hash} reverted (receipt status 0)
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/e6c7820a7e904c1a.
Report an issue: GitHub.