{"record":{"id":"453eb126c5960430","repo":"nautechsystems/nautilus_trader","slug":"call-edge-references-an-unpinned-contract","errorCode":null,"errorMessage":"Call edge references an unpinned contract","messagePattern":"Call edge references an unpinned contract","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/verification.rs","lineNumber":1405,"sourceCode":"    }\n    let mut call_edges = HashSet::new();\n    for edge in &manifest.call_edges {\n        anyhow::ensure!(\n            matches!(\n                edge.purpose.as_str(),\n                \"wrap\" | \"approve\" | \"swap_sell\" | \"swap_buy\"\n            ) && matches!(\n                edge.call_type.as_str(),\n                \"call\" | \"staticcall\" | \"delegatecall\" | \"callcode\"\n            ),\n            \"Deployment manifest call edge is invalid\"\n        );\n        let caller = Address::from_str(&edge.caller)\n            .map_err(|_| anyhow::anyhow!(\"Call edge address is invalid\"))?;\n        let target = Address::from_str(&edge.target)\n            .map_err(|_| anyhow::anyhow!(\"Call edge address is invalid\"))?;\n        for address in [caller, target] {\n            anyhow::ensure!(\n                contract_addresses.contains(&address),\n                \"Call edge references an unpinned contract\"\n            );\n        }\n        anyhow::ensure!(\n            call_edges.insert((\n                edge.purpose.as_str(),\n                caller,\n                target,\n                edge.call_type.as_str()\n            )),\n            \"Deployment manifest contains a duplicate call edge\"\n        );\n    }\n\n    for purpose in [\"swap_sell\", \"swap_buy\"] {\n        anyhow::ensure!(\n            manifest","sourceCodeStart":1387,"sourceCodeEnd":1423,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/verification.rs#L1387-L1423","documentation":"Both the caller and target of every call edge must be pinned in the manifest's contract_addresses set. An edge that references a contract with no pinned identity is rejected, because un-pinned addresses cannot be verified against known bytecode and could point at arbitrary or hostile code.","triggerScenarios":"Validating a manifest where a call edge's caller or target parses as a valid address but is absent from the contracts section — e.g. an edge added for a new helper contract that was never declared with a role and code hash.","commonSituations":"Adding a call edge for a new router/approval contract without adding its contract entry; redeploying a contract so its address changed but the edge still names the old address; copying edges from a different chain's manifest.","solutions":["Add a pinned contract entry (address, role, runtime_code_hash) for each address the edge references","Update the edge's caller/target to the exact addresses of already-pinned contracts","Delete stale edges pointing at contracts that are no longer part of this deployment","Regenerate the manifest so edges and pinned contracts stay consistent"],"exampleFix":"// before\n{\"call_edges\": [{\"caller\": \"0xaaa...\", \"target\": \"0xbbb...\", \"purpose\": \"wrap\"}]}\n// contracts section lacks 0xbbb...\n// after\n{\"contracts\": [{\"address\": \"0xbbb...\", \"role\": \"WrappedNative\", \"runtime_code_hash\": \"0x...\"}], \"call_edges\": [{\"caller\": \"0xaaa...\", \"target\": \"0xbbb...\", \"purpose\": \"wrap\"}]}","handlingStrategy":"validation","validationCode":"let pinned: HashSet<Address> = manifest.contracts.iter()\n    .filter_map(|c| Address::from_str(&c.address).ok())\n    .collect();\nfor edge in &manifest.call_edges {\n    for addr in [&edge.caller, &edge.target] {\n        let a = Address::from_str(addr)?;\n        if !pinned.contains(&a) {\n            return Err(format!(\"call edge references unpinned contract {addr}\"));\n        }\n    }\n}","typeGuard":"fn edge_is_pinned(edge: &CallEdge, pinned: &HashSet<Address>) -> bool {\n    [&edge.caller, &edge.target].iter().all(|s|\n        Address::from_str(s).map(|a| pinned.contains(&a)).unwrap_or(false))\n}","tryCatchPattern":"match validate_deployment_manifest(&manifest) {\n    Err(e) if e.to_string().contains(\"unpinned contract\") => {\n        eprintln!(\"Pin every edge endpoint in the contracts section: {e}\");\n    }\n    Err(e) => return Err(e),\n    Ok(()) => {}\n}","preventionTips":["Add a contract entry whenever you add a call edge","Regenerate manifests after any contract redeployment","Keep edges and contracts sourced from the same deployment record"],"tags":["blockchain","manifest-validation","security"],"backgroundTag":"schema-validation-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}