# SuperRare staking exploit (RareStakingV1), July 2025

Citations [n] resolve to the Sources at the end.

## 1. What happened
On 2025-07-28 the NFT platform SuperRare's staking contract **RareStakingV1** on **Ethereum** was exploited: attackers drained about **11.9M RARE** tokens worth roughly **$730,000** [1][2][3][6]. Victim `0xfFB512B9176D527C5D32189c3e310Ed4aB2Bb9eC`; attack tx `0xd8137...5ba6e3c1`; exploiter `0x5B9B4...2D4a2` [2][3][14][15]. Only the staking/reward pool was hit - the RARE token and marketplace were unaffected [3][6][7]. Verichains gives the exact amount as 11,907,874.71 RARE [2].

Sources disagree on the USD figure: SlowMist, SolidityScan, CertiK/PeckShield/Blockaid and Cointelegraph cite ~$730,000 [1][3][5][9]; Cyvers reports **$731,809.68** [13]; Verichains **~$680,000** [2]; Quadriga notes SupLabsYi citing **$710,000** [9]. All agree ~11.9M RARE. A **front-running twist**: Blockaid says the first attacker deployed an exploit contract, but the actual draining tx was executed by a separate front-runner one block later [7][9][12]; Cyvers confirmed this [13]. Cyvers traced the exploiter's funding to Tornado Cash ~186 days earlier [7][9][13].

## 2. Root cause
This was **not** a stolen key, a tricked signer or a key-handling failure - it was a smart-contract logic bug. `updateMerkleRoot` was meant to let only the contract `owner()` or one hard-coded authorized address set the Merkle root that encodes per-user reward allocations. The deployed `require` was inverted:

`require(msg.sender != owner() || msg.sender != address(0xc2F394a45e994bc81EfF678bDE9172e10f7c8ddc), "Not authorized to update merkle root");`

No address is both `owner()` and `0xc2F3...8ddc`, so at least one `!=` clause is always true, the `||` is always true, and the check never reverts - it excludes the wrong set (everyone is admitted) [3][4][10]. Anyone could therefore set a malicious Merkle root and then claim the full pool [1][2][3]. Veridise adds that by the team's own account the check was introduced in a change made **after** the contract's initial review [4]. SuperRare co-founder Jonathan Perkins told Cointelegraph the contracts had been audited and unit-tested but the bug was introduced late and was not covered by final test scenarios; he said 61 wallets were affected, no core protocol funds were lost, and affected users would be made whole [5]. **No formal SuperRare post-mortem blog was found**; as of 2025-07-28 cryptonews.com noted SuperRare had not released one [7], and Quadriga likewise found no public acknowledgement [9]. Perkins' remarks to Cointelegraph are the closest thing to the project's own account [5].

## 3. Pattern
General class: **broken / inverted access control** (OWASP SC Top 10 SC01). The guard is present but enforces nothing because it names who is *excluded* instead of who is *allowed* [3][4]. Vulnerable shape:

```
function updateMerkleRoot(bytes32 newRoot) external {
    require(msg.sender != owner() || msg.sender != AUTHORIZED, "Not authorized");
    currentClaimRoot = newRoot;   // tautology: every caller passes
}
```

Because a valid Merkle root is trusted as proof of a reward claim, whoever controls the root controls who may claim, so an inverted caller check converts directly into theft [2][4][10].

## 4. The check that would have caught it
- **Unit test (permissions):** call `updateMerkleRoot` from a fresh, non-privileged address and assert it *reverts* and `currentClaimRoot` is unchanged; also assert `owner()` and the authorized address succeed. This negative test is exactly what SuperRare's final test scenarios omitted [5][10].
- **Fuzz / invariant:** invariant = "for every `msg.sender` that is neither `owner()` nor the authorized address, `updateMerkleRoot` must revert; only privileged members may change the root." Fuzz random callers against it [4]. Enforce statically too: an access-control `require` comparing `msg.sender` with `!=` rather than `==` is a high-signal smell, detected by scanners (SolidityScan, Bug Hunter, Veridise's Vanguard) on this contract [3][4][10].
- **Operational control:** re-audit and re-test *every* post-audit change, however small - the change that introduced this require bypassed the original review [4][5].

## 5. Sources
1. SlowMist Hacked: https://hacked.slowmist.io/
2. Verichains: https://blog.verichains.io/p/superrare-exploit-analysis
3. SolidityScan: https://blog.solidityscan.com/superrare-hack-analysis-488d544d89e0/
4. Veridise: https://veridise.com/blog/audit-insights/smart-contract-access-control-superrare-exploit/
5. Cointelegraph: https://cointelegraph.com/news/superrare-730-000-exploit-was-easily-preventable-experts-weigh-in
6. crypto.news: https://crypto.news/superrare-nft-platform-loses-730k-in-rare-token-exploit/
7. CryptoNews: https://cryptonews.com/news/breaking-superrare-staking-contract-hit-by-730k-exploit-rare-token-unscathed/
8. Protos: https://protos.com/tornado-cash-user-hacks-superrare-staking-contract-steals-730k-in-rare/
9. Quadriga Initiative: https://www.quadrigainitiative.com/hackfraudscam/superrareupdatemerklerootbackwardspermissionchecklogic.php
10. Bug Hunter: https://docs.bughunter.live/blog/superrare-bughunter/
11. The Coin Republic: https://www.thecoinrepublic.com/2025/07/28/superrare-hack-730k-stolen-in-staking-exploit-with-frontrun-twist/
12. Blockaid on X: https://x.com/blockaid_/status/1949757641720242494
13. Cyvers on X: https://x.com/CyversAlerts/status/1949766758635610276
14. Etherscan contract: https://etherscan.io/address/0xfFB512B9176D527C5D32189c3e310Ed4aB2Bb9eC
15. Etherscan tx: https://etherscan.io/tx/0xd813751bfb98a51912b8394b5856ae4515be6a9c6e5583e06b41d9255ba6e3c1
16. rekt.news leaderboard (checked; **no dedicated SuperRare entry found**): https://rekt.news/leaderboard/

Not found: a SuperRare/RareDAO first-party post-mortem, and no rekt.news article on this incident [16]. Differing USD amounts are reported above with their sources rather than reconciled [2][9][13].
