Reproduced Exploit
Y2K Earthquake — `depositFee` can be bypassed via the deposit queue
Chain
Other
Category
logic
Date
Jan 1970
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: 18535-h-3-depositfee-can-be-bypassed-via-deposit-queue-sherlock-no. Standalone Foundry PoC and full write-up: 18535-h-3-depositfee-can-be-bypassed-via-deposit-queue-sherlock-no_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/logic/fee-calculation · vuln/defi/fee-theft
Reproduction: the test deploys the REAL audited
Carousel(VaultV2+ a standard OpenZeppelinERC1155) — no protocol logic is mocked; only the opaque underlying and emissions tokens are minimal real ERC-20s. It charges the dynamic deposit fee on the real direct-deposit path and shows the real queue path (deposit(0,…)+mintDepositInQueue) mints the same position for zero deposit fee.
Root cause#
Audited source: sherlock-audit/2023-03-Y2K @ 93e3994, file
Earthquake/src/v2/Carousel/Carousel.sol,
vendored here at src/src/v2/Carousel/Carousel.sol.
The dynamic depositFee (linear from 0 at epoch creation up to depositFee bps at
epoch start) is charged only on the direct path, _deposit for a non-zero epoch id:
if (depositFee > 0) {
...
uint256 feeAmount = _assets.mulDivDown(fee, 10000);
assetsToDeposit = _assets - feeAmount;
_asset().safeTransfer(treasury, feeAmount); // fee -> treasury
}
The queue path does not. A deposit to epoch 0 is only pushed onto depositQueue
(no fee), and mintDepositInQueue later mints it while deducting only the relayer
fee — never the deposit fee:
_mintShares(queue[i].receiver, _epochId, queue[i].assets - relayerFee); // no depositFee
...
asset.safeTransfer(msg.sender, _operations * relayerFee); // relayer paid
A late depositor therefore routes into the epoch-0 queue and, in the same transaction,
self-relays mintDepositInQueue — minting their epoch position while paying zero deposit
fee and recovering the relayer fee they advanced. The treasury loses the fee revenue.
The fix (Y2K PR #126) adds a minimum
deposit requirement to enlistInRollover and reworks the queue economics so queue mints
are no longer fee-free.
Reproduction (real numbers)#
relayerFee = 1e18, depositFee = 250 (2.5%, the constructor maximum), deposit amount
100e18.
- Honest direct depositor (Foundry test, warped to
epochBegin): pays the full100e18 × 250/10000 = 2.5e18fee to the treasury and receives97.5e18shares. - Attacker via the queue:
deposit(0, 100e18)then self-relayedmintDepositInQueue(1, 1)→ mints100e18 − 1e18 = 99e18shares, treasury receives0, and the1e18relayer fee is returned to the attacker (self-relay), so the total fee paid is exactly 0.
Net effect: the fee-dodger out-mints the honest depositor by 1.5e18 shares (and by the
full 2.5e18 fee once the recovered relayer fee is accounted for), and the protocol
collects nothing.
Run#
_shared/run-poc/run_poc.sh 18535-h-3-depositfee-can-be-bypassed-via-deposit-queue-sherlock-no_exp -vvvvv
Expected: [PASS] testDepositFeeBypassedViaQueue. The logs print the direct fee
(2.5e18), the queue fee (0), and the extra shares gained by fee-dodging (1.5e18);
the assertions in
test/18535-h-3-depositfee-can-be-bypassed-via-deposit-queue-sherlock-no_exp.sol
enforce every number.
Sources#
- AuditVault finding #18535
- Sherlock 2023-03-Y2K issue #75
- Audited
Carousel.sol@ 93e3994 - Y2K fix PR #126
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 18535-h-3-depositfee-can-be-bypassed-via-deposit-queue-sherlock-no_exp (evm-hack-registry mirror).
- AuditVault finding: 18535-h-3-depositfee-can-be-bypassed-via-deposit-queue-sherlock-no.
- Upstream DeFiHackLabs PoC directory: src/test.
Alerts & third-party analyses
- DeFiHackLabs incident explorer: search "Y2K Earthquake".
- 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.