function closePot() external onlyOwner {
if (block.timestamp - i_deployedAt < 90 days) revert Pot__StillOpenForClaim();
if (remainingRewards > 0) {
uint256 managerCut = remainingRewards / managerCutPercent;
i_token.transfer(msg.sender, managerCut);
uint256 claimantCut = (remainingRewards - managerCut) / i_players.length;
for (uint256 i = 0; i < claimants.length; i++) {
_transferReward(claimants[i], claimantCut);
}
}
}
pragma solidity ^0.8.20;
import {Test} from "lib/forge-std/src/Test.sol";
import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {Pot} from "../../src/Pot.sol";
import {ERC20Mock} from "../../test/ERC20Mock.sol";
contract F001WrongDenominatorDistribution is Test {
address private player1 = makeAddr("player1");
address private player2 = makeAddr("player2");
function test_F001_underpaysClaimants_and_locksFunds() public {
address[] memory players = new address[](2);
players[0] = player1;
players[1] = player2;
uint256[] memory rewards = new uint256[](2);
rewards[0] = 500;
rewards[1] = 500;
uint256 totalRewards = 1000;
ERC20Mock token = new ERC20Mock("TKN", "TKN", address(this), 0);
Pot pot = new Pot(players, rewards, IERC20(address(token)), totalRewards);
token.mint(address(this), totalRewards);
token.transfer(address(pot), totalRewards);
vm.prank(player1);
pot.claimCut();
assertEq(token.balanceOf(player1), rewards[0]);
vm.warp(block.timestamp + 91 days);
pot.closePot();
uint256 remainingRewards = totalRewards - rewards[0];
uint256 managerCut = remainingRewards / 10;
uint256 expectedExtraIfDistributedToClaimants = remainingRewards - managerCut;
uint256 actualExtraPaid = token.balanceOf(player1) - rewards[0];
assertEq(actualExtraPaid, 225);
assertEq(expectedExtraIfDistributedToClaimants, 450);
assertEq(token.balanceOf(address(pot)), expectedExtraIfDistributedToClaimants - actualExtraPaid);
vm.prank(player2);
vm.expectRevert();
pot.claimCut();
}
}
- uint256 claimantCut = (remainingRewards - managerCut) / i_players.length;
- for (uint256 i = 0; i < claimants.length; i++) {
- _transferReward(claimants[i], claimantCut);
- }
+ uint256 distributable = remainingRewards - managerCut;
+ if (claimants.length == 0) {
+ i_token.transfer(msg.sender, distributable);
+ } else {
+ uint256 claimantCut = distributable / claimants.length;
+ for (uint256 i = 0; i < claimants.length; i++) {
+ _transferReward(claimants[i], claimantCut);
+ }
+ uint256 remainder = distributable - (claimantCut * claimants.length);
+ if (remainder > 0) i_token.transfer(msg.sender, remainder);
+ }
+ remainingRewards = 0;