{"record":{"id":"cff4127935f7ba91","repo":"nautechsystems/nautilus_trader","slug":"wrap-authorization-does-not-match-the-transaction","errorCode":null,"errorMessage":"Wrap authorization does not match the transaction call","messagePattern":"Wrap authorization does not match the transaction call","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":1997,"sourceCode":"        VerificationOutcome::Retryable(_) => {\n            anyhow::bail!(\"{context} verification is retryable\")\n        }\n        VerificationOutcome::LocallyInvalid(_) => {\n            anyhow::bail!(\"{context} verification is locally invalid\")\n        }\n    }\n}\n\nfn validate_transaction_authorization(\n    authorization: Option<&TransactionAuthorization>,\n    to: Address,\n    value: U256,\n    input: &[u8],\n) -> anyhow::Result<()> {\n    match authorization {\n        None => Ok(()),\n        Some(TransactionAuthorization::Wrap { weth }) => {\n            anyhow::ensure!(\n                to == *weth && !value.is_zero() && input == WETH9::depositCall::SELECTOR,\n                \"Wrap authorization does not match the transaction call\"\n            );\n            Ok(())\n        }\n        Some(TransactionAuthorization::Approve {\n            token,\n            router,\n            amount,\n        }) => {\n            let expected = ERC20::approveCall {\n                spender: *router,\n                amount: *amount,\n            }\n            .abi_encode();\n            anyhow::ensure!(\n                to == *token && value.is_zero() && input == expected,\n                \"Approve authorization does not match the transaction call\"","sourceCodeStart":1979,"sourceCodeEnd":2015,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L1979-L2015","documentation":"The client verifies that an authorized Wrap operation (WETH deposit) exactly matches the transaction actually being signed: recipient must be the authorized WETH contract, value nonzero, and calldata exactly WETH's deposit() selector. Any mismatch means the signed call would exceed or differ from what was authorized, so signing is refused.","triggerScenarios":"prepare/sign path invoked with a TransactionAuthorization::Wrap but the transaction's `to` is not the authorized weth address, `value` is zero, or `input` is not the deposit selector — i.e. the call payload diverged from the authorization.","commonSituations":"Bug in transaction construction that swaps `to`/calldata; WETH address misconfigured to a different token; authorization created for wrap but the builder emitted a different call (e.g. forgot to set value or used transfer instead of deposit).","solutions":["Ensure the transaction's `to` equals the authorized WETH address and `input` equals WETH9::depositCall::SELECTOR with nonzero value.","Check the transaction builder so the wrap authorization and emitted call are built from the same parameters.","Verify the weth address in configuration matches the canonical WETH9 deployment on the target chain.","Re-derive the authorization from the same code path that builds the call to keep them in sync."],"exampleFix":"// before: wrap auth but call built incorrectly\nlet input = WETH9::transferCall { .. }.abi_encode(); // wrong selector\nverify_wrap(Some(Wrap { weth }), weth, value, &input)?;\n// after\nlet input = WETH9::depositCall::SELECTOR.to_vec();\nverify_wrap(Some(Wrap { weth }), weth, value, &input)?;","handlingStrategy":"validation","validationCode":"fn wrap_call_matches(weth: Address, value: U256, input: &[u8]) -> bool {\n    value != U256::zero() && input == WETH9::depositCall::SELECTOR\n}","typeGuard":"fn is_wrap_auth(auth: &TransactionAuthorization) -> Option<Address> {\n    if let TransactionAuthorization::Wrap { weth } = auth { Some(*weth) } else { None }\n}","tryCatchPattern":"match result { Err(e) if e.to_string().contains(\"Wrap authorization does not match\") => { rebuild_tx_from_authorization(); retry(); } Ok(v) => v }","preventionTips":["Build transaction calls from the same parameters as the authorization","Verify WETH address per chain in config","Unit-test that wrap txs emit exactly the deposit selector with nonzero value"],"tags":["security","authorization","weth","validation"],"backgroundTag":"invalid-argument-value","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"}