The RAAC Minter contract incorrectly calculates the utilization rate, leading to unintended emission rate adjustments. The function getUtilizationRate() retrieves the total borrowed value from lendingPool.getNormalizedDebt(), which returns the usage index instead of the total normalized debt supply. This results in an incorrect utilization rate calculation, causing emission rates to always increase after the first deposit in StabilityPool::deposit.
Vulnerability Details
The vulnerability exists in the following function inside the RAAC Minter contract:
The function lendingPool.getNormalizedDebt() does not return the total normalized debt but rather the usageIndex, which is not useful for utilization calculations.The correct value for totalBorrowed should be the total normalized supply of the debt token, which represents the actual outstanding debt in the system.Since the incorrect totalBorrowed value is used, the utilization rate calculation is fundamentally flawed. As a result, getUtilizationRate() returns a nonzero utilization rate even when there is no actual borrowed amount. Since the usageIndex is in ray precision (1e27) and total deposits have 18 decimal precision, the calculation will be flawed. As a result, the emission rate will only ever decrease once which will be the first time a user deposits using StabilityPool::deposit. Every deposit/borrow after that will produce an increase in the emission rate which is not intended behaviour.
This test was run in protocols-test.js in the "StabilityPool" describe block
Inaccurate Emission Adjustments: Since the emission rate is dynamically adjusted based on utilization, an incorrect calculation means the protocol could emit too many or too few rewards, affecting the incentive structure.
Protocol Inefficiency: A nonzero utilization rate when no debt exists means emissions could be kept higher than necessary, leading to excessive inflation of RAAC rewards.
Misleading Data: Users relying on the utilization rate for decision-making (e.g., whether to deposit or borrow) could be misled into making incorrect financial decisions.
Manual Review, Hardhat
To fix this issue, totalBorrowed should be set to the actual total supply of the debt token rather than relying on lendingPool.getNormalizedDebt(). Modify getUtilizationRate() as follows:
This ensures:
The correct total borrowed value is used.
The utilization rate reflects actual lending activity.
Emissions are adjusted appropriately based on real system usage.
By implementing this fix, the protocol will correctly adjust emission rates based on actual utilization, preventing unintended reward distortions and ensuring better efficiency.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.