code-423n4 / 2023-07-pooltogether-findings

12 stars 7 forks source link

The `maxMint` check in `Vault::_beforeMint()` could be side stepped #346

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/GenerationSoftware/pt-v5-vault/blob/b1deb5d494c25f885c34c83f014c8a855c5e2749/src/Vault.sol#L965-L974

Vulnerability details

Impact

A user could accumulate more shares than the defined maximum limit.

Proof of Concept

Suppose a user (_receiver) currently holds some shares and the maxMint limit is defined. This user can still call the mint or mintWithPermit function multiple times with _shares values that, in sum, exceed the maxMint limit. This is because the mint function's implementation does not account for the total shares a user could have after multiple mint transactions, or what they had before calling this

Here is the mint()'s function code:

function mint(uint256 _shares, address _receiver) public virtual override returns (uint256) {
    uint256 _assets = _beforeMint(_shares, _receiver);

    _deposit(msg.sender, _receiver, _assets, _shares);

    return _assets;
}

Which calls the _beforeMint() function

  /**
   * @notice Compute the amount of assets to deposit before minting `_shares`.
   * @param _shares Amount of shares to mint
   * @param _receiver Address of the receiver of the vault shares
   * @return uint256 Amount of assets to deposit.
   */
  function _beforeMint(uint256 _shares, address _receiver) internal view returns (uint256) {
    if (_shares > maxMint(_receiver)) revert MintMoreThanMax(_receiver, _shares, maxMint(_receiver));
    return _convertToAssets(_shares, Math.Rounding.Up);
  }

Tools Used

Manual Audit

Recommended Mitigation Steps

Modify the _beforeMint function to include a check that accounts for the sum of _shares to be minted and the shares already minted by the _receiver. This will ensure that users cannot exceed the maxMint limit through multiple mint transactions.

Assessed type

Invalid Validation

c4-sponsor commented 1 year ago

asselstine marked the issue as sponsor confirmed

Picodes commented 1 year ago

Downgrading to Low, considering this requirement is intended only for the amount of one transaction and not for the amount held overall by someone

c4-judge commented 1 year ago

Picodes changed the severity to QA (Quality Assurance)

PierrickGT commented 1 year ago

Fixed in the following PR: https://github.com/GenerationSoftware/pt-v5-vault/commit/c864cd798d105b2106e2e0c6f63467cf784d4fad#diff-97c974f5c3c03a0cfcbc52a5b8b9ae2196d535754ff2034e2903de1fec23508aR393 We now compare _shares to the max amount of shares the user can still mint before overflowing over uint96.