@@ -96,6 +96,9 @@ contract TruthBountyWeighted is AccessControl, ReentrancyGuard, Pausable, Govern
9696 uint256 totalSlashed;
9797 uint256 winnerWeightedStake; // Changed to weighted (NEW)
9898 uint256 loserWeightedStake; // Changed to weighted (NEW)
99+ uint256 winnerCount; // Number of winning voters eligible for rewards
100+ uint256 winnersClaimed; // Number of winning voters that claimed rewards
101+ uint256 rewardsClaimed; // Total rewards already distributed
99102 }
100103
101104 struct VerifierStake {
@@ -340,9 +343,17 @@ contract TruthBountyWeighted is AccessControl, ReentrancyGuard, Pausable, Govern
340343 bool isWinner = (vote.support == settlement.passed);
341344 require (isWinner, "Not a winner " );
342345
343- // Calculate proportional reward based on EFFECTIVE stake
346+ // Calculate proportional reward based on EFFECTIVE stake. Integer division can
347+ // leave a remainder, so assign any undistributed dust to the final winning
348+ // claimant to ensure totalRewards is fully paid out.
344349 uint256 reward = (vote.effectiveStake * settlement.totalRewards) / settlement.winnerWeightedStake;
345350
351+ settlement.winnersClaimed += 1 ;
352+ if (settlement.winnersClaimed == settlement.winnerCount) {
353+ reward = settlement.totalRewards - settlement.rewardsClaimed;
354+ }
355+ settlement.rewardsClaimed += reward;
356+
346357 // Mark as claimed
347358 vote.rewardClaimed = true ;
348359
@@ -518,10 +529,27 @@ contract TruthBountyWeighted is AccessControl, ReentrancyGuard, Pausable, Govern
518529 totalRewards: rewardAmount,
519530 totalSlashed: slashedAmount,
520531 winnerWeightedStake: winnerWeightedStake,
521- loserWeightedStake: loserWeightedStake
532+ loserWeightedStake: loserWeightedStake,
533+ winnerCount: _countWinners (claimId, passed),
534+ winnersClaimed: 0 ,
535+ rewardsClaimed: 0
522536 });
523537 }
524538
539+ /**
540+ * @notice Count voters on the winning side for remainder-safe reward distribution
541+ */
542+ function _countWinners (uint256 claimId , bool passed ) internal view returns (uint256 count ) {
543+ address [] storage voters = claimVoters[claimId];
544+
545+ for (uint256 i = 0 ; i < voters.length ; i++ ) {
546+ Vote storage vote = votes[claimId][voters[i]];
547+ if (vote.support == passed) {
548+ count += 1 ;
549+ }
550+ }
551+ }
552+
525553 /**
526554 * @notice Assign per-vote slash amounts to each loser
527555 * @dev Iterates through all voters and stores slash amount in Vote struct for losers
0 commit comments