code-423n4 / 2023-09-asymmetry-findings

2 stars 1 forks source link

Attacker can mint afEth with cheaper price #7

Closed c4-submissions closed 9 months ago

c4-submissions commented 10 months ago

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, then price 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

    function price() public view returns (uint256) {
        if (totalSupply() == 0) return 1e18;
        AbstractStrategy vEthStrategy = AbstractStrategy(vEthAddress);
        uint256 safEthValueInEth = (ISafEth(SAF_ETH_ADDRESS).approxPrice(true) *
            safEthBalanceMinusPending()) / 1e18;
        uint256 vEthValueInEth = (vEthStrategy.price() *
            vEthStrategy.balanceOf(address(this))) / 1e18;
        return ((vEthValueInEth + safEthValueInEth) * 1e18) / totalSupply();
    }

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. Also pendingSafEthWithdraws 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

elmutt commented 9 months ago

https://github.com/asymmetryfinance/afeth/pull/162

c4-judge commented 9 months ago

0xleastwood marked the issue as duplicate of #59

c4-judge commented 9 months ago

0xleastwood marked the issue as duplicate of #25

c4-judge commented 9 months ago

0xleastwood marked the issue as satisfactory