Reproduced Exploit

Rubicon — First depositor bug on unmodified Compound fork

1. Fresh CToken has totalSupply == 0 and exchangeRate = 2e26. 2. Attacker mints the minimum (2e8 underlying → 1 share), then donates a large underlying amount to the CToken. 3. Victim deposits 100e18; inflated rate rounds their mintTokens to 0. 4. Attacker redeems their 1 share and drains the entir…

Apr 2023Otheruntagged3 min read

Chain

Other

Category

untagged

Date

Apr 2023

Source

AuditVault

EVM Playground

Source-level debugger — step opcodes and Solidity in sync

evm-hack-analyzer

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.

Loading fork state…

Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 48956-h-17-first-depositor-bug-on-unmodified-compound-fork-code4re. Standalone Foundry PoC and full write-up: 48956-h-17-first-depositor-bug-on-unmodified-compound-fork-code4re_exp in the evm-hack-registry mirror.


Vulnerability classes: rounding-direction · direct-drain · frontrun · first-deposit

Reproduction: self-contained Foundry PoC with only forge-std — no fork. Full trace: output.txt. PoC: test/48956-h-17-first-depositor-bug-on-unmodified-compound-fork-code4re_exp.sol.


Key info#

ImpactHIGH — attacker steals victim deposit; market per-underlying is unique so BathHouse market is bricked
ProtocolRubicon BathToken / Compound V2 CToken fork
Vulnerable codeCToken.mintFreshmintTokens = div_(actualMintAmount, exchangeRate) with no dead-share floor
Bug classFirst-deposit share inflation / rounding to zero
FindingCode4rena 2023-04-rubicon · #48956 · H-17 · reporter fs0c
Reportcode4rena.com/reports/2023-04-rubicon
SourceAuditVault
StatusAcknowledged. Classic Compound/ERC4626 first-depositor pattern.
Compiler^0.8.24 (PoC)

TL;DR#

  1. Fresh CToken has totalSupply == 0 and exchangeRate = 2e26.
  2. Attacker mints the minimum (2e8 underlying → 1 share), then donates a large underlying amount to the CToken.
  3. Victim deposits 100e18; inflated rate rounds their mintTokens to 0.
  4. Attacker redeems their 1 share and drains the entire cash (including the victim's deposit).
  5. Because BathHouse allows only one bathToken per underlying, the market cannot be recreated.

The vulnerable code#

SOLIDITY
uint mintTokens = div_(actualMintAmount, exchangeRate);
// @> VULN: no dead-share floor; inflated rate → mintTokens rounds to 0
totalSupply = totalSupply + mintTokens;
accountTokens[minter] = accountTokens[minter] + mintTokens;

Fix: on first mint, mint a dead-share floor to address(0) (Uniswap V2 style).


Root cause#

Share minting uses pure division against the exchange rate with no minimum liquidity / dead shares. A donation after a 1-wei mint inflates the rate so the next depositor rounds to zero shares while their underlying is still pulled in.


Preconditions#

  • New CToken/BathToken with totalSupply == 0.
  • Attacker can mint and transfer underlying to the CToken before the victim deposits.

Attack walkthrough#

  1. Alice mints 2e8 → 1 cToken.
  2. Alice transfers 100e18 underlying directly to the CToken.
  3. Bob mints 100e180 shares.
  4. Alice redeems 1 share → receives ~all cash including Bob's deposit.

Diagrams#

flowchart TD A["Alice mints 2e8 → 1 share"] --> B["Alice donates 100e18 underlying"] B --> C["Exchange rate inflated"] C --> D["Bob mints 100e18"] D --> E{"mintTokens = amount / rate"} E --> F["Rounds to 0 shares"] F --> G["Alice redeems 1 share"] G --> H["Alice drains Bob deposit"]

Impact#

Direct theft of depositor funds; unique-underlying market in BathHouse becomes unusable without full redeploy.


Taxonomy#

  • genome: rounding-direction, direct-drain, frontrun, first-deposit
  • severity/high · sector/lending · platform/code4rena

Sources#


Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

  • Web3Sec X hacked database: search.
  • Rekt leaderboard: search.
  • Solodit incident search: search.

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.