sherlock-audit / 2023-01-derby-judging

4 stars 1 forks source link

SPYBOY - First depositor can manipulate share price of MainVault #358

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

SPYBOY

high

First depositor can manipulate share price of MainVault

Summary

The first depositors can mint 1 share and send in a large amount of Token into MainVault. The price of 1 share will be inflated. The next depositor who deposits will lose out due to a rounding error.

Vulnerability Detail

The adversary will call deposit with the amount of 1 to mint 1 share. He then transfers a large amount of Tokens over 1000 to the address of Mainvault. The price of 1 share is now 1001. The next depositor deposits 2000 and receives 1 share due to a rounding error. The pool has 3001 assets with 2 shares. The adversary can withdraw his 1 share and receive 1500 assets, gaining 500 assets.

  function deposit(
    uint256 _amount,
    address _receiver
  ) external nonReentrant onlyWhenVaultIsOn returns (uint256 shares) {
    if (training) {
      require(whitelist[msg.sender]);
      uint256 balanceSender = (balanceOf(msg.sender) * exchangeRate) / (10 ** decimals());
      require(_amount + balanceSender <= maxTrainingDeposit);
    }

    uint256 balanceBefore = getVaultBalance() - reservedFunds;
    vaultCurrency.safeTransferFrom(msg.sender, address(this), _amount);
    uint256 balanceAfter = getVaultBalance() - reservedFunds;

    uint256 amount = balanceAfter - balanceBefore;
    shares = (amount * (10 ** decimals())) / exchangeRate;

    _mint(_receiver, shares);
  }
  function withdraw(
    uint256 _amount,
    address _receiver,
    address _owner
  ) external nonReentrant onlyWhenVaultIsOn returns (uint256 value) {
    value = (_amount * exchangeRate) / (10 ** decimals());

    require(value > 0, "!value");

    require(getVaultBalance() - reservedFunds >= value, "!funds");

    _burn(msg.sender, _amount);
    transferFunds(_receiver, value);
  }

Impact

The first depositors can manipulate share prices to gain from future depositors.

Code Snippet

deposit() : https://github.com/sherlock-audit/2023-01-derby/blob/main/derby-yield-optimiser/contracts/MainVault.sol#L106-L124 withdraw() : https://github.com/sherlock-audit/2023-01-derby/blob/main/derby-yield-optimiser/contracts/MainVault.sol#L131-L144

Tool used

Manual Review

Recommendation

Recommend requiring minimum amount of shares for first depositor and burning some shares of first depositor so that price of share will be more resistant.

Duplicate of #258