After a lot of checks, function withdraw() calls to the previewWithdraw(assets) to get the shares coressponding to the amount of assets that the user want to withdraw. The vulnerability of this calculation is previewWithdraw() use the round-down instead of round-up.
In case the assets * supply < totalAssets(), the shares will get the value 0. It creates a big flaw for the attacker to steal the tokens of the vault.
See the section below for more details of the attacks.
Attack scenario
We shall assume the state of vault as follows:
totalSupply() = 100
totalAssets() = 1000
Attacker call BaseVault.withdraw(1, attacker_address, attacker_address). The corresponding shares to be burned is 1 * 100 / 1000 = 0. After the call, the attacker will get 1 asset tokens without burn any shares of him. The attacker can keep doing this until totalSupply() < totalAssets() and get a lot of money.
Title
Attacker can withdraw asset without burning any shares
Affected smart contract
https://github.com/Fujicracy/fuji-v2/blob/1b939ec84af137db430fc2aa1b4c6f15e5254003/packages/protocol/src/abstracts/BaseVault.sol#L271
Description
Function
BaseVault.withdraw()
is implemented as follows:After a lot of checks, function
withdraw()
calls to thepreviewWithdraw(assets)
to get the shares coressponding to the amount of assets that the user want to withdraw. The vulnerability of this calculation ispreviewWithdraw()
use the round-down instead of round-up.In case the
assets * supply < totalAssets()
, theshares
will get the value 0. It creates a big flaw for the attacker to steal the tokens of the vault. See the section below for more details of the attacks.Attack scenario
We shall assume the state of vault as follows:
Attacker call
BaseVault.withdraw(1, attacker_address, attacker_address)
. The corresponding shares to be burned is1 * 100 / 1000 = 0
. After the call, the attacker will get 1 asset tokens without burn any shares of him. The attacker can keep doing this untiltotalSupply() < totalAssets()
and get a lot of money.The PR to the attack test: https://github.com/Fujicracy/fuji-v2/pull/299
Recommendation
Calculate the
burnedShares
by using round-up instead of round-down calculation