Reproduced Exploit
Tokemak: streaming fee on total assets pays the sink 99999999999999999999
_calculateSharesToMintFeeCollection prices the streaming fee from totalAssets. The sink is minted 111111111111111111111 shares and redeems 99999999999999999999 assets. A fee on the 100 of profit pays 10.
Chain
Other
Category
logic
Date
Jul 2024
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: 53524-toke-14-incorrect-streaming-fee-share-calculation-hexens-non. Standalone Foundry PoC and full write-up: 53524-toke-14-incorrect-streaming-fee-share-calculation-hexens-non_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/logic/fee-calculation · vuln/defi/fee-manipulation
Key info#
| Protocol | Tokemak |
| Finding | Hexens TOKE-14, AuditVault 53524 |
| Vulnerable code | FeeVault._mintStreamingFee |
| Harm | A 10 percent fee on 1000 assets, of which only 100 is profit, mints shares that redeem for 99999999999999999999. The profit-based fee redeems for 10. |
| Chain | local synthetic |
TL;DR#
_calculateSharesToMintFeeCollection prices the streaming fee from totalAssets. The sink is minted 111111111111111111111 shares and redeems 99999999999999999999 assets. A fee on the 100 of profit pays 10.
The vulnerable code#
// @> VULN: fee assets are totalAssets times the fee bps, not the profit
uint256 feeAssets = assets * feeBps / FEE_DIVISOR;
Root cause#
The share formula uses the whole asset balance. The streaming fee is supposed to apply to profit only.
Preconditions#
The vault has 1000 assets and 1000 shares. Profit inside the total is 100. The fee is 1000 basis points.
Attack walkthrough#
- Load 1000 assets and 1000 shares. See output.txt.
- Charge the streaming fee.
- The vulnerable branch mints
111111111111111111111shares. - Those shares redeem for
99999999999999999999assets. - The sink's token balance is that amount.
- The fixed branch, which uses profit times the fee, pays 10.
Diagrams#
Impact#
LPs give up about 90 more assets than the 10 the profit fee would take. The fixed mulDiv on profit pays exactly 10.
Remediation#
Mint profit * feeBps * supply / (totalAssets * FEE_DIVISOR - profit * feeBps), rounding up.
How to reproduce#
cd 53524-toke-14-incorrect-streaming-fee-share-calculation-hexens-non_exp
forge test -vv
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 53524-toke-14-incorrect-streaming-fee-share-calculation-hexens-non_exp (evm-hack-registry mirror).
- AuditVault finding: 53524-toke-14-incorrect-streaming-fee-share-calculation-hexens-non.
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.