it("allows new lockers to claim disproportionate rewards", async function () {
const [, , , , , , , user3, user4] = await ethers.getSigners();
await raacToken.mint(user3.address, INITIAL_MINT);
await raacToken.mint(user4.address, INITIAL_MINT);
await raacToken
.connect(user3)
.approve(feeCollector.target, ethers.MaxUint256);
await raacToken
.connect(user4)
.approve(feeCollector.target, ethers.MaxUint256);
await raacToken.connect(user3).approve(veRAACToken.target, ethers.MaxUint256);
await raacToken.connect(user4).approve(veRAACToken.target, ethers.MaxUint256);
await feeCollector.connect(owner).distributeCollectedFees();
await veRAACToken.connect(user3).lock(ethers.parseEther("1000"), ONE_YEAR);
await time.increase(ONE_YEAR / 2);
await veRAACToken.connect(user4).lock(ethers.parseEther("1000"), ONE_YEAR);
let user3Reward, user4Reward;
await expect(feeCollector.connect(user4).claimRewards(user4.address))
.to.emit(feeCollector, "RewardClaimed")
.withArgs(user4.address, (value) => {
user4Reward = value;
return true;
});
await expect(feeCollector.connect(user3).claimRewards(user3.address))
.to.emit(feeCollector, "RewardClaimed")
.withArgs(user3.address, (value) => {
user3Reward = value;
return true;
});
console.log("user3Reward: ", user3Reward);
console.log("user4Reward: ", user4Reward);
expect(user4Reward).to.be.gt(user3Reward);
});
High Severity - Directly impacts reward distribution fairness, allowing strategic actors to maximize returns through timing attacks while penalizing long-term participants.
contracts/core/collectors/FeeCollector.sol
function _calculatePendingRewards(address user) internal view returns (uint256) {
+ uint256 duration = block.timestamp - lastClaimTime[user];
+ uint256 avgPower = veRAACToken.getAveragePower(user, lastClaimTime[user], duration);
- uint256 userShare = userVotingPower * 1e18 / totalVotingPower;
+ uint256 userShare = avgPower * 1e18 / veRAACToken.getAverageTotalPower(duration);