This is how price is calculated. First, function calculates eth amount that contract holds in safEth tokens. You can see, that safEthBalanceMinusPending function is used to get amount. This function doesn't include safEth that is requested to withdraw. And then vEth amount in terms of eth is calculated. And this total amount then divided by whole totalSupply.
This means that when withdraw request is done, then eth amount of safEth token and vEth token has decreased, but totalSupply of afEth is still the same. As result, price of token decreases.
While this incorrect for everyone, this also can be used by attacker(some eth whale) in order to mint tokens cheaper. To do that he will need to deposit big amount of eth to the afEth. Then signal withdraw request for all his tokens and mint for example same amount. Soon, he will start earn profit every round he does so, as he will always mint tokens cheaper.
Tools Used
VsCode
Recommended Mitigation Steps
Change last line of price function:
return ((vEthValueInEth + safEthValueInEth) * 1e18) / (totalSupply() - balanceOf(address(this)));
Lines of code
https://github.com/code-423n4/2023-09-asymmetry/blob/main/contracts/AfEth.sol#L133-L141
Vulnerability details
Impact
Attacker can mint afEth with cheaper price and then withdraw.
Proof of Concept
When user would like to buy some
amount
of afEth tokens, thenprice
is calculated. This price will be used to calculate amount of tokens to mint.https://github.com/code-423n4/2023-09-asymmetry/blob/main/contracts/AfEth.sol#L133-L141
This is how price is calculated. First, function calculates eth amount that contract holds in safEth tokens. You can see, that
safEthBalanceMinusPending
function is used to get amount. This function doesn't include safEth that is requested to withdraw. And then vEth amount in terms of eth is calculated. And this total amount then divided by whole totalSupply.Now, we need to look, how withdraw requests work. First important this is that afEth, sent by user, isn't burnt, but transferred to the contract, which means that
totalSupply
remains same after request. But, when vEth is requested to withdraw, then it shares are burnt at the moment of request. AlsopendingSafEthWithdraws
is increased with safEth amount.This means that when withdraw request is done, then eth amount of safEth token and vEth token has decreased, but totalSupply of afEth is still the same. As result, price of token decreases.
While this incorrect for everyone, this also can be used by attacker(some eth whale) in order to mint tokens cheaper. To do that he will need to deposit big amount of eth to the afEth. Then signal withdraw request for all his tokens and mint for example same amount. Soon, he will start earn profit every round he does so, as he will always mint tokens cheaper.
Tools Used
VsCode
Recommended Mitigation Steps
Change last line of price function:
return ((vEthValueInEth + safEthValueInEth) * 1e18) / (totalSupply() - balanceOf(address(this)));
Assessed type
Error