Worked example · 2022-07
Audius governance storage-collision attack — Ethereum — 2022-07-23
Summary
Audius is a decentralised music-streaming protocol with on-chain governance over a community treasury denominated in AUDIO tokens. Audius's smart-contract architecture uses an upgradeable-proxy pattern (a Governance logic contract behind a Storage proxy). On 2022-07-23, an attacker submitted governance proposal #75, titled "Establish Community Guardian," whose payload exploited a storage-layout flaw in the Audius Governance Storage Proxy: variables introduced across upgrades had not been laid out in slots that respected the inherited storage layout, with the result that a subset of writes intended to set "voting parameters" overlapped, in storage-slot terms, with the slot that held the role-assignment variable controlling the guardianAddress field.
The attacker used proposal #75 to write into the colliding slot, setting themselves as the sole guardianAddress for the protocol. Once the role was assigned, the attacker invoked the privileged path the role unlocked — submitting and self-executing a follow-on proposal that transferred ~18.5M AUDIO from the community treasury to attacker-controlled addresses. The AUDIO was bridged out and swapped for ~705 ETH on Uniswap; a portion was routed through Tornado Cash. Audius paused the affected contracts the same day, published an incident timeline and post-mortem, and subsequently shipped a re-audited governance contract.
The case is OAK's reference example for the storage-collision subclass of T9.003 because the failure mode is not "the attacker acquired enough voting power to pass a malicious proposal" (Beanstalk's pattern) but rather "the proxy storage layout let a benign-looking proposal write into a privileged role slot." The two subclasses share a Tactic and a Technique number but diverge on detection and mitigation.
Timeline (UTC)
| When | Event | OAK ref |
|---|---|---|
| Pre-event | Audius governance contracts upgraded multiple times under the Storage-Proxy pattern; storage layout inherits across upgrades | (standing T9.003 surface) |
| 2022-07-23 (proposal submission) | Proposal #75 ("Establish Community Guardian") submitted by attacker-controlled address | T9.003 setup |
| 2022-07-23 (proposal execution) | Proposal #75 executed; payload writes into the slot controlling guardianAddress, setting attacker as sole guardian |
T9.003 execution (storage-collision) |
| 2022-07-23 (follow-on proposal) | With guardian role acquired, attacker submits and self-executes a transfer of ~18.5M AUDIO from the community treasury | T9.003 + T9.004 extraction |
| 2022-07-23 (within hours) | Drained AUDIO bridged out and swapped for ~705 ETH on Uniswap | T5 outflow |
| 2022-07-23 (within hours) | Audius pauses affected contracts; incident page published | (defender response) |
| Subsequent days | Portion of proceeds routed through Tornado Cash | T7.001 |
| Subsequent | Audius ships re-audited governance contracts; post-mortem with detailed root-cause analysis published | (recovery / mitigation) |
What defenders observed
- Pre-event (proxy-storage-layout layer): Audius's governance contract architecture used the standard upgradeable-proxy pattern, with logic-contract upgrades shipped over time. Storage-layout management in upgradeable proxies requires that every newly-introduced variable in a child contract be declared in a slot that does not collide with any slot used by inherited or previously-declared variables. The Audius layout, across multiple upgrades, had introduced variables in a way that produced an overlapping slot — a classic upgradeable-proxy storage-collision failure mode that had been documented in the audit literature (OpenZeppelin proxy guidance, Trail of Bits Slither/crytic-style analysers) for years before this incident. This was a standing T9.003 surface from the moment the colliding upgrade was deployed.
- At-event (governance-side signal): proposal #75 was a non-standard governance call whose payload wrote into a slot that should not have been writable by a normal voting-parameter update. A storage-layout-aware governance-payload analysis would have flagged the proposal at submission. Audius's runtime governance pipeline did not perform such an analysis.
- At-event (role-assignment signal): the
guardianAddressfield was changeable via the proposal-execution path with no separate proposer-eligibility check, no multi-sig confirmation, and no time-locked role-rotation guard — the T9.004 contributory surface. Once the storage write succeeded, the role-assignment took effect immediately and the privileged extraction path was unlocked in the same transaction. - Post-event: Audius's pause-and-relaunch response is the standard mitigation chain for a T9.003 incident at the affected-protocol layer. The published post-mortem is a useful artefact for OAK contributors because it documents the storage-collision root cause at slot-level granularity.
What this example tells contributors writing future Technique pages
- T9.003 has at least two distinct subclasses. Beanstalk (
/examples/2022-04-beanstalk.md) is the flash-loan-enabled quorum-acquisition subclass — the attacker acquires enough voting power to legitimately pass a malicious proposal, and the failure is that voting power was acquirable over a single block. Audius is the storage-collision subclass — the attacker submits a proposal whose payload writes into a privileged role slot via an upgradeable-proxy storage-layout flaw, and the failure is that the proxy storage layout was not invariant across upgrades. The two subclasses share a Technique number but have different detection signals (vote-power-vs-flash-loan vs payload-storage-write-analysis) and different mitigations (snapshot voting / quorum delay vs proxy-storage-layout discipline / storage-gap reservation / OpenZeppelin upgrade-safety checks). T9.003 contributors should preserve the subclass distinction. - T9.004 is contributory, not standalone, here. The absent proposer-eligibility / role-assignment guard on
guardianAddressis a real T9.004 surface, but it would not have been exploitable in isolation — the attacker reached that surface through the storage-collision write. Worked examples should distinguish the precondition Technique (here, T9.003 storage-collision) from the contributory surface (here, T9.004 role-assignment guard) and resist labelling the incident with whichever is more visible. - Storage-collision is a code-review-layer Technique. Detection lives at audit time, not at runtime. The OpenZeppelin upgrade-safety tooling, Slither / crytic-compile storage-layout diff checks, and the standard "storage gap" pattern for upgradeable contracts are all known mitigations from before the Audius incident. Mitigation guidance for the T9.003 storage-collision subclass should reflect this — it is mostly a question of whether the protocol used the available tooling, not whether the tooling existed.
- Pseudonymous attribution is the v0.1 norm. As with Beanstalk, Saddle, and Inverse, the Audius attacker did not publicly self-identify and no authoritative public attribution was made. OAK records this case as
pseudonymous / unattributed.
Public references
- Audius — Audius Governance Takeover Post-Mortem — protocol-side post-mortem with slot-level root-cause analysis.
- PeckShield — Audius Governance Hack Analysis — same-day on-chain trace of proposal #75 and the storage-collision write path.
- Halborn — Explained: The Audius Hack (July 2022) — defender-oriented technical post-mortem.
- The Block — Audius governance attack drains $6 million from community treasury — contemporaneous coverage.
- OpenZeppelin — Writing Upgradeable Contracts: Storage Layout — pre-existing public guidance on the storage-collision failure mode.
[zhou2023sok]— academic taxonomy classifying this as a governance / proxy-storage-layout chain.
Discussion
Audius is OAK's canonical T9.003 case for the storage-collision subclass because the public root-cause analysis is unusually clean — Audius's own post-mortem reports the exact slot collision, and the PeckShield trace reconstructs the storage-write at on-chain granularity. Pairing it with Beanstalk in the v0.1 example set forces contributors writing T9.003 pages to grapple with the subclass distinction; without Audius, the framework's T9.003 vocabulary tends to collapse into the Beanstalk shape and miss the proxy-storage-layout failure mode entirely.
The structural parallel to Wintermute (/examples/2022-09-wintermute.md) is also worth flagging: in both cases, mitigation guidance for the failure mode existed in the public record well before the incident — OpenZeppelin's upgrade-safety documentation for Audius, 1inch's Profanity disclosure for Wintermute. The recurring observation is that publicly-known-vulnerability-class-with-public-mitigation-guidance is a pattern OAK does not yet surface as a cross-cutting axis. As noted in the Wintermute Discussion, this is a v1.0-era taxonomy question; Audius is one more data point that the question will eventually need a structural answer.
The Chainalysis 2022 retrospective records governance-attack incidents at a smaller dollar scale than oracle-manipulation incidents in aggregate, but with disproportionately high publication-of-root-cause clarity — the failure modes are well-documented in the open audit literature, which makes the cohort useful for teaching even when individual losses are mid-six- to mid-seven-figures.