Skip to content

Commit

Permalink
Merge pull request #185 from futureversecom/SM-386
Browse files Browse the repository at this point in the history
SM-386
  • Loading branch information
Nick95550 authored Aug 6, 2024
2 parents 590cc3e + b7c5fad commit c6b1957
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 7 deletions.
14 changes: 14 additions & 0 deletions contracts/payments/IRewardsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ interface IRewardsManager {
uint256[] calldata cycles
) external view returns (uint256[] memory);

function getClaim(address node, address user, uint256 cycle) external view returns (uint256);

function getUnclaimedReward(
address node,
address user,
uint256 cycle
) external view returns (uint256);

function getUnclaimedRewards(
address node,
address user,
uint256[] calldata cycles
) external view returns (uint256[] memory);

function getUnclaimedNodeCommission(address node) external view returns (uint256);

function incrementRewardPool(address node, uint256 amount) external;
Expand Down
30 changes: 26 additions & 4 deletions contracts/payments/RewardsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,28 @@ contract RewardsManager is IRewardsManager, Initializable, AccessControl {
return rewardPools[node][cycle];
}

function getUnclaimedReward(address node, address user, uint256 cycle) external view returns (uint256) {
return _getUnclaimedReward(node, user, cycle);
}

function getUnclaimedRewards(address node, address user, uint256[] calldata cycles) external view returns (uint256[] memory) {
uint256 [] memory unclaimedRewards = new uint256[](cycles.length);

for (uint256 i = 0; i < cycles.length; i++) {
unclaimedRewards[i] = _getUnclaimedReward(node, user, cycles[i]);
}

return unclaimedRewards;
}

function _getUnclaimedReward(address node, address user, uint256 cycle) internal view returns (uint256) {
if (claims[node][user][cycle]) {
return 0;
}

return _getClaim(node, user, cycle);
}

function getClaim(address node, address user, uint256 cycle) external view returns (uint256) {
return _getClaim(node, user, cycle);
}
Expand All @@ -157,10 +179,6 @@ contract RewardsManager is IRewardsManager, Initializable, AccessControl {
uint256 claimAmount = (rewardPools[node][cycle] * userRewardCycleStake) /
nodeRewardCycleStake;

if (user == node) {
claimAmount += unclaimedNodeCommission[node];
}

return claimAmount;
}

Expand Down Expand Up @@ -201,6 +219,10 @@ contract RewardsManager is IRewardsManager, Initializable, AccessControl {

uint256 claimAmount = _getClaim(node, msg.sender, cycle);

if (msg.sender == node) {
claimAmount += unclaimedNodeCommission[node];
}

if (claimAmount == 0) {
revert CannotClaimZeroAmount();
}
Expand Down
49 changes: 46 additions & 3 deletions test/paymets/rewardsManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ describe('Rewards Manager', () => {
'function getUnclaimedNodeCommission(address node) external view returns (uint256)',
'function incrementRewardPool(address node, uint256 amount) external',
'function claim(address node, uint256 cycle) external',
'function getClaim(address node, address user, uint256 cycle) external view returns (uint256)',
'function getUnclaimedReward(address node, address user, uint256 cycle) external view returns (uint256)',
'function getUnclaimedRewards(address node, address user, uint256[] cycles) external view returns (uint256[])',
];

const interfaceId = getInterfaceId(abi);
Expand Down Expand Up @@ -291,6 +294,14 @@ describe('Rewards Manager', () => {
await setTimeSinceStart(1000);

await testClaim(node1.getAddress(), user, 1, rewardAmount);

const unclaimedReward = await rewardsManager.getUnclaimedReward(
node1.getAddress(),
user.address,
1,
);

expect(unclaimedReward).to.equal(0);
});

it('can claim reward over multiple cycles', async () => {
Expand All @@ -308,6 +319,16 @@ describe('Rewards Manager', () => {
await setTimeSinceStart(cycle * 1000);
}

const unclaimedRewards = await rewardsManager.getUnclaimedRewards(
node1.getAddress(),
user.getAddress(),
cycles,
);

for (const [i, r] of unclaimedRewards.entries()) {
expect(r).to.be.eq(BigInt(i + 1) * rewardAmount);
}

for (const cycle of cycles) {
await testClaim(
node1.getAddress(),
Expand Down Expand Up @@ -363,7 +384,15 @@ describe('Rewards Manager', () => {

await setTimeSinceStart(1000);

await testClaim(node1.getAddress(), node1, 1, rewardAmount / 2n);
const balance = await contracts.syloToken.balanceOf(node1.getAddress());

await rewardsManager.connect(node1).claim(node1.getAddress(), 1);

const balanceAfter = await contracts.syloToken.balanceOf(
node1.getAddress(),
);

expect(balanceAfter).to.equal(balance + rewardAmount / 2n);
});

it('can claim as node and stakee', async () => {
Expand All @@ -381,7 +410,15 @@ describe('Rewards Manager', () => {

await setTimeSinceStart(1000);

await testClaim(node1.getAddress(), node1, 1, rewardAmount);
const balance = await contracts.syloToken.balanceOf(node1.getAddress());

await rewardsManager.connect(node1).claim(node1.getAddress(), 1);

const balanceAfter = await contracts.syloToken.balanceOf(
node1.getAddress(),
);

expect(balanceAfter).to.equal(balance + rewardAmount);
});

it('claim is distributed between nodes and stakers', async () => {
Expand Down Expand Up @@ -501,9 +538,15 @@ describe('Rewards Manager', () => {
const balance = await contracts.syloToken.balanceOf(user);

const claim = await rewardsManager.getClaim(node, user.getAddress(), cycle);

expect(claim).to.equal(expectedIncrease);

const unclaimed = await rewardsManager.getUnclaimedReward(
node,
user.getAddress(),
cycle,
);
expect(unclaimed).to.equal(expectedIncrease);

await rewardsManager.connect(user).claim(node, cycle);

const balanceAfter = await contracts.syloToken.balanceOf(user);
Expand Down

0 comments on commit c6b1957

Please sign in to comment.