{"record":{"id":"e6c7820a7e904c1a","repo":"linera-io/linera-protocol","slug":"returned-accountinfo-should-have-code-some-a","errorCode":null,"errorMessage":"Returned AccountInfo should have code: Some(...) and so code_by_hash_ref should never be called","messagePattern":"Returned AccountInfo should have code: Some\\(\\.\\.\\.\\) and so code_by_hash_ref should never be called","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"linera-execution/src/evm/database.rs","lineNumber":818,"sourceCode":"            let modules = self.modules.lock().unwrap();\n            let application_id = address_to_user_application_id(address);\n            modules.contains_key(&application_id)\n        };\n        self.inner.read_basic_ref(\n            InnerDatabase::<Runtime>::get_contract_account_info,\n            address,\n            is_newly_created,\n        )\n    }\n\n    /// There are two ways to implement the trait:\n    /// * Returns entries with \"code: Some(...)\"\n    /// * Returns entries with \"code: None\".\n    ///\n    /// Since we choose the first design, `code_by_hash_ref` is not needed. There\n    /// is an example in the Revm source code of this kind.\n    fn code_by_hash_ref(&self, _code_hash: B256) -> Result<Bytecode, ExecutionError> {\n        panic!(\"Returned AccountInfo should have code: Some(...) and so code_by_hash_ref should never be called\");\n    }\n\n    /// Accesses the storage by the relevant remote access function.\n    fn storage_ref(&self, address: Address, index: U256) -> Result<U256, ExecutionError> {\n        self.inner.read_storage(\n            InnerDatabase::<Runtime>::get_contract_storage_value,\n            address,\n            index,\n        )\n    }\n\n    fn block_hash_ref(&self, number: u64) -> Result<B256, ExecutionError> {\n        Ok(keccak256(number.to_string().as_bytes()))\n    }\n}\n\nimpl<Runtime> Database for ContractDatabase<Runtime>\nwhere","sourceCodeStart":800,"sourceCodeEnd":836,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-execution/src/evm/database.rs#L800-L836","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (design invariant broken)\nfn basic_ref(&self, address: Address) -> ... { AccountInfo { code: None, ... } } // -> code_by_hash_ref panics\n\n// after (restore invariant)\nfn basic_ref(&self, address: Address) -> ... { AccountInfo { code: Some(self.load_bytecode(address)?), ... } }","handlingStrategy":"validation","validationCode":"# Build/CI check: keep revm & alloy at the validated versions\ncargo update --dry-run 2>/dev/null | grep -E 'revm|alloy' || echo 'pinned OK'\n# and a smoke test executing EXTCODEHASH-heavy contracts in CI to trip the panic early","typeGuard":"// Invariant check (test-only): every account exposed to revm must carry inline code\nassert!(matches!(db.basic_ref(addr)?, Some(info) if info.code.is_some()));","tryCatchPattern":null,"preventionTips":["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."],"tags":["rust","revm","evm","database","panic","dependency-upgrade"],"backgroundTag":"unimplemented-trait-method","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}