nautechsystems/nautilus_trader · error
Call edge references an unpinned contract
Error message
Call edge references an unpinned contract
What it means
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.
Source
Thrown at crates/adapters/blockchain/src/rpc/verification.rs:1405
}
let mut call_edges = HashSet::new();
for edge in &manifest.call_edges {
anyhow::ensure!(
matches!(
edge.purpose.as_str(),
"wrap" | "approve" | "swap_sell" | "swap_buy"
) && matches!(
edge.call_type.as_str(),
"call" | "staticcall" | "delegatecall" | "callcode"
),
"Deployment manifest call edge is invalid"
);
let caller = Address::from_str(&edge.caller)
.map_err(|_| anyhow::anyhow!("Call edge address is invalid"))?;
let target = Address::from_str(&edge.target)
.map_err(|_| anyhow::anyhow!("Call edge address is invalid"))?;
for address in [caller, target] {
anyhow::ensure!(
contract_addresses.contains(&address),
"Call edge references an unpinned contract"
);
}
anyhow::ensure!(
call_edges.insert((
edge.purpose.as_str(),
caller,
target,
edge.call_type.as_str()
)),
"Deployment manifest contains a duplicate call edge"
);
}
for purpose in ["swap_sell", "swap_buy"] {
anyhow::ensure!(
manifestView on GitHub (pinned to 18893faf8b)
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
Example fix
// before
{"call_edges": [{"caller": "0xaaa...", "target": "0xbbb...", "purpose": "wrap"}]}
// contracts section lacks 0xbbb...
// after
{"contracts": [{"address": "0xbbb...", "role": "WrappedNative", "runtime_code_hash": "0x..."}], "call_edges": [{"caller": "0xaaa...", "target": "0xbbb...", "purpose": "wrap"}]} Defensive patterns
Strategy: validation
Validate before calling
let pinned: HashSet<Address> = manifest.contracts.iter()
.filter_map(|c| Address::from_str(&c.address).ok())
.collect();
for edge in &manifest.call_edges {
for addr in [&edge.caller, &edge.target] {
let a = Address::from_str(addr)?;
if !pinned.contains(&a) {
return Err(format!("call edge references unpinned contract {addr}"));
}
}
} Type guard
fn edge_is_pinned(edge: &CallEdge, pinned: &HashSet<Address>) -> bool {
[&edge.caller, &edge.target].iter().all(|s|
Address::from_str(s).map(|a| pinned.contains(&a)).unwrap_or(false))
} Try / catch
match validate_deployment_manifest(&manifest) {
Err(e) if e.to_string().contains("unpinned contract") => {
eprintln!("Pin every edge endpoint in the contracts section: {e}");
}
Err(e) => return Err(e),
Ok(()) => {}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Router {router} is not in the configured `router_addresses`
- Token {token} is not an input token in the configured `allow
- Verified call trace contains a forbidden state-changing oper
- Signer address {} derived from '{}' does not match configure
- Verified chain ID does not match the transaction chain
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/453eb126c5960430.
Report an issue: GitHub.