# SushiSwap MISO: msg.value reuse in batch drains auction

SushiSwap MISO DutchAuction's BoringBatchable delegatecall persists msg.value, letting an attacker batch commitEth calls to bid for free and drain refunds.

- Payout: Real-world hack
- Severity: critical
- Program: SushiSwap Miso
- Analysis by: DeFiHackLabs
- Disclosed: 2021-09-16
- Write-up quality: 9/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2021-09/Sushimiso_exp.sol
- Library page: http://bugbountylibrary.com/r/dhl%3A20210916-sushimiso
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:critical tech:evm tech:solidity technique:chained technique:source-review vuln:accounting-error vuln:business-logic

**Target:** DutchAuction contract (commitEth via BoringBatchable.batch)
**Root cause:** BoringBatchable.batch uses delegatecall, which preserves msg.sender and msg.value across iterations, so commitEth's msg.value check passes repeatedly for a single ETH payment. Refund logic also returns any ETH over the hard cap, enabling extraction.
**Steps:**
1. Identify DutchAuction at `0x4c4564a1FE775D97297F9e3Dc2e762e0Ed5Dda0e` importing BoringBatchable.
2. Encode `commitEth(address(this), true)` payload and push it 5 times into a `bytes[]`.
3. Call `DutchAuction.batch{value: 100_000_000_000_000_000_000}(data, true)` — each delegatecall sees the same msg.value, so 5 commitments are credited for 0.1 ETH.
4. Because the auction hard cap is exceeded, the contract refunds the over-cap ETH to the attacker, extracting funds.
**How found:** Browsing a Telegram discussion about a MISO raise, opened the DutchAuction contract, noticed unguarded initMarket but it was protected by initAccessControls; then spotted BoringBatchable and recalled the Opyn msg.value-in-loop bug, hypothesizing delegatecall would persist msg.value across batched commitEth calls.
**Exploitation:** Attacker batches multiple commitEth calls in one transaction paying msg.value once; delegatecall preserves msg.value so each commitment is counted at full value. Over-cap contributions trigger refunds, letting the attacker pull ETH out of the contract rather than just bid for free.
**Escalation:** From free bidding to draining all other participants' bids via the over-hard-cap refund path, putting ~109k ETH (~$350M) at risk.
**Insight:** When a contract mixes BoringBatchable (or any delegatecall batch) with payable functions that check msg.value, test whether msg.value is reused across iterations — the same class as the Opyn loop bug. Also audit refund paths for over-cap contributions as an extraction primitive.

## Proof of concept (copied exactly from the original report)

**Foundry PoC reusing msg.value via batch commitEth**

```
bytes memory payload =
            abi.encodePacked(DutchAuction.commitEth.selector, uint256(uint160(address(this))), uint256(uint8(0x01)));
        data.push(payload);
        data.push(payload);
        data.push(payload);
        data.push(payload);
        data.push(payload);
        DutchAuction.batch{value: 100_000_000_000_000_000_000}(data, true);
```

