The $3.7M Exploit That Was Predicted — Then Ignored
On March 15, 2026, an attacker extracted approximately $3.7 million in BTCB, CAKE, and WBNB from Venus Protocol's Thena (THE) market on BNB Chain. The protocol was left with $2.18 million in bad debt. Community members flagged the attacker's address months earlier. A Code4rena security audit had identified the exact vulnerability.
Venus declined to fix it, calling the donation mechanism "an intentional feature with no negative side effects."
This is the anatomy of a preventable exploit.
The Vulnerability: getCashPrior() Trusts Raw Balances
Venus Protocol is a Compound fork. Like all Compound-style lending markets, it tracks deposits through a share-based system: you deposit tokens, receive vTokens representing your share of the pool.
The critical flaw lived in how Venus calculated available cash:
// Vulnerable pattern (simplified)
function getCashPrior() internal view returns (uint) {
// Reads the contract's actual token balance
return IERC20(underlying).balanceOf(address(this));
}
This function reads the raw ERC-20 balance of the contract — not the amount deposited through the proper mint() pathway. The supply cap check, however, only validates deposits made through the standard entry point:
function mintInternal(uint mintAmount) internal {
// Supply cap is checked here
require(
totalSupply + mintAmount <= supplyCap,
"supply cap reached"
);
// ... proceeds with minting vTokens
}
The gap: If you transfer tokens directly to the contract (a "donation"), the supply cap check never fires, but getCashPrior() counts those tokens anyway. This inflates the exchange rate between the underlying token and its vToken representation.
The Attack: 9 Months of Patience
This wasn't a flash loan blitz. The attacker played the long game.
Phase 1: Accumulation (June 2025 — March 2026)
Over nine months, the attacker gradually acquired THE tokens until they controlled approximately 84% of Venus's 14.5 million THE supply cap. Community members flagged the concentration. The protocol team cited decentralization principles and took no action.
Phase 2: The Donation Loop
In March 2026, the attacker deployed a malicious contract and executed a recursive loop:
1. Borrow liquid assets (BTCB, CAKE, WBNB) against THE collateral
2. Swap borrowed assets for THE on open market
3. Donate THE directly to the vTHE contract (bypassing supply cap)
4. Exchange rate inflates → borrowing power increases
5. Repeat
Each iteration:
- Increased THE in the contract past the supply cap (raw transfer, no cap check)
- Inflated the vTHE exchange rate by 3.81x
- Pumped THE's spot price from $0.263 to over $0.51
- Expanded borrowing capacity against the inflated collateral
By the end of the loop, THE supply in Venus reached 53.23 million tokens — 367% of the 14.5 million cap.
Phase 3: Extraction and Collapse
The attacker extracted $3.7 million in liquid assets. But the selling pressure from constant market buys and the unsustainable price created a cascade:
- Health factor approached 1.0
- 8,048 liquidation transactions fired
- 42 million THE in collateral was unwound
- THE price collapsed to $0.22 (below pre-attack levels)
- The attacker suffered net on-chain losses of $4.7 million
The protocol was left with $2.18 million in bad debt. The attacker likely lost money overall — but the protocol and its users paid the price regardless.
The Audit Trail: A Bug Found and Dismissed
Here's where this exploit becomes a case study in security culture rather than just security engineering.
The donation attack vector in Compound forks is well-documented. It's been a known risk class since at least 2022. Multiple protocols have been exploited through this exact pattern.
Venus Protocol's Code4rena audit explicitly flagged the donation vulnerability. The protocol's response:
"Donations are an intentional feature with no negative side effects."
Venus had already suffered a similar attack in February 2025 on its zkSync deployment, where malicious donations caused over $700K in bad debt. Even after that incident, the BNB Chain deployment remained unpatched.
Why Standard Supply Caps Fail Against Donations
The fundamental issue is a measurement mismatch:
| What's Checked | What's Measured |
|---|---|
| Supply cap enforcement | Tokens deposited via mint()
|
| Exchange rate calculation | Raw token balance (balanceOf()) |
| Borrowing power | Derived from exchange rate |
When these measure different things, an attacker can inflate one metric without triggering the other's safety check.
The Fix: Track Internal Accounting, Not Raw Balances
// Secure pattern
uint256 internal totalCash; // Track deposits explicitly
function mintInternal(uint mintAmount) internal {
require(totalCash + mintAmount <= supplyCap, "supply cap reached");
totalCash += mintAmount;
// ... mint vTokens
}
function getCashPrior() internal view returns (uint) {
return totalCash; // Use tracked value, not balanceOf()
}
function redeemInternal(uint redeemAmount) internal {
totalCash -= redeemAmount;
// ... burn vTokens and transfer
}
This decouples the accounting from the raw balance. Donated tokens still arrive in the contract, but they don't inflate exchange rates or borrowing power.
Additional Defenses
1. Exchange Rate Bounds
uint256 constant MAX_EXCHANGE_RATE_DELTA = 1e16; // 1% per block
function exchangeRateStoredInternal() internal view returns (uint) {
uint newRate = calculateRate();
uint lastRate = lastExchangeRate;
require(
newRate <= lastRate + MAX_EXCHANGE_RATE_DELTA,
"exchange rate spike"
);
return newRate;
}
2. Concentration Limits
function mintInternal(uint mintAmount) internal {
uint userShare = (balanceOf(msg.sender) + mintAmount) * 1e18 / totalSupply;
require(userShare <= MAX_CONCENTRATION, "concentration limit");
// ...
}
3. Donation Detection via Balance Reconciliation
modifier reconcileBalance() {
uint actualBalance = IERC20(underlying).balanceOf(address(this));
uint expectedBalance = totalCash + reserves;
if (actualBalance > expectedBalance) {
// Donated tokens detected — add to reserves, not supply
reserves += (actualBalance - expectedBalance);
}
_;
}
The Broader Lesson: Audit Findings Are Not Optional
The Venus exploit is unusual not because of its technical sophistication — donation attacks are a known, documented vulnerability class — but because of the institutional failure:
- Audit identified the bug → Protocol dismissed it
- Community flagged suspicious accumulation → Protocol cited decentralization
- Previous exploit on zkSync → BNB Chain deployment remained unpatched
- 9 months of preparation → No monitoring triggered alerts
For protocol teams:
- Audit findings that you disagree with still need formal risk assessments
- "Intentional feature" is not the same as "safe feature"
- Previous exploits of the same bug class on your own protocol should trigger immediate review everywhere
- Concentration monitoring is table stakes for low-liquidity markets
For auditors:
- When a finding is dismissed, escalate in the final report
- Track whether previous findings have been addressed in re-audits
- Flag market-specific risks (thin liquidity amplifies donation attacks)
For users:
- Check if a protocol has addressed its audit findings
- Concentration of supply in any market is a red flag
- Previous exploits of the same vulnerability class = elevated risk
Timeline
| Date | Event |
|---|---|
| Feb 2025 | Venus zkSync deployment exploited via donation attack ($700K bad debt) |
| June 2025 | Attacker begins accumulating THE tokens |
| Late 2025 | Community flags concentrated THE position |
| March 15, 2026 | Exploit executed: $3.7M extracted |
| March 15, 2026 | 8,048 liquidations, THE collapses to $0.22 |
| March 15, 2026 | Venus suspends THE market, zeros collateral factor |
| Post-exploit | Protocol left with $2.18M bad debt |
Conclusion
The Venus Protocol exploit is a masterclass in what happens when security findings are treated as suggestions rather than requirements. The technical fix is straightforward — track internal accounting instead of trusting raw balances. But the real vulnerability was organizational: a protocol that dismissed auditors, ignored community warnings, and failed to learn from its own previous exploit.
In DeFi security, the most dangerous bugs aren't the ones nobody finds. They're the ones everybody finds — and nobody fixes.
This article is part of the DeFi Security Research series analyzing real-world exploits and the defensive patterns that could have prevented them.
Top comments (0)