Platform: Code4rena
Start Date: 15/12/2022
Pot Size: $128,000 USDC
Total HM: 28
Participants: 111
Period: 19 days
Judge: GalloDaSballo
Total Solo HM: 1
Id: 194
League: ETH
Rank: 104/111
Findings: 1
Award: $14.91
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xdeadbeef0x
Also found by: 0xLad, 0xNazgul, 0xSmartContract, 0xbepresent, Arbor-Finance, Breeje, HE1M, IllIllI, Qeew, Rolezn, SEVEN, SamGMK, SmartSek, TomJ, WatchDogs, ak1, btk, ck, datapunk, dic0de, eierina, fs0c, hansfriese, koxuan, ladboy233, peanuts, rvierdiiev, sces60107, tonisives, unforgiven, yongskiws
14.9051 USDC - $14.91
Empty ERC4626 vaults can be manipulated to inflate the price of a share and cause depositors to lose their deposits due to rounding in favor of the vault. In particular, this can be done as a frontrunning attack if the vault is used without specifying a minimum of shares to be received using an ERC4626 router.
The inflation attack comes from the amount of underlying AVAX
changing without the amount of ggAVAX
reflecting that. This inflation makes all the ggAVAX
more valuable, which means that someone buying ggAVAX
will get less than they would have expected.
The bigger the inflation, the bigger the effect of the attack, which is why this is particularly sensitive when then vault is its early stages, with low liquidity.
A malicious early user can deposit()
with 1 wei
of AVAX
as the first depositor of the Vault, and get 1 wei
of ggAVAX
.
Then the attacker can send 10000e18-1
of AVAX
tokens and inflate the price per share from 1.0000 to an extreme value of 1.0000e22
(from 1+10000e18-1)/1).
As a result, the future user who deposits 19999e18 will only receive 1 wei (from 19999e18 * 1 / 10000e18) of ggAVAX
.
They will immediately lose 9999e18 or half of their deposits if they redeem right after the deposit()
Visual Studio Code
The first solution is the most simple one, but also possibly the less satisfying. It doesn't actually address the issue as much as it goes around it.
Advantage:
Drawback:
Keeping track of the assets held by the vault internally remove the effect of direct transfers. Tokens transferred directly are not accounted for (unlike tokens that are explicitly transferred during a mint
/deposit
operation), which completely removes the risk of inflation attack.
This however causes other issues. Transferring tokens is still possible, and if they are not accounted for automatically, they might not be recoverable. To recover them would likely require some form of access control, which might not be desirable when building trust minimizing applications.
In addition to direct transfers, this also apply to re-basing tokens!
Advantage:
Drawback:
The last option is inspired by Uniswap V2, which created some "dead LP shares" when the first liquidity is deposited. That basically means that the first liquidity provider is giving away a fraction of its shares for monetary stability.
A similar approach could be implemented in ERC4626 vaults, by minting "dead shares" on the first deposit
/mint
. For any assets that are then transferred to the vault, a fraction would be associated to these dead shares, and not redeemable by anyone.
In addition to not solving the actual problem (it is still possible to do inflation attacks, the profit is just reduced) this approach disincentivize any early liquidity providing that is not part of an inflation attack. It asks a lot of questions with the amount of "dead shares" to mint that possibly don't have an absolute good answer, and must be answered on a case-by-case basis.
Advantage:
Drawback:
Mitigation steps posted by @Amxx in https://github.com/OpenZeppelin/openzeppelin-contracts/issues/3706#issuecomment-1297199749
#0 - c4-judge
2023-01-08T13:11:36Z
GalloDaSballo marked the issue as duplicate of #209
#1 - c4-judge
2023-02-08T09:44:19Z
GalloDaSballo marked the issue as satisfactory