The issue is that, after the first claim, users will no longer be able to claim any future reward distributed since userRewards[user]
will be greater than the computed share
which will always return 0
pragma solidity ^0.8.28;
import "forge-std/Test.sol";
import "forge-std/console.sol";
import "contracts/core/tokens/RAACToken.sol";
import "contracts/core/tokens/veRAACToken.sol";
import "contracts/core/collectors/FeeCollector.sol";
contract FeeCollectorTest is Test {
RAACToken public raacToken;
veRAACToken public veRToken;
FeeCollector public feeCollector;
address public owner;
address public user1;
address public user2;
address public treasury;
address public newTreasury;
address public repairFund;
address public emergencyAdmin;
uint256 constant BASIS_POINTS = 10000;
uint256 constant WEEK = 7 * 24 * 3600;
uint256 constant ONE_YEAR = 365 * 24 * 3600;
uint256 constant INITIAL_MINT = 10000 ether;
uint256 constant SWAP_TAX_RATE = 100;
uint256 constant BURN_TAX_RATE = 50;
struct FeeType {
uint256 veRAACShare;
uint256 burnShare;
uint256 repairShare;
uint256 treasuryShare;
}
FeeType public defaultFeeType;
function setUp() public {
owner = makeAddr("owner");
user1 = makeAddr("alice");
user2 = makeAddr("bob");
treasury = makeAddr("treasury");
newTreasury = makeAddr("newTreasury");
repairFund = makeAddr("repairFund");
emergencyAdmin = makeAddr("emergencyAdmin");
vm.startPrank(owner);
raacToken = new RAACToken(owner, SWAP_TAX_RATE, BURN_TAX_RATE);
veRToken = new veRAACToken(address(raacToken));
feeCollector = new FeeCollector(
address(raacToken),
address(veRToken),
treasury,
repairFund,
owner
);
raacToken.setFeeCollector(address(feeCollector));
raacToken.manageWhitelist(address(feeCollector), true);
raacToken.manageWhitelist(address(veRToken), true);
raacToken.setMinter(owner);
veRToken.setMinter(owner);
feeCollector.grantRole(feeCollector.FEE_MANAGER_ROLE(), owner);
feeCollector.grantRole(feeCollector.EMERGENCY_ROLE(), emergencyAdmin);
feeCollector.grantRole(feeCollector.DISTRIBUTOR_ROLE(), owner);
vm.stopPrank();
}
function test_POC() public {
uint256 protocolFeeGross = 50 ;
uint256 lendingFeeGross = 30 ;
uint256 swapTaxGross = 20 ;
vm.startPrank(owner);
raacToken.mint(address(user1), 100 );
raacToken.mint(address(user2), 100 );
raacToken.mint(owner, 200);
raacToken.approve(address(feeCollector), 200 );
feeCollector.collectFee(protocolFeeGross, 0);
feeCollector.collectFee(lendingFeeGross, 1);
feeCollector.collectFee(swapTaxGross, 6);
vm.stopPrank();
vm.startPrank(user1);
raacToken.approve(address(veRToken), 100);
veRToken.lock(100, ONE_YEAR);
vm.stopPrank();
vm.startPrank(user2);
raacToken.approve(address(veRToken), 100);
veRToken.lock(100, ONE_YEAR);
vm.stopPrank();
vm.prank(owner);
feeCollector.distributeCollectedFees();
vm.prank(user1);
assertEq(feeCollector.claimRewards(user1), 31);
vm.warp(block.timestamp + WEEK);
vm.startPrank(owner);
raacToken.mint(owner, 200);
raacToken.approve(address(feeCollector), 200 );
feeCollector.collectFee(50, 0);
feeCollector.distributeCollectedFees();
vm.stopPrank();
vm.warp(block.timestamp + WEEK);
vm.prank(user1);
vm.expectRevert(abi.encodeWithSignature("InsufficientBalance()"));
feeCollector.claimRewards(user1);
vm.prank(user2);
assertEq(feeCollector.claimRewards(user2), 51);
}
}
New rewards distributed after their first claim are unclaimable leading to loss of reward for token holders
Modify the function to ensure that users can claim their reward when distributions are made