Core Contracts

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

Owner Mismatch in Curve Vault Rebalancing

Summary

The _rebalanceLiquidity function deposits assets into Curve Vault with address(this) as the owner, but tries to withdraw them with msg.sender as the owner. This fails because msg.sender doesn’t own the shares.

Vulnerability Details

In _depositIntoVault, the contract calls curveVault.deposit(amount, address(this)), making the lending pool (address(this)) the owner of the minted shares. Later, in _withdrawFromVault, it calls curveVault.withdraw(amount, address(this), msg.sender, 0, []), telling Curve Vault to burn shares owned by msg.sender. But msg.sender (the user calling deposit) never received shares—address(this) did. Curve Vault’s withdraw function checks the owner and reverts because msg.sender has no shares to burn. For example:

  • User deposits 100 crvUSD.

  • _rebalanceLiquidity moves 50 crvUSD to Curve Vault, owner = address(this).

  • Later, it tries to withdraw 20 crvUSD, claiming msg.sender as owner, but fails.

LendingPool._depositIntoVault

LendingPool._withdrawFromVault

https://github.com/curvefi/scrvusd/blob/95a120847c7a2901cea5256ba081494e18ea5315/contracts/yearn/VaultV3.vy#L1795C1-L1810C18

https://github.com/curvefi/scrvusd/blob/95a120847c7a2901cea5256ba081494e18ea5315/contracts/yearn/VaultV3.vy#L1827-L1846

Impact

Withdrawals from Curve Vault fail during rebalancing, leaving liquidity stuck. Users can deposit, but the pool can’t pull funds back when needed, breaking borrowing or withdrawal functions that rely on _ensureLiquidity. This locks up assets and disrupts the system.

Tools Used

Manual review of deposit, _rebalanceLiquidity, _depositIntoVault, _withdrawFromVault, and Curve Vault’s deposit/withdraw functions.

Recommendations

  1. Fix Owner in Withdraw: Use address(this) as the owner in _withdrawFromVault since it owns the shares.

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

Lead Judging Commences

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