code-423n4 / 2023-05-venus-findings

2 stars 1 forks source link

First Deposit Bug in VToken #224

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-05-venus/blob/main/contracts/VToken.sol#L776

Vulnerability details

Impact

Loss of user funds due to incorrect rounding

Details

The amount of VTokens minted to a user are based on the following calculations:

function _mintFresh(
        address payer,
        address minter,
        uint256 mintAmount
    ) internal {
        //... removed other irrelevant code
        Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });

        uint256 actualMintAmount = _doTransferIn(payer, mintAmount);

        uint256 mintTokens = div_(actualMintAmount, exchangeRate); //@audit first deposit bug

        totalSupply = totalSupply + mintTokens;
        uint256 balanceAfter = accountTokens[minter] + mintTokens;
        accountTokens[minter] = balanceAfter;

    }

function _exchangeRateStored() internal view virtual returns (uint256) {
        uint256 _totalSupply = totalSupply;
        if (_totalSupply == 0) {
            return initialExchangeRateMantissa;
        } else {
            uint256 totalCash = _getCashPrior();
            uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;
            uint256 exchangeRate = (cashPlusBorrowsMinusReserves * expScale) / _totalSupply;

            return exchangeRate;
        }
    }

For a newly deployed VToken, the totalBorrows, badDebt and totalReserves would be zero, and the exchange rate would be equal to either of the one:

  1. initialExchangeRateMantissa, in case totalSupply is zero.
  2. exchange_rate = underlying.balanceOf(this) * 1e18 / totalSupply

An attacker can follow these steps to manipulate the exchange rate:

  1. Just after VToken is deployed, mint the smallest amount of VTokens possible.
  2. Transfer underling tokens directly to the contract to inflate the exchange rate, if any user now transfers tokens less than the value of exchangeRate the mintTokens value would be rounded down to zero.
  3. redeem the VToken balance for the entire underlying token balance of the VToken contract.

The attacker would transfer a large amount of tokens in step 2 so that all the user transfers would round down to zero and later they can redeem all the underlying tokens from the contract.

For more info: https://akshaysrivastav.hashnode.dev/first-deposit-bug-in-compoundv2-and-its-forks

Recommendation

The protocol owners can perform the initial deposit themselves with a small amount of underlying tokens and then burn the received VTokens by sending them to a dead address.

Assessed type

Math

c4-judge commented 1 year ago

0xean marked the issue as duplicate of #314

c4-judge commented 1 year ago

0xean marked the issue as satisfactory

c4-judge commented 1 year ago

0xean changed the severity to 2 (Med Risk)