# Reliance on incorrect hash in IpcContract.sol leads to permanent fund loss and receipt message execution failure

IpcContract stores inflight messages keyed by toHash() but receipts reference toTracingId(), so receipt lookup always fails, blocking result handling and trapping refunds.

- Payout: Contest reward
- Severity: high
- Program: Recall
- Credited: sin1st3r__
- Disclosed: 2026-03-13
- Write-up quality: 7/10
- Original: https://code4rena.com/reports/2025-02-recall#h-03
- Library page: https://bugbountylibrary.com/r/c4%3A2025-02-recall%3AH-03
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** IpcContract.sol cross-subnet messaging (Xnet envelopes/receipts)
**Root cause:** performIpcCall keys inflightMsgs by envelope.toHash() (includes localNonce), but createResultMsg sets ResultMsg.id via toTracingId() which excludes localNonce, so the hashes never match.
**Steps:**
1. Call performIpcCall() with value>0; gateway fills nonces and envelope is stored at inflightMsgs[envelope.toHash()].
2. Destination executes and calls createResultMsg(), setting ResultMsg.id = toTracingId(crossMsg) (no localNonce).
3. Receipt returns to source; handleIpcMessage() decodes ResultMsg and looks up inflightMsgs[result.id].
4. Lookup returns empty struct; orig.message.length == 0 triggers revert UnrecognizedResult().
**How found:** Code-reading comparison of the two hashing helpers: noticed toHash() includes localNonce while toTracingId() omits it, then traced that the receipt id is used as the inflightMsgs key.
**Exploitation:** No attacker action needed; any Xnet call with value>0 that fails on destination leaves funds stuck since the receipt can never be matched and refunded, and all receipts revert.
**Insight:** When a protocol has multiple hash helpers for the same struct, diff their field lists; any field added by a middleware (like a nonce filled in later) will desync keys between send-side storage and receive-side lookup.
