Summary
After perform the rebalance of the Lending Pool liquidity, the LiquidityRebalanced event is emitted. The event is supposed to include the current amount of liquidity in the buffer, however, this value is not updated after the rebalance, resulting in a wrong value emitted.
Vulnerability Details
The LiquidityRebalanced event definition is the following:
> ILendingPool.sol
* @notice Emitted when liquidity is rebalanced
* @param bufferAmount The amount of liquidity in the buffer
* @param vaultAmount The amount of liquidity in the Curve vault
*/
event LiquidityRebalanced(uint256 bufferAmount, uint256 vaultAmount);
However, when emitted after the liquidity rebalancing, only the second parameter has the updated value, while the amount of liquidity in the buffer still reflects an old value.
> LendingPool.sol
function _rebalanceLiquidity() internal {
if (address(curveVault) == address(0)) {
return;
}
uint256 totalDeposits = reserve.totalLiquidity;
uint256 desiredBuffer = totalDeposits.percentMul(liquidityBufferRatio);
@> uint256 currentBuffer = IERC20(reserve.reserveAssetAddress).balanceOf(reserve.reserveRTokenAddress);
if (currentBuffer > desiredBuffer) {
uint256 excess = currentBuffer - desiredBuffer;
_depositIntoVault(excess);
} else if (currentBuffer < desiredBuffer) {
uint256 shortage = desiredBuffer - currentBuffer;
_withdrawFromVault(shortage);
}
@> emit LiquidityRebalanced(currentBuffer, totalVaultDeposits);
}
Impact
Impact: Low
Multiple associated services may display incorrect values, potentially misleading protocol administrators and consumers.
Likelihood: Medium
Tools Used
Manual Review
Recommendations
This issue is present even if liquidity rebalancing process is not correctly performed. It is recommended to update the current amount of liquidity in the buffer to reflect the most recent value in the LiquidityRebalanced event.
> LendingPool.sol
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);
}
+ currentBuffer = IERC20(reserve.reserveAssetAddress).balanceOf(reserve.reserveRTokenAddress);
emit LiquidityRebalanced(currentBuffer, totalVaultDeposits);
}