# Incorrect proof management makes cross-chain design not work as expected

SuperValidatorBase decodes only one destination Merkle proof, so userOps with multiple cross-chain messages can never be fully proven, breaking core multi-chain functionality.

- Payout: Contest reward
- Severity: medium
- Program: Superform
- Credited: Orion Security
- Disclosed: 2025-07-17
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_superform_may2025.pdf#3.2.20
- Library page: https://bugbountylibrary.com/r/cantina%3Asuperform_may2025%3A3.2.20
- Tags: domain:web3 impact:dos kind:contest platform:cantina sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic

**Target:** SuperValidatorBase / SuperMerkleValidator signature decoding (ERC-4337 userOp validation)
**Root cause:** SignatureData struct only carries a single bytes32[] proofDst, so a Merkle tree with more than two leaves (source + multiple destination messages) cannot supply proofs for all destination leaves.
**Steps:**
1. Build a userOp with 4 hooks: approve USDC, approve WETH, Across-bridge USDC, Across-bridge WETH.
2. Construct 3 leaves: source (userOpHash+validUntil), USDC destination leaf, WETH destination leaf.
3. Build Merkle tree and sign root.
4. Encode sigData as `abi.encode(validUntil, root, proof[0], proof[1], signature)` — only one destination proof fits.
5. Call `handleOps`; observe both FundsDeposited events carry the identical proofDst, so one destination message is unprovable.
**How found:** Read the cross-chain execution docs showing a multi-leaf Merkle tree, then traced `_decodeSignatureData` and noticed proofDst is a single array, contradicting the documented multi-destination design.
**Insight:** When a protocol documents a Merkle tree with N leaves, check that the signature/calldata struct can actually carry N proofs — fixed-size proof arrays silently cap the tree to two leaves.
