Full Report
The author beings with a quick statement: "A common misconception in building software is that if every component in a system is individually verified to be safe, the system itself is also safe". This article is really into the mind of the blockchain hacker. SushiSwap has a MISO platform (sidenote: if you want to be taken seriously, please don't use ridiculous names like this). This platform has two types of auctions: Dutch and Batch Auctions. The author quickly skimmed through all of the contracts to see nothing wrong obviously wrong with it. While scrolling through all of the files, they found two libraries: SafeTransfer and BoringBatchable. The BoringBatchable library is added in order to easily introduce batch calls to any contract that imports it. This is done with a simple delegateCall flow. In a previous time, the author of the post was on a call with the Opyn team about trying to protect user funds after a horrible attack. The contract allowed for the batching of multiple calls and would REUSE the msg.value in the loop. This was the same bug in a different form. In the context of an auction... you could send 1ETH to the batch functionality. When calling this functionality, you could call commitEth for an auction once. Then again. And over and over for all auctions, while only ever spending the 1ETH. Is there anything else we can do besides win auctions for free? Yes! We can call refund on repeat. By sending ETH that went over the auctions hard cap, the contract would simply refund the ETH. By doing this over and over again via the batch call, all of the funds from the contract could be drained. The timeline of this is absolutely wild. From discovery to being on a call with the Sushi team, it was only 2 hours. No funds ended up being stolen. Overall, the post is awesome and really puts you into the mind of a hacker. Sometimes, taking a few extra minutes to look at something can change the world. Welcome to the world of hackers!
Analysis Summary
# Vulnerability: MISO DutchAuction `msg.value` Reuse via `BoringBatchable`
## CVE Details
- **CVE ID**: Not Assigned (DeFi security incident)
- **CVSS Score**: 10.0 (Critical)
- **CWE**: CWE-440: Expected Behavior Violation (Logic Error), CWE-670: Always-Incorrect Control Flow Implementation
## Affected Systems
- **Products**: SushiSwap MISO Launchpad
- **Versions**: Contracts deployed prior to August 17, 2021
- **Configurations**: Contracts inheriting the `BoringBatchable` library utilizing functions that process native ETH via `msg.value` (specifically `DutchAuction` and `BatchAuction`).
## Vulnerability Description
The vulnerability arises from the interaction between the `BoringBatchable` library and functions that handle native ETH payments.
The `BoringBatchable` library allows for batching multiple function calls into a single transaction using `delegatecall`. In Ethereum, `delegatecall` preserves the context of the original caller, including the `msg.value`. Because `msg.value` is a global variable that does not update during the execution of a transaction, a user can call a payment function (like `commitEth`) multiple times within a single `batch` call. The contract checks if `msg.value` is sufficient for each individual call but fails to account for the fact that the same ETH is being "spent" repeatedly.
## Exploitation
- **Status**: PoC available (Discovered by researcher; not exploited in the wild)
- **Complexity**: Low
- **Attack Vector**: Network
- **Details**: An attacker could commit to an auction multiple times using the same ETH, effectively bidding for "free" after the first commitment. Furthermore, by batching calls to functions that refund excess ETH, an attacker could drain the entire ETH balance of the contract.
## Impact
- **Confidentiality**: None
- **Integrity**: Critical (Unauthorized manipulation of auction state)
- **Availability**: High (Potential draining of all funds held in the contract—estimated at 109,000 ETH at the time of discovery)
## Remediation
### Patches
- The SushiSwap team addressed the issue by pausing the vulnerable auctions and ensuring future deployments do not combine `BoringBatchable` with `msg.value` logic in loops.
### Workarounds
- **WETH Migration**: Use Wrapped ETH (WETH) instead of native ETH. Because WETH is an ERC-20 token, it requires a `transferFrom` call which updates the user's balance, preventing reuse within a loop.
- **State Validation**: Avoid using `msg.value` inside any loop or batched logic; instead, track internal balances or use a pull-payment pattern.
## Detection
- **Indicators of Compromise**: Multiple internal calls to `commitEth` or `refund` within a single transaction hash where the total intended deposit exceeds the actual `msg.value` sent.
- **Detection methods and tools**: Static analysis tools (like Slither) can be configured to detect `msg.value` usage inside loops or `delegatecall` contexts.
## References
- **Vendor Advisories**: [https://www.paradigm.xyz/2021/08/two-rights-might-make-a-wrong](https://www.paradigm.xyz/2021/08/two-rights-might-make-a-wrong)
- **Etherscan Contract**: [https://etherscan.io/address/0x4c4564a1FE775D97297F9e3Dc2e762e0Ed5Dda0e](https://etherscan.io/address/0x4c4564a1FE775D97297F9e3Dc2e762e0Ed5Dda0e)