Omniscia Kanpeki Finance Audit
RewardManager Manual Review Findings
RewardManager Manual Review Findings
RMR-01M: Ineffectual Cap Increase
Type | Severity | Location |
---|---|---|
Logical Fault | Medium | RewardManager.sol:L197, L265, L286, L291 |
Description:
The _calcReward
incentivizes discounted borrowers to make large debts by increasing the total reward they are able to receive, however, the double reward cap is only utilized for the assignment of the reward the user is meant to receive and is not actually utilized for the reward payout meaning that a user will never receive the fully eligible payout they initially calculated they will receive.
Example:
contracts/managers/RewardManager.sol
245/**246 * calculates the KAE reward for a Debt247 *248 * reward calculation is basically: Math.min((multiplier * debtInUSD), reward cap)249 * -> multiplier = (interestRate - 1)%250 * -> reward cap = currentRewardCap251 *252 * if (isBorrowerDiscounted && debtInUSD > $50K)253 * -> rewardCap = currentRewardCap * 2254 *255 * @param interestRate Debt's interest rate in basis point but must be converted to 1e18256 */257function _calcReward (uint256 debtInUSD, uint256 interestRate, bool isDiscountedBorrower) internal view returns (uint256)258{259 uint256 reward = _calcScaledPercentOf(debtInUSD, _calcPriceAdjustedMultiplier(interestRate - 100));260
261 // 50_000e18 = $50K in DAI262 if (isDiscountedBorrower && debtInUSD > 50_000e18)263 {264 // 50 = 0.5% in basis point; first converts basis point to 1e18; 0.5% of Debt265 return Math.min(reward + _calcScaledPercentOf(debtInUSD, _calcPriceAdjustedMultiplier(50)), _config.currentRewardCap * 2);266 }267 else268 {269 return Math.min(reward, _config.currentRewardCap);270 }271}272
273// front-end274function calcReward (address debtToken, uint256 debt, uint256 interestRate, bool isDiscountedBorrower) external view returns (uint256)275{276 return _calcReward(IOracle(_ADDRESSES.oracle()).convertToUSD(debtToken, debt), interestRate, isDiscountedBorrower);277}278
279// @param interestRate Debt interest in basis point but must be converted to 1e18280function registerDebt (bytes32 debtID, uint256 debtInUSD, uint256 interestRate, bool isDiscountedBorrower) external override281{282 require(hasRole(REWARDER_ROLE, msg.sender), "!rewarder");283 require(_reward[debtID] == 0, "reg'd");284
285
286 uint256 reward = _calcReward(debtInUSD, interestRate, isDiscountedBorrower);287
288 require(reward > 0 && reward < type(uint80).max, "bad reward");289
290
291 _reward[debtID] = uint80(reward);292}
Recommendation:
We strongly recommend rewards that contain a double cap multiplier to be properly tracked and rewarded with the new cap in mind to avoid discrepancies between what the users perceive on the application and what they actually receive.
Alleviation:
The codebase was significantly revamped no longer rendering this exhibit relevant.