# LibMuon Signature hash collision

LibMuon hashes signatures with abi.encodePacked and no type prefix, so verifyPrices and verifyPartyAUpnlAndPrice hashes collide, letting a valid signature be reused for the other function.

- Payout: Contest reward
- Severity: high
- Program: Symmetrical
- Credited: bin2chen
- Disclosed: 2023-06-05
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-06-symmetrical-judging/issues/214
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-06-symmetrical%3AH-4
- Tags: domain:web3 impact:integrity kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:crypto vuln:signature-replay

**Target:** Solidity signature verification library (LibMuon)
**Root cause:** Signatures are hashed with abi.encodePacked without a function/type prefix, so different struct layouts (dynamic arrays vs scalars) can produce identical byte encodings and thus identical keccak256 hashes.
**Steps:**
1. Identify verifyPrices hashing `partyA, upnl, totalUnrealizedLoss, symbolIds[], prices[]` and verifyPartyAUpnlAndPrice hashing `partyA, partyANonces, upnl, symbolId, price`.
2. Note both use abi.encodePacked with no type prefix.
3. Craft values so the packed bytes match: partyA equal, upnl=partyANonces, totalUnrealizedLoss=upnl, symbolIds[0]=symbolId, prices[0]=price.
4. Run forge test asserting keccak256 of both encodings are equal (confirmed true).
5. Reuse a legitimate verifyPartyAUpnlAndPrice signature as a verifyPrices signature with attacker-chosen upnl/totalUnrealizedLoss.
**How found:** Code review of LibMuon noticed abi.encodePacked used without type prefixes across multiple verify functions; hypothesized that a dynamic array in one struct could be flattened to match scalar fields in another, then wrote a Foundry test to confirm hash equality.
**Exploitation:** Attacker obtains a valid Muon TSS signature for verifyPartyAUpnlAndPrice and replays the same signature against verifyPrices, substituting partyANonces as upnl and other fields, feeding illegal upnl/price data into the protocol.
**Insight:** When auditing signature verification, compare every verify* function's packed encoding side by side; if any struct contains a dynamic array and another uses scalars, check whether field-by-field substitution yields identical packed bytes.
