Reproduced Exploit
IQ AI — Adversary can win proposals with voting power as low as 4%
1. Constructor sets GovernorVotesQuorumFraction(4) with comment "quorum is 25% (1/4th)". 2. OZ quorumDenominator() defaults to 100, so quorum = supply * 4 / 100 = 4%. 3. Attacker with 4% of votes meets quorum alone and can execute proposals (e.g. Agent takeover). 4. Fix: GovernorVotesQuorumFraction…
Chain
Other
Category
untagged
Date
Jan 2025
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: 50064-h-01-adversary-can-win-proposals-with-voting-power-as-low-as. Standalone Foundry PoC and full write-up: 50064-h-01-adversary-can-win-proposals-with-voting-power-as-low-as_exp in the
evm-hack-registrymirror.
Vulnerability classes: quorum-supply-drift · governance-voting-power-snapshot · governance/proposal-manipulation
Reproduction: self-contained Foundry PoC with only
forge-std— no fork. Full trace: output.txt. PoC: test/50064-h-01-adversary-can-win-proposals-with-voting-power-as-low-as_exp.sol.
Key info#
| Impact | HIGH — malicious proposal executes with only 4% of supply (comment claimed 25%) |
| Protocol | IQ AI — TokenGovernor |
| Vulnerable code | GovernorVotesQuorumFraction(4) with OZ denominator 100 → 4% quorum |
| Bug class | Quorum misconfiguration / comment-vs-code (treated as 4% effective quorum) |
| Finding | Code4rena 2025-01-iq-ai · #50064 · H-01 · reporter DoD4uFN |
| Report | code4rena.com/reports/2025-01-iq-ai |
| Source | AuditVault |
| Status | Judge maintained High (Agent ownership / LP risk on low-cap agent tokens). |
| Compiler | ^0.8.24 (PoC) |
TL;DR#
- Constructor sets
GovernorVotesQuorumFraction(4)with comment "quorum is 25% (1/4th)". - OZ
quorumDenominator()defaults to 100, so quorum =supply * 4 / 100= 4%. - Attacker with 4% of votes meets quorum alone and can execute proposals (e.g. Agent takeover).
- Fix:
GovernorVotesQuorumFraction(25).
The vulnerable code#
// constructor:
quorumNumeratorValue = 4; // claimed 25% (1/4th) — wrong for denominator 100
function quorum(uint256) public view returns (uint256) {
// @> VULN: numerator 4 / denominator 100 ⇒ 4% (intended 25%)
return (token().getPastTotalSupply(t) * quorumNumerator(t)) / quorumDenominator();
}
Root cause#
Misread of OZ quorum fraction API: 4 means 4%, not "1/4". Comment documents the intended 25% but code ships 4%.
Preconditions#
- Attacker holds ≥ 4% of voting power (delegated).
- Other holders do not vote against (or lack voting power at snapshot).
Attack walkthrough#
- Whale holds 100M supply; attacker gets 4M (4%) and self-delegates.
governor.quorum() == 4M.- Attacker proposes Agent
takeover, votes For, executes — succeeds. - With true 25% quorum (25M), the same 4% vote would fail.
Diagrams#
Impact#
Low-cap agent tokens can have multiple 4% holders; governance of Agent (holding LP) is capturable far below the documented 25% threshold.
Taxonomy#
genome: quorum-supply-drift,governance-voting-power-snapshot,governance/proposal-manipulationseverity/high·sector/governance·platform/code4rena
Sources#
- AuditVault finding #50064
- Code4rena report 2025-01-iq-ai
- Repo: code-423n4/2025-01-iq-ai ·
src/TokenGovernor.solL55 - OZ:
GovernorVotesQuorumFractionv5.2.0 L62–L74
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 50064-h-01-adversary-can-win-proposals-with-voting-power-as-low-as_exp (evm-hack-registry mirror).
- AuditVault finding: 50064-h-01-adversary-can-win-proposals-with-voting-power-as-low-as.
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.