
Four exploits in the last week of August, $9M lost across Base, Ethereum and BNB Chain. None involved a stolen key or a compromised admin. Three of the four came down to a price the contract had no business trusting — an illiquid collateral token, a spot reserve, a pair balance mid-transfer. The fourth skipped an ownership check entirely and moved 52 people's tokens without approval. In every case the code ran exactly as written. Below is what broke in each, and the invariant that would have caught it.
Moonwell's lending market priced MAMO collateral off a manipulable on-chain source with no manipulation-resistant guard and no liquidity or supply cap before granting borrowing power. Because MAMO is relatively illiquid, the attacker could move its price cheaply, inflate the value of their MAMO collateral, and borrow far more real cbBTC than the collateral was genuinely worth, leaving the lending market with bad debt. Proceeds were aggregated at an attacker-controlled address — Etherscan-tagged "Moonwell Exploiter 2," funded from Tornado.Cash and holding ~$8.7M multichain — and cycled through 700 ETH swaps via Velora and 1inch as the drained value was consolidated.
Invariant broken: collateral must be valued from a manipulation-resistant source, and borrowing power must be capped against the collateral's real liquidity.
An approval-check bypass in Enjin's ERC-1155 Crypto Items platform. Each item routes transfers through a per-item transfer adapter, and the attacker registered or used a malicious adapter that skips the owner-approval check. That let their exploit contract call transferFrom(holder, attacker, 1) and pull ENJ-backed items out of roughly 52 unrelated holders' wallets with no approval and no setApprovalForAll, producing real TransferSingle events. The attacker then called melt() on each stolen item to redeem the 500-ENJ backing per item from the platform reserve, netting about 5.24M ENJ. The transaction shows many small ENJ transfers out of the reserve and ERC-1155 items moving from holders to the attacker with no approval events.
Invariant broken: no transfer path may move a holder's tokens without that holder's approval, regardless of which adapter routes it.
The CashCowCoin sale/AMM contract prices buys and sells from the spot reserves of the CCC/WBNB PancakePair via getReserves(), with no TWAP or manipulation-resistant source. The attacker flash-loaned roughly 416,831 WBNB from a Moolah lending market, donated WBNB directly into the pair and called sync() to inflate its reserves, then cycled buy/sell against the manipulated price to extract the pair's real liquidity — draining the CCC/WBNB pair from about 165.5 WBNB down to roughly 0.018 WBNB and netting about 165.47 WBNB after repaying the loan. The transaction confirms it: the large flash loan, the WBNB routed through the pair, and hundreds of CCC transfers as the loop runs.
Invariant broken: a trade must not price off a reserve an attacker can move within the same transaction.
Flawed deflationary sell-tax logic in FHToken._transfer. On sells, the isSell path burns and redistributes tokens from the PancakeSwap pool's own balance (80% to dead, 20% redistributed) and calls sync() before the seller's net amount settles, which inflates the pair's reserves relative to real balances. The attacker looped buy/sell transactions to exploit the reserve mismatch each iteration created, draining USDT from the pool. The transaction shows repeated FH and BSC-USD movements through the PancakeSwap V2/V3 pools with a Lista DAO flash loan funding the loop. The flash loan is amplification; the defect is that the token's transfer logic manipulates the pair's reserves via a premature sync() before balances settle.
Invariant broken: a token's transfer logic must not mutate a pair's reserves, and reserves must never be synced against unsettled balances.