Core Contracts

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

`LendingPool::_depositIntoVault` would always revert because insufficient balance

Summary

Lending pool have mechanism where if there are excess amount of asset token from the desiredBuffer, then the excess would be sent into the curve vault. But this function would fail because the function would deposit the asset token from LendingPoolinto the curve vault, but the asset token are saved inside the RToken contract address, not in the LendingPool contract itself.

Vulnerability Details

lets take a look in LendingPool::

LendingPool.sol#L772-L793

function _rebalanceLiquidity() internal {
// if curve vault is not set, do nothing
if (address(curveVault) == address(0)) {
return;
}
uint256 totalDeposits = reserve.totalLiquidity; // Total liquidity in the system
uint256 desiredBuffer = totalDeposits.percentMul(liquidityBufferRatio);
@> uint256 currentBuffer = IERC20(reserve.reserveAssetAddress).balanceOf(reserve.reserveRTokenAddress);
if (currentBuffer > desiredBuffer) {
uint256 excess = currentBuffer - desiredBuffer;
// Deposit excess into the Curve vault
_depositIntoVault(excess);
} else if (currentBuffer < desiredBuffer) {
uint256 shortage = desiredBuffer - currentBuffer;
// Withdraw shortage from the Curve vault
_withdrawFromVault(shortage);
}
emit LiquidityRebalanced(currentBuffer, totalVaultDeposits);
}

notice that the currentBuffervalue is actually the asset token held inside the reserve.reserveRTokenAddress not this contract.

so if the if currentBuffer > desiredBuffer is satisfied, the function would then call _depositIntoVaultwith the excess.

LendingPool.sol#L799-L803

function _depositIntoVault(uint256 amount) internal {
IERC20(reserve.reserveAssetAddress).approve(address(curveVault), amount);
curveVault.deposit(amount, address(this));
totalVaultDeposits += amount;
}

it try to approve the curveVault address to spend excess amount, but the deposit function would revert because there are no token asset inside this lending pool contract that can be sent. thus making this function revert with insufficient balance.

Impact

  1. potential DoS for function that call the faulty _rebalanceLiquiditylike LendingPool's deposit, withdraw, and repay

  2. DoS cant be stopped by setting the curve vault to address(0) to make the function _rebalanceLiquidityto return early, because setCurveVaultaddress params cant be set to address zero.

  3. unused asset token inside RToken cannot generate yield, making the protocol and user lose potential yield generated from the curve vault.

Tools Used

manual review

Recommendations

set the asset approval for LendingPool to spent token held by RToken address, then apply the following diff so before the deposit happen the asset token is sent into the lending pool first:

diff --git a/contracts/core/pools/LendingPool/LendingPool.sol b/contracts/core/pools/LendingPool/LendingPool.sol
index b02fc97..829c727 100644
--- a/contracts/core/pools/LendingPool/LendingPool.sol
+++ b/contracts/core/pools/LendingPool/LendingPool.sol
@@ -797,6 +811,7 @@ contract LendingPool is ILendingPool, Ownable, ReentrancyGuard, ERC721Holder, Pa
* @param amount The amount to deposit
*/
function _depositIntoVault(uint256 amount) internal {
+ IERC20(reserve.reserveAssetAddress).safeTransferFrom(reserve.reserveRTokenAddress, address(this), amount);
IERC20(reserve.reserveAssetAddress).approve(address(curveVault), amount);
curveVault.deposit(amount, address(this));
totalVaultDeposits += amount;
Updates

Lead Judging Commences

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

LendingPool::_depositIntoVault and _withdrawFromVault don't transfer tokens between RToken and LendingPool, breaking Curve vault interactions

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

LendingPool::_depositIntoVault and _withdrawFromVault don't transfer tokens between RToken and LendingPool, breaking Curve vault interactions

Support

FAQs

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