First-Depositor Inflation in an ERC-4626-Style Vault
A vault that prices shares from its own token balance lets an attacker capture the next deposit with a 1-wei position and a donation.
NaiveVault mirrors a pattern common in early yield vaults: totalAssets() returns asset.balanceOf(address(this)), and shares are minted with plain floor division. PatchedVault applies virtual shares and assets with a decimals offset of 6, and rounds in the protocol's favour.
Both contracts and every test referenced below are in the lab directory listed on this page.
highXV-DEMO-01 · Verified by testDonation inflates share price so the next deposit mints zero shares
Donation inflates share price so the next deposit mints zero shares
Description
With 1 share outstanding, a direct token transfer raises totalAssets() without minting shares. A following deposit of X tokens computes X * 1 / (X + 1), which rounds to zero.
Impact
An attacker who front-runs the first real deposit captures the victim's entire deposit.
Recommendation
Use virtual shares with a decimals offset, mint dead shares at deployment, or track assets internally instead of via balanceOf.
mediumXV-DEMO-02 · Verified by testpreviewWithdraw rounds down, contrary to ERC-4626
previewWithdraw rounds down, contrary to ERC-4626
Description
Shares burned for a fixed-asset withdrawal are computed with floor division, so at a share price above 1 a small withdrawal burns zero shares.
Impact
Repeated small withdrawals leak value from remaining depositors.
Recommendation
Round up when computing shares burned for a fixed asset amount.
lowXV-DEMO-03 · Identified by reviewNo slippage protection on deposit
No slippage protection on deposit
Description
deposit accepts no minimum-shares parameter, so users cannot bound the outcome of a front-run transaction.
Impact
Combined with XV-DEMO-01, users have no on-chain way to abort an unfavourable deposit.
Recommendation
Offer a router or wrapper with a minSharesOut parameter.
Measured in the lab: against NaiveVault, a 10,000-token victim deposit minted 0 shares and the attacker's net gain was exactly 10,000 tokens. Against PatchedVault, the same sequence left the victim with at least 99.99% of their deposit and the attacker with a net loss.
Withdrawing 1 wei at a share price of roughly 2 burned 0 shares in NaiveVault and at least 1 share in PatchedVault. XV-DEMO-03 was identified by review and is not exercised by a test.
The lab code and tests for this case study live in labs/web3 of the Xevry website repository.
cd labs/web3npm installnpx hardhat test test/VaultInflation.test.jsFiles: labs/web3/contracts/Vaults.sol · labs/web3/test/VaultInflation.test.js
Let's discuss your security needs.
Tell us what you're building. We'll respond with clear questions, an honest view of whether we're the right fit, and a scoped proposal if we are.