Proud Rusty Mantis
High
Upon selling our NUMA
, we have the following code:
uint256 tokenAmount = vaultManager.numaToToken(_numaAmount, last_lsttokenvalueWei, decimals, criticalScaleForNumaPriceAndSellFee);
require(lstToken.balanceOf(address(this)) >= tokenAmount, "not enough liquidity in vault");
We convert the NUMA
to sell into an LST and check that the vault has sufficient liquidity. That is wrong as we are applying fees to the tokenAmount
afterwards which results in users being able to withdraw less than supposed to.
- User wants to sell his 1e18 NUMA which is equal to 1e18 LST (1:1 ratio)
- The fee is 0.95e18 (indicating 5e16 or 5%)
- We calculate the token out,
$1e18 * 0.95e18 / 1e18 = 0.95e18$ and we send them out to the user - We calculate the fees to send to the fee receiver like this:
uint feeTransferNum = fees * (1 ether - fee);
uint feeTransferDen = uint(BASE_1000) * 1 ether;
uint256 feeAmount = (feeTransferNum * tokenAmount) / (feeTransferDen);
-
fees
are set to 200, thus result is$200 * (1e18 - 0.95e18) * 1e18 / (1000 * 1e18) = 10 000 000 000 000 000$ and we transfer them out to the fee receiver - Total tokens sent are equal to
$10 000 000 000 000 000 + 0.95e18 = 960 000 000 000 000 000$ - If the user wanted to sell his 1e18 NUMA, we would have reverted even though we would have had more than enough tokens to satisfy the sale (let's say we have 1e18 - 1 in liquidity), this results in users having stuck funds for an unknown amount of time
Stuck funds for an unknown amount of time, until liquidity in the vault increases
Remove the check altogether as we would revert either way if the tokens are insufficient