Reproduced Exploit
Revolution / Collective — art-piece quorum inflated by auctioned ERC721 voting power
1. createPiece sets totalVotesSupply from erc20.totalSupply() + weighted erc721.totalSupply(). 2. The ERC721 currently held by AuctionHouse is included but cannot vote for that piece. 3. quorumVotes is computed from the inflated supply. 4. HARM: with 1000e18 accessible and weight-100 NFT on auction…
Chain
Other
Category
governance
Date
Dec 2023
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.
Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 30089-h-02-artpiecetotalvotessupply-and-artpiecequorumvotes-are-in. Standalone Foundry PoC and full write-up: 30089-h-02-artpiecetotalvotessupply-and-artpiecequorumvotes-are-in_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/governance/quorum-manipulation · vuln/arithmetic/precision-loss · genome: precision-loss · locked-funds · quorum-supply-drift
Reproduction: a self-contained Foundry PoC that compiles & runs in an isolated project with only
forge-std— no fork, no RPC, noanvil_state. Full trace: output.txt. PoC: test/30089-h-02-artpiecetotalvotessupply-and-artpiecequorumvotes-are-in_exp.sol.
AuditVault taxonomy: lang/solidity · platform/code4rena · has/github · has/poc · severity/high · sector/governance · sector/nft · sector/token · genome: precision-loss · locked-funds · quorum-supply-drift
Key info#
| Impact | HIGH — quorum for new art pieces is inflated by inaccessible auction NFT weight |
| Protocol | Revolution Protocol / Collective |
| Vulnerable code | CultureIndex.createPiece — totalVotesSupply / quorumVotes snapshot |
| Bug class | Quorum supply drift / inaccessible voting power counted |
| Finding | Code4rena 2023-12-revolutionprotocol · H-02 · #30089 |
| Report | code4rena.com/reports/2023-12-revolutionprotocol |
| Source | AuditVault |
| Status | Confirmed (sponsor). Reproduced as standalone local PoC. |
| Compiler | ^0.8.24 (PoC) |
TL;DR#
createPiecesetstotalVotesSupplyfromerc20.totalSupply()+ weightederc721.totalSupply().- The ERC721 currently held by
AuctionHouseis included but cannot vote for that piece. quorumVotesis computed from the inflated supply.- HARM: with 1000e18 accessible and weight-100 NFT on auction, honest 50% (500e18) fails the inflated 550e18 quorum (effective 55%).
The vulnerable code#
newPiece.totalVotesSupply = _calculateVoteWeight(
erc20VotingToken.totalSupply(),
erc721VotingToken.totalSupply() // @> VULN: includes ERC721 on auction
);
newPiece.quorumVotes = (quorumVotesBPS * newPiece.totalVotesSupply) / 10_000; // @> VULN: inflated
Fix: subtract erc721VotingToken.balanceOf(auctionHouse) when snapshotting ERC721 supply.
Root cause#
Vote-supply snapshot ignores that the live auction NFT’s voting power is inaccessible: the auction house does not vote, and the eventual buyer is checkpoint-gated against pieces created before they held the token.
Preconditions#
- An ERC721 verbs token is mid-auction (balance sits in AuctionHouse) when a new piece is created.
- Impact is largest early (small ERC721 supply, high weight).
Attack walkthrough#
- State: 1000e18 erc20, 1 NFT in AuctionHouse, weight=100, quorum BPS=5000.
createPiece→totalVotesSupply=1100e18,quorumVotes=550e18.- Accessible supply is still 1000e18.
- Cast honest half (500e18) → fails inflated quorum.
Diagrams#
Impact#
Pieces created during an auction face a higher-than-configured quorum relative to votes that can actually be cast — unfair vs pieces created when no NFT is locked, and harder to advance to auction especially at launch.
How to reproduce#
cd evm-hack-registry/30089-h-02-artpiecetotalvotessupply-and-artpiecequorumvotes-are-in_exp
forge test -vvv
Sources#
- AuditVault finding #30089
- Code4rena report 2023-12-revolutionprotocol
- Reduced from code-423n4/2023-12-revolutionprotocol@d42cc62b
createPiece
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 30089-h-02-artpiecetotalvotessupply-and-artpiecequorumvotes-are-in_exp (evm-hack-registry mirror).
- AuditVault finding: 30089-h-02-artpiecetotalvotessupply-and-artpiecequorumvotes-are-in.
Alerts & third-party analyses
These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.