{"record":{"id":"3e10c90f9fac9aed","repo":"nautechsystems/nautilus_trader","slug":"proxy-target-binding-is-invalid","errorCode":null,"errorMessage":"Proxy target binding is invalid","messagePattern":"Proxy target binding is invalid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/verification.rs","lineNumber":1299,"sourceCode":"        );\n\n        if let Some(proxy) = &contract.proxy {\n            anyhow::ensure!(\n                matches!(\n                    proxy.kind.as_str(),\n                    \"eip1967_implementation\" | \"zeppelinos_implementation\"\n                ),\n                \"Proxy kind is unsupported\"\n            );\n            B256::from_str(&proxy.storage_slot)\n                .map_err(|_| anyhow::anyhow!(\"Proxy storage slot is invalid\"))?;\n            let storage_value = B256::from_str(&proxy.storage_value)\n                .map_err(|_| anyhow::anyhow!(\"Proxy storage value is invalid\"))?;\n            let target = Address::from_str(&proxy.target_address)\n                .map_err(|_| anyhow::anyhow!(\"Proxy target address is invalid\"))?;\n            let target_hash = B256::from_str(&proxy.target_code_hash)\n                .map_err(|_| anyhow::anyhow!(\"Proxy target code hash is invalid\"))?;\n            anyhow::ensure!(\n                target != Address::ZERO\n                    && target != address\n                    && target_hash != B256::ZERO\n                    && storage_value[..12].iter().all(|byte| *byte == 0)\n                    && storage_value[12..] == *target.as_slice(),\n                \"Proxy target binding is invalid\"\n            );\n        }\n\n        for probe in &contract.probes {\n            Bytes::from_str(&probe.call_data)\n                .map_err(|_| anyhow::anyhow!(\"Manifest probe call data is invalid\"))?;\n            Bytes::from_str(&probe.expected_output)\n                .map_err(|_| anyhow::anyhow!(\"Manifest probe output is invalid\"))?;\n        }\n    }\n\n    for contract in &manifest.contracts {","sourceCodeStart":1281,"sourceCodeEnd":1317,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/verification.rs#L1281-L1317","documentation":"This error is thrown by the deployment-manifest validator in the blockchain adapter when a contract's proxy entry fails the target-binding invariants: the target address must be nonzero, must differ from the proxy's own address, the target code hash must be nonzero, and the proxy storage value must be an EIP-1967-style slot value whose low 20 bytes equal the target address. It guarantees a proxy really points at a concrete implementation contract before the verifier uses the manifest.","triggerScenarios":"Calling the manifest verification routine with a deployment manifest whose contract.proxy has: a zero target_address, a target_address equal to the proxy contract's own address, a zero or malformed target_code_hash, or a storage_value that is not (12 zero bytes || target address) — e.g. an incorrectly computed EIP-1967 slot value or a value copied from the wrong proxy.","commonSituations":"Hand-editing deployment manifest JSON after deploy; regenerating a manifest with a script that writes the slot value in the wrong endianness or with the wrong padding; copying a proxy block between networks where the implementation address differs; typos in hex addresses; pointing the proxy at itself after a self-upgrade misconfiguration.","solutions":["Set proxy.target_address to the real implementation contract address (nonzero, different from the proxy address)","Recompute proxy.storage_value as 32 bytes where the last 20 bytes are the target address (hex, left-padded with 12 zero bytes) and proxy.target_code_hash to the implementation's nonzero runtime code hash","Regenerate the manifest from the deployment tooling instead of hand-editing, then recompute the manifest digest"],"exampleFix":"// before\n\"proxy\": {\"target_address\": \"0x0000000000000000000000000000000000000000\", \"storage_value\": \"0x...\", \"target_code_hash\": \"0x0...\"}\n// after\n\"proxy\": {\"target_address\": \"0x9f2c...impl\", \"storage_value\": \"0x0000000000000000000000009f2c...impl\", \"target_code_hash\": \"0xabc...32bytehash\"}","handlingStrategy":"validation","validationCode":"use alloy_primitives::{Address, B256};\nfn proxy_binding_ok(proxy_addr: &str, target: &str, code_hash: &str, storage_value: &str) -> bool {\n    let (Ok(target), Ok(hash), Ok(value), Ok(addr)) = (\n        Address::from_str(target), B256::from_str(code_hash),\n        B256::from_str(storage_value), Address::from_str(proxy_addr),\n    ) else { return false };\n    target != Address::ZERO && target != addr && hash != B256::ZERO\n        && value[..12].iter().all(|b| *b == 0) && value[12..] == *target.as_slice()\n}","typeGuard":"fn is_valid_proxy(p: &ProxyEntry) -> bool {\n    Address::from_str(&p.target_address).is_ok()\n        && B256::from_str(&p.target_code_hash).is_ok()\n        && B256::from_str(&p.storage_value).is_ok()\n}","tryCatchPattern":"match validate_manifest(&config) {\n    Err(e) if e.to_string().contains(\"Proxy target binding\") => {\n        eprintln!(\"fix proxy target/storage_value fields: {e}\");\n    }\n    Err(e) => return Err(e),\n    Ok(v) => v,\n}","preventionTips":["Compute storage_value as the EIP-1967 implementation slot value: 12 zero bytes followed by the target address","Never point a proxy at itself or the zero address","Regenerate manifests with tooling instead of hand-editing hex","Recompute the manifest digest after any fix so the digest check also passes"],"tags":["validation","blockchain","config","hex-parsing"],"backgroundTag":"invalid-config-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}