50195 sc low unfair yield distribution due to remainder allocation to last holder
Description
Brief/Intro
Vulnerability Details
function distributeYield(uint256 amount) external onlyRole(YIELD_DISTRIBUTOR_ROLE) nonReentrant {
// ... validation logic ...
uint256 distributedSum = 0;
uint256 lastProcessedIndex = holderCount > 0 ? holderCount - 1 : 0;
// Process all holders except the last one
for (uint256 i = 0; i < lastProcessedIndex; i++) {
address holder = $.holders.at(i);
if (!_isYieldAllowed(holder)) continue;
uint256 holderBalance = balanceOf(holder);
if (holderBalance > 0) {
uint256 share = (amount * holderBalance) / effectiveTotalSupply; // ❌ Rounds down
if (share > 0) {
yToken.safeTransfer(holder, share);
distributedSum += share; // ❌ Accumulates rounding losses
}
}
}
// ❌ CRITICAL FLAW: Last holder gets remainder instead of proportional share
if (holderCount > 0) {
address lastHolder = $.holders.at(lastProcessedIndex);
if (_isYieldAllowed(lastHolder)) {
uint256 lastShare = amount - distributedSum; // ❌ Gets ALL remainder
if (lastShare > 0) {
yToken.safeTransfer(lastHolder, lastShare);
}
}
}
}Impact Details
References
Proof of Concept
Previous51159 sc insight high gas iterative date calculations in datetime solNext50887 sc insight arcotokenpurchase purchasemade event mislabels payment amount as pricepaid instead of unit price
Was this helpful?