Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Valid

Inconsistent Vault Share Recipient Parameter in `LendingPool::_withdrawFromVault` Function

Summary

The LendingPool contract integrates with a Curve crvUSD Vault to manage liquidity. During the deposit process, the contract correctly mints vault shares to itself (i.e., using address(this)). However, during withdrawal, the contract incorrectly passes msg.sender as the account from which vault shares are to be burned. This inconsistency can lead to errors in share accounting and potential failures in liquidity operations.

Vulnerability Details

In the LendingPool contract, the liquidity management functions interact with the Curve vault as follows:

  • Deposit Flow:
    The function _depositIntoVault approves the vault to transfer the reserve asset, then deposits the asset with the vault while specifying address(this) as the recipient. This ensures that the vault shares are allocated to the LendingPool contract.

    function _depositIntoVault(uint256 amount) internal {
    IERC20(reserve.reserveAssetAddress).approve(address(curveVault), amount);
    curveVault.deposit(amount, address(this));
    totalVaultDeposits += amount;
    }
  • Withdrawal Flow:
    In contrast, the function _withdrawFromVault calls the vault’s withdrawal function and passes msg.sender as the account from which the shares should be burned. Since the vault shares were minted to address(this), this inconsistency results in the vault trying to burn shares from an account that does not hold them.

    function _withdrawFromVault(uint256 amount) internal {
    curveVault.withdraw(amount, address(this), msg.sender, 0, new address[](0));
    totalVaultDeposits -= amount;
    }

The discrepancy arises because the deposit process designates the LendingPool contract as the owner of the vault shares, while the withdrawal process mistakenly uses the external caller (msg.sender). This misalignment can cause the following issues:

  • Incorrect Share Burning: The vault will attempt to burn shares from msg.sender, who likely does not possess the vault shares.

  • Transaction Reversion: If msg.sender does not have the required shares, the withdrawal transaction may revert, thereby locking liquidity.

POC

  1. Initial Deposit:

    • A user (User A) calls the deposit function with a valid amount.

    • The LendingPool contract deposits the asset into the Curve vault by calling _depositIntoVault, which mints vault shares to address(this).

    • The state variable totalVaultDeposits is incremented accordingly.

  2. Attempted Withdrawal:

    • Later, User A calls the withdraw function, which triggers the internal _ensureLiquidity function.

    • If additional liquidity is required from the Curve vault, _withdrawFromVault is invoked.

    • The withdrawal call passes msg.sender (i.e., User A) instead of address(this) as the account from which vault shares should be burned.

    • Since User A does not hold the vault shares (the shares are held by the LendingPool contract), the Curve vault's withdrawal mechanism fails or reverts due to an insufficient share balance.

Impact

Users may be unable to withdraw funds from the LendingPool because the withdrawal process incorrectly targets the wrong account for share burning. This error can result in a complete DOS of the withdrawal functionality.

Tools Used

  • Manual Review

  • Integration: Implementation of the Curve vault CurveVault

Recommendations

Update the _withdrawFromVault function to pass address(this) for share burning, ensuring it matches the deposit logic.

Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

LendingPool::_withdrawFromVault incorrectly uses msg.sender instead of address(this) as the owner parameter, causing vault withdrawals to fail

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

LendingPool::_withdrawFromVault incorrectly uses msg.sender instead of address(this) as the owner parameter, causing vault withdrawals to fail

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.