RootCause & Where It Happens
In the deposit()
function:
No code checks how many tokens actually arrived in the vault after the transfer. Some ERC20 tokens charge a “transfer fee,” burning or redirecting a portion of tokens. If that happens:
The vault might only receive, say, amount * 0.98
tokens.
But depositInfo[counter].amount
is still set to amount
(the full 100%), and _mint(...)
eventually gives the user shares as if they contributed the entire amount
.
This leads to an over-credit of shares and effectively dilutes other depositors or even the vault itself.
Example
A token charges a 2% fee on every transfer.
A user calls deposit(1000)
:
They lose 1000 tokens from their account, 20 tokens are burned or redirected as fees, and 980 tokens arrive in the vault.
depositInfo[counter].amount = 1000
, though the vault only received 980.
When shares are calculated in _mint()
, it uses the full 1000
as the deposit’s contribution.
The depositor ends up with more shares than they truly deserve based on the vault’s real new collateral. Over time, this can be exploited to siphon value from honest depositors and the vault.
Impact
High severity for any environment where tokens are not strictly vanilla ERC20s (e.g., fee-on-transfer, rebasing, deflationary tokens). The vault logic fails to handle the actual delivered amount and thus inflates the depositor’s shares at everyone else’s expense.
Even if the project intends to use “standard” tokens like USDC, in practice many tokens do not follow the exact ERC20 standard. If, by mistake or design, a fee-on-transfer token is allowed, this leads to easy, direct exploitation.
Proof of Exploitation
Suppose the vault is worth 10,000 tokens total (with 10,000 total shares).
An attacker deposits 1,000 “fee-on-transfer” tokens that only deliver 900 net tokens to the vault.
The vault believes 1,000 arrived, calculates share issuance as if 1,000 was contributed. The attacker gets ~1,000 shares (10% of the vault).
In reality, the vault’s net new balance is only 900 tokens, so the attacker effectively got 100 shares for “free.”
They can later withdraw or exploit the over-minted shares to take a disproportionate fraction of the vault’s real assets.
Recommended Remediation
Check the actual token balance received. For example, before and after the safeTransferFrom
, measure the vault’s actual balance difference:
Restrict deposits to tokens that do not charge fees or cause unexpected balance changes. If the protocol only intends to accept fee-less stablecoins (e.g., a well-known USDC with no transfer fee), you might explicitly revert if the vault receives less than amount
.
Without such a check, a malicious or unsuspecting user can deposit “1000” tokens while only 900 arrive, yet still receive shares for 1000 worth of collateral.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.