https://github.com/kinetic-market/public-money-market-contracts
Attackers can exploit the precision loss in reward calculations by frequently calling the updateRewardSupplyIndex
and updateRewardBorrowIndex
functions, causing the rewards to be effectively zero. In particular, when attackers repeatedly call these functions, the downwards rounding may result in no increase in the rewardSupplyState.index
or rewardBorrowState.index
. This issue is more prominent in chains with low gas costs and fast block times.
Here’s the relevant part of the code:
function updateRewardSupplyIndex(uint8 rewardType, address cToken) internal {
require(rewardType < rewardTokens.length, "IR");
RewardMarketState storage supplyState = rewardSupplyState[rewardType][cToken];
uint supplySpeed = supplyRewardSpeeds[rewardType][cToken];
uint blockTimestamp = getBlockTimestamp();
uint deltaTimestamps = sub_(blockTimestamp, uint(supplyState.timestamp));
if (deltaTimestamps > 0 && supplySpeed > 0) {
uint supplyTokens = CToken(cToken).totalSupply();
uint rewardsAccrued = mul_(deltaTimestamps, supplySpeed);
Double memory ratio = supplyTokens > 0 ? fraction(rewardsAccrued, supplyTokens) : Double({mantissa: 0});
Double memory index = add_(Double({mantissa: supplyState.index}), ratio);
rewardSupplyState[rewardType][cToken] = RewardMarketState({
index: safe224(index.mantissa, "224"),
timestamp: safe32(blockTimestamp, "32")
});
} else if (deltaTimestamps > 0) {
supplyState.timestamp = safe32(blockTimestamp, "32");
}
}
In this function, the reward index might not increase as expected because of rounding, causing a situation where no rewards are distributed. The problem is exacerbated in environments where transactions are cheap, and blocks are mined quickly, allowing an attacker to repeatedly call the function and manipulate the rewards.
Implement additional precision or checks to ensure that the reward index is updated correctly even when small values are involved.
https://github.com/kinetic-market/public-money-market-contracts/blob/d46f5223344ff6502349549ad858588e496483df/contracts/Comptroller.sol#L932-L950
https://github.com/kinetic-market/public-money-market-contracts/blob/d46f5223344ff6502349549ad858588e496483df/contracts/Comptroller.sol#L957-L975