{"record":{"id":"b66256302e8e4185","repo":"linera-io/linera-protocol","slug":"contracts-cannot-call-themselves","errorCode":null,"errorMessage":"Contracts cannot call themselves","messagePattern":"Contracts cannot call themselves","errorType":"validation","errorClass":"EvmExecutionError","httpStatus":null,"severity":"error","filePath":"linera-execution/src/evm/revm.rs","lineNumber":616,"sourceCode":"            } => {\n                let authenticated = true;\n                let is_tracked = true;\n                let grant = Resources::default();\n                let send_message_request = SendMessageRequest {\n                    destination,\n                    authenticated,\n                    is_tracked,\n                    grant,\n                    message,\n                };\n                let mut runtime = context.db().0.lock_runtime();\n                runtime.send_message(send_message_request)?;\n                Ok(vec![])\n            }\n            ContractRuntimePrecompile::TryCallApplication { target, argument } => {\n                let authenticated = true;\n                let mut runtime = context.db().0.lock_runtime();\n                ensure!(\n                    target != runtime.application_id()?,\n                    EvmExecutionError::NoSelfCall\n                );\n                runtime.try_call_application(authenticated, target, argument)\n            }\n            ContractRuntimePrecompile::Emit { stream_name, value } => {\n                let mut runtime = context.db().0.lock_runtime();\n                let result = runtime.emit(stream_name, value)?;\n                Ok(bcs::to_bytes(&result)?)\n            }\n            ContractRuntimePrecompile::ReadEvent {\n                chain_id,\n                stream_name,\n                index,\n            } => {\n                let mut runtime = context.db().0.lock_runtime();\n                runtime.read_event(chain_id, stream_name, index)\n            }","sourceCodeStart":598,"sourceCodeEnd":634,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-execution/src/evm/revm.rs#L598-L634","documentation":"The Linera contract runtime precompile exposed to EVM contracts rejects tryCallApplication when the target application id equals the caller's own id (revm.rs:616). This is a direct reentrancy guard: re-entering your own application through the runtime while its execution is in flight would bypass fuel and state-consistency accounting.","triggerScenarios":"Inside an EVM contract, calling the runtime precompile (address 0x0b) with ContractRuntimePrecompile::TryCallApplication where target equals the application id the contract itself is running as.","commonSituations":"Trying to reuse your own public entry point via the runtime instead of an internal Solidity function call; generic call-forwarding or fallback code that passes through whatever target it received (which may resolve to self); porting recursive application designs from other chains.","solutions":["Refactor: invoke the internal Solidity function directly instead of a tryCallApplication round-trip","Guard the precompile call and revert early when target == own application id","If recursion is genuinely needed, split the logic into two applications so the call is never self-directed"],"exampleFix":"// before: re-enter self through the runtime\nruntime.tryCallApplication(appId, data); // appId == this application\n\n// after: direct internal call, no runtime round-trip\nhandleInternally(data);","handlingStrategy":"validation","validationCode":"// Solidity: refuse to call ourselves through the runtime precompile\nfunction callApp(address target, bytes memory data) internal {\n    require(target != OWN_APP_TARGET, NoSelfTarget());\n    LineraRuntime(PRECOMPILE).tryCallApplication(target, data);\n}","typeGuard":"fn is_no_self_call(err: &ExecutionError) -> bool {\n    matches!(err, ExecutionError::EvmError(EvmExecutionError::NoSelfCall))\n}","tryCatchPattern":"match runtime.try_call_application(target, arg) {\n    Ok(out) => out,\n    Err(ref e) if is_no_self_call(e) => {\n        // self-call attempted: run the logic internally instead\n        Ok(self.handle_internally(arg))\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Treat the runtime precompile as an inter-application API only; never point it at your own application id","Keep reusable logic in internal Solidity functions and have entry points call those directly","Add a test that forwards your own application id through every generic call path and asserts a clean application-level revert"],"tags":["evm","reentrancy","runtime-precompile","linera"],"backgroundTag":"reentrant-call","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}