Core Contracts

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

Incorrect `owner` parameter in `Lendingpool::_withdrawFromVault` disrupts the protocol's ability to manage vault shares, leading to transaction failures

Summary

The owner parameter in the Curve vault's withdraw call is set to msg.sender (the user) instead of the LendingPool itself (address(this)). This is a critical error because the LendingPool is the entity that owns the shares in the vault, not the user. The user isn't interacting directly with the vault, so they don't have any shares there. Therefore, the parameters for the withdraw call are incorrect. The third parameter (owner) should be address(this) instead of msg.sender. This mistake leads to failed transactions when attempting to withdraw from the vault, breaking core functionality of the protocol.

Vulnerability Details

The Curve Vault's withdraw function is called with msg.sender as the owner parameter:

curveVault.withdraw(amount, address(this), msg.sender, 0, new address[](0));

The owner parameter specifies the address that owns the shares in the vault. Since the LendingPool deposited into the vault (via _depositIntoVault), the shares belong to the LendingPool (address(this)), not the user (msg.sender). Using msg.sender here causes the vault to check the user's balance (which is zero), leading to transaction reverts.

Looking at the deposit function, when the LendingPool deposits into the vault in _depositIntoVault, it's calling curveVault.deposit(amount, address(this)). The deposit function mints shares to the receiver, which in this case is the LendingPool.

//LendingPool::_depositIntoVault function
function _depositIntoVault(uint256 amount) internal {
curveVault.deposit(amount, address(this)); // Shares go to LendingPool
}
// The LendingPool `(address(this))` is the receiver, making it the `owner` of the vault shares.

Therefore, the LendingPool holds the shares in the vault. Thus, when withdrawing, the owner must be the LendingPool (address(this)), so that the vault can burn the correct shares.

But In the current code, the owner is set to msg.sender (the user).

//LendingPool::_withdrawFromVault function
function _withdrawFromVault(uint256 amount) internal {
curveVault.withdraw(amount, address(this), msg.sender, 0, new address[](0));
}

Since the user doesn't own any shares in the vault, this will result in the Curve vault's withdraw function reverting because the owner doesn't have enough shares.

Impact

Any operation requiring liquidity from the vault (user withdrawals or borrows) will fail when the LendingPool attempts to withdraw, as the user lacks vault shares. Core functionalities (withdrawals, borrows) become unusable if the RToken's balance is insufficient and needs vault liquidity.

Tools Used

Manual review

Recommendations

Adjust the owner parameter to address(this) (i.e LendingPool)

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

Lead Judging Commences

inallhonesty Lead Judge 7 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 7 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.

Give us feedback!