@nodeset/contracts
Version:
Protocol for accessing NodeSet's Constellation Ethereum staking network
723 lines (602 loc) • 32.9 kB
JavaScript
import { getCurrentTime, increaseTime } from '../_utils/evm'
import { printTitle } from '../_utils/formatting';
import { shouldRevert } from '../_utils/testing';
import { submitPrices } from '../_helpers/network';
import {
registerNode,
setNodeTrusted,
setNodeWithdrawalAddress,
nodeStakeRPL,
getNodeEffectiveRPLStake,
} from '../_helpers/node'
import {
RocketDAONodeTrustedSettingsMinipool,
RocketDAOProtocolSettingsNode,
RocketMerkleDistributorMainnet,
RocketSmoothingPool,
RocketStorage,
} from '../_utils/artifacts';
import { setDAOProtocolBootstrapSetting, setRewardsClaimIntervalTime, setRPLInflationStartTime } from '../dao/scenario-dao-protocol-bootstrap'
import { mintRPL } from '../_helpers/tokens';
import { rewardsClaimersPercTotalGet } from './scenario-rewards-claim';
import { setDAONetworkBootstrapRewardsClaimer, setRPLInflationIntervalRate } from '../dao/scenario-dao-protocol-bootstrap';
// Contracts
import { RocketRewardsPool } from '../_utils/artifacts';
import { createMinipool, stakeMinipool } from '../_helpers/minipool'
import { userDeposit } from '../_helpers/deposit'
import { setDAONodeTrustedBootstrapSetting } from '../dao/scenario-dao-node-trusted-bootstrap';
import { executeRewards, submitRewards } from './scenario-submit-rewards';
import { claimRewards } from './scenario-claim-rewards';
import { claimAndStakeRewards } from './scenario-claim-and-stake-rewards';
import { parseRewardsMap } from '../_utils/merkle-tree';
import { daoNodeTrustedExecute, daoNodeTrustedPropose, daoNodeTrustedVote } from '../dao/scenario-dao-node-trusted';
import { getDAOProposalStartTime } from '../dao/scenario-dao-proposal';
import { assertBN } from '../_helpers/bn';
export default function() {
contract('RocketRewardsPool', async (accounts) => {
// One day in seconds
const ONE_DAY = 24 * 60 * 60;
// Accounts
const [
owner,
userOne,
registeredNode1,
registeredNode2,
registeredNodeTrusted1,
registeredNodeTrusted2,
unregisteredNodeTrusted1,
unregisteredNodeTrusted2,
node1WithdrawalAddress,
random
] = accounts;
// The testing config
const claimIntervalTime = ONE_DAY * 28;
let scrubPeriod = (60 * 60 * 24); // 24 hours
// Set some RPL inflation scenes
let rplInflationSetup = async function() {
// Current time
let currentTime = await getCurrentTime(web3);
// Starting block for when inflation will begin
let timeStart = currentTime + ONE_DAY;
// Yearly inflation target
let yearlyInflationTarget = 0.05;
// Set the daily inflation start time
await setRPLInflationStartTime(timeStart, { from: owner });
// Set the daily inflation rate
await setRPLInflationIntervalRate(yearlyInflationTarget, { from: owner });
// claimIntervalTime must be greater than rewardIntervalTime for tests to properly function
assert.isAbove(claimIntervalTime, ONE_DAY, 'Tests will not function correctly unless claimIntervalTime is greater than inflation period (1 day)')
// Return the starting time for inflation when it will be available
return timeStart + ONE_DAY;
}
// Set a rewards claiming contract
let rewardsContractSetup = async function(_claimContract, _claimAmountPerc) {
// Set the amount this contract can claim
await setDAONetworkBootstrapRewardsClaimer(_claimContract, _claimAmountPerc, { from: owner });
// Set the claim interval blocks
await setRewardsClaimIntervalTime(claimIntervalTime, { from: owner });
}
async function kickTrustedNode(nodeAddress, voters) {
// Encode the calldata for the proposal
let proposalCalldata = web3.eth.abi.encodeFunctionCall(
{name: 'proposalKick', type: 'function', inputs: [{type: 'address', name: '_nodeAddress'}, {type: 'uint256', name: '_rplFine'}]},
[nodeAddress, '0']
);
// Add the proposal
let proposalID = await daoNodeTrustedPropose(`Kick ${nodeAddress}`, proposalCalldata, {
from: registeredNodeTrusted1
});
// Current time
let timeCurrent = await getCurrentTime(web3);
// Now increase time until the proposal is 'active' and can be voted on
await increaseTime(web3, (await getDAOProposalStartTime(proposalID)-timeCurrent)+2);
// Now lets vote
for (const voter of voters) {
await daoNodeTrustedVote(proposalID, true, { from: voter });
}
// Proposal has passed, lets execute it now
await daoNodeTrustedExecute(proposalID, { from: registeredNode1 });
}
// Setup
before(async () => {
// Disable RocketClaimNode claims contract
await setDAONetworkBootstrapRewardsClaimer('rocketClaimNode', '0'.ether, {from: owner});
// Set settings
await setDAONodeTrustedBootstrapSetting(RocketDAONodeTrustedSettingsMinipool, 'minipool.scrub.period', scrubPeriod, {from: owner});
// Register nodes
await registerNode({from: registeredNode1});
await registerNode({from: registeredNode2});
await registerNode({from: registeredNodeTrusted1});
await registerNode({from: registeredNodeTrusted2});
await registerNode({from: unregisteredNodeTrusted1});
await registerNode({from: unregisteredNodeTrusted2});
// Set node 1 withdrawal address
await setNodeWithdrawalAddress(registeredNode1, node1WithdrawalAddress, {from: registeredNode1});
// Set nodes as trusted
await setNodeTrusted(registeredNodeTrusted1, 'saas_1', 'node@home.com', owner);
await setNodeTrusted(registeredNodeTrusted2, 'saas_2', 'node@home.com', owner);
// Set max per-minipool stake to 100% and RPL price to 1 ether
const block = await web3.eth.getBlockNumber();
await setDAOProtocolBootstrapSetting(RocketDAOProtocolSettingsNode, 'node.per.minipool.stake.maximum', '1'.ether, {from: owner});
await submitPrices(block, '1'.ether, {from: registeredNodeTrusted1});
await submitPrices(block, '1'.ether, {from: registeredNodeTrusted2});
// Mint and stake RPL
await mintRPL(owner, registeredNode1, '32'.ether);
await mintRPL(owner, registeredNode2, '32'.ether);
await nodeStakeRPL('32'.ether, {from: registeredNode1});
await nodeStakeRPL('32'.ether, {from: registeredNode2});
// User deposits
await userDeposit({from: userOne, value: '48'.ether});
// Create minipools
let minipool1 = await createMinipool({from: registeredNode1, value: '16'.ether});
let minipool2 = await createMinipool({from: registeredNode2, value: '16'.ether});
let minipool3 = await createMinipool({from: registeredNode2, value: '16'.ether});
// Wait required scrub period
await increaseTime(web3, scrubPeriod + 1);
// Stake minipools
await stakeMinipool(minipool1, {from: registeredNode1});
await stakeMinipool(minipool2, {from: registeredNode2});
await stakeMinipool(minipool3, {from: registeredNode2});
// Check node effective stakes
let node1EffectiveStake = await getNodeEffectiveRPLStake(registeredNode1);
let node2EffectiveStake = await getNodeEffectiveRPLStake(registeredNode2);
assertBN.equal(node1EffectiveStake, '16'.ether, 'Incorrect node 1 effective stake');
assertBN.equal(node2EffectiveStake, '32'.ether, 'Incorrect node 2 effective stake');
});
/*** Setting Claimers *************************/
it(printTitle('userOne', 'fails to set interval blocks for rewards claim period'), async () => {
// Set the rewards claims interval in seconds
await shouldRevert(setRewardsClaimIntervalTime(100, {
from: userOne,
}), 'Non owner set interval blocks for rewards claim period');
});
it(printTitle('guardian', 'succeeds setting interval blocks for rewards claim period'), async () => {
// Set the rewards claims interval in blocks
await setRewardsClaimIntervalTime(100, {
from: owner,
});
});
it(printTitle('userOne', 'fails to set contract claimer percentage for rewards'), async () => {
// Set the amount this contract can claim
await shouldRevert(setDAONetworkBootstrapRewardsClaimer('myHackerContract', '0.1'.ether, {
from: userOne,
}), 'Non owner set contract claimer percentage for rewards');
});
it(printTitle('guardian', 'set contract claimer percentage for rewards, then update it'), async () => {
// Set the amount this contract can claim
await setDAONetworkBootstrapRewardsClaimer('rocketClaimDAO', '0.0001'.ether, {
from: owner,
});
// Set the amount this contract can claim, then update it
await setDAONetworkBootstrapRewardsClaimer('rocketClaimNode', '0.01'.ether, {
from: owner,
});
// Update now
await setDAONetworkBootstrapRewardsClaimer('rocketClaimNode', '0.02'.ether, {
from: owner,
});
});
it(printTitle('guardian', 'set contract claimer percentage for rewards, then update it to zero'), async () => {
// Get the total current claims amounts
let totalClaimersPerc = await rewardsClaimersPercTotalGet();
// Set the amount this contract can claim, then update it
await setDAONetworkBootstrapRewardsClaimer('rocketClaimNode', '0.01'.ether, {
from: owner,
});
// Update now
await setDAONetworkBootstrapRewardsClaimer('rocketClaimNode', '0'.ether, {
from: owner,
}, totalClaimersPerc);
});
it(printTitle('guardian', 'set contract claimers total percentage to 100%'), async () => {
// Get the total current claims amounts
let totalClaimersPerc = await rewardsClaimersPercTotalGet();
// Get the total % needed to make 100%
let claimAmount = '1'.ether.sub(totalClaimersPerc);
// Set the amount this contract can claim and expect total claimers amount to equal 1 ether (100%)
await setDAONetworkBootstrapRewardsClaimer('rocketClaimNode', claimAmount, {
from: owner,
}, '1'.ether);
});
it(printTitle('guardian', 'fail to set contract claimers total percentage over 100%'), async () => {
// Get the total current claims amounts
let totalClaimersPerc = await rewardsClaimersPercTotalGet();
// Get the total % needed to make 100%
let claimAmount = '1'.ether.sub(totalClaimersPerc).add('0.001'.ether);
// Set the amount this contract can claim and expect total claimers amount to equal 1 ether (100%)
await shouldRevert(setDAONetworkBootstrapRewardsClaimer('rocketClaimNode', claimAmount, {
from: owner,
}), "Total claimers percentrage over 100%");
});
/*** Regular Nodes *************************/
it(printTitle('node', 'can claim RPL and ETH'), async () => {
// Initialize RPL inflation & claims contract
let rplInflationStartTime = await rplInflationSetup();
await rewardsContractSetup('rocketClaimNode', '0.5'.ether);
// Move to inflation start plus one claim interval
let currentTime = await getCurrentTime(web3);
assert.isBelow(currentTime, rplInflationStartTime, 'Current block should be below RPL inflation start time');
await increaseTime(web3, rplInflationStartTime - currentTime + claimIntervalTime);
// Send ETH to rewards pool
const rocketSmoothingPool = await RocketSmoothingPool.deployed();
await web3.eth.sendTransaction({ from: owner, to: rocketSmoothingPool.address, value: '20'.ether});
const rocketRewardsPool = await RocketRewardsPool.deployed();
const pendingRewards = await rocketRewardsPool.getPendingETHRewards.call();
// Submit rewards snapshot
const rewards = [
{
address: registeredNode1,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '1'.ether,
nodeETH: '0'.ether
},
{
address: registeredNode2,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '2'.ether,
nodeETH: '1'.ether
},
{
address: registeredNodeTrusted1,
network: 0,
trustedNodeRPL: '1'.ether,
nodeRPL: '2'.ether,
nodeETH: '0'.ether
},
{
address: userOne,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '1.333'.ether,
nodeETH: '0.3'.ether
},
]
await submitRewards(0, rewards, '0'.ether, '2'.ether, {from: registeredNodeTrusted1});
await submitRewards(0, rewards, '0'.ether, '2'.ether, {from: registeredNodeTrusted2});
// Claim RPL
await claimRewards(registeredNode1, [0], [rewards], {
from: registeredNode1,
});
await claimRewards(registeredNode2, [0], [rewards], {
from: registeredNode2,
});
await claimRewards(registeredNodeTrusted1, [0], [rewards], {
from: registeredNodeTrusted1,
});
await claimRewards(userOne, [0], [rewards], {
from: userOne,
});
// Do a second claim interval
await submitRewards(1, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(1, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
// Claim RPL
await claimRewards(registeredNode1, [1], [rewards], {
from: registeredNode1,
});
await claimRewards(registeredNode2, [1], [rewards], {
from: registeredNode2,
});
});
it(printTitle('node', 'can claim from withdrawal address'), async () => {
// Initialize RPL inflation & claims contract
let rplInflationStartTime = await rplInflationSetup();
await rewardsContractSetup('rocketClaimNode', '0.5'.ether);
// Move to inflation start plus one claim interval
let currentTime = await getCurrentTime(web3);
assert.isBelow(currentTime, rplInflationStartTime, 'Current block should be below RPL inflation start time');
await increaseTime(web3, rplInflationStartTime - currentTime + claimIntervalTime);
// Send ETH to rewards pool
const rocketSmoothingPool = await RocketSmoothingPool.deployed();
await web3.eth.sendTransaction({ from: owner, to: rocketSmoothingPool.address, value: '20'.ether});
// Submit rewards snapshot
const rewards = [
{
address: registeredNode1,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '1'.ether,
nodeETH: '0'.ether
}
]
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
// Claim RPL
await claimRewards(registeredNode1, [0], [rewards], {
from: node1WithdrawalAddress,
});
});
it(printTitle('node', 'can not claim with invalid proof'), async () => {
// Initialize RPL inflation & claims contract
let rplInflationStartTime = await rplInflationSetup();
await rewardsContractSetup('rocketClaimNode', '0.5'.ether);
// Move to inflation start plus one claim interval
let currentTime = await getCurrentTime(web3);
assert.isBelow(currentTime, rplInflationStartTime, 'Current block should be below RPL inflation start time');
await increaseTime(web3, rplInflationStartTime - currentTime + claimIntervalTime);
// Submit rewards snapshot
const rewards = [
{
address: registeredNode1,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '1'.ether,
nodeETH: '0'.ether
},
]
// Create 3 snapshots
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
let treeData = parseRewardsMap(rewards);
let proof = treeData.proof.claims[web3.utils.toChecksumAddress(registeredNode1)];
let amountsRPL = [proof.amountRPL];
let amountsETH = [proof.amountETH];
let proofs = [proof.proof];
let rocketMerkleDistributorMainnet = await RocketMerkleDistributorMainnet.deployed();
// Attempt to claim reward for registeredNode1 with registeredNode2
await shouldRevert(rocketMerkleDistributorMainnet.claim(registeredNode2, [0], amountsRPL, amountsETH, proofs, {from: registeredNode2}), 'Was able to claim with invalid proof', 'Invalid proof');
});
it(printTitle('node', 'can not claim same interval twice'), async () => {
// Initialize RPL inflation & claims contract
let rplInflationStartTime = await rplInflationSetup();
await rewardsContractSetup('rocketClaimNode', '0.5'.ether);
// Move to inflation start plus one claim interval
let currentTime = await getCurrentTime(web3);
assert.isBelow(currentTime, rplInflationStartTime, 'Current block should be below RPL inflation start time');
await increaseTime(web3, rplInflationStartTime - currentTime + claimIntervalTime);
// Submit rewards snapshot
const rewards = [
{
address: registeredNode1,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '1'.ether,
nodeETH: '0'.ether
},
]
// Create 3 snapshots
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
await submitRewards(1, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(1, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
await submitRewards(2, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(2, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
// Claim RPL
await claimRewards(registeredNode1, [0, 1], [rewards, rewards], {
from: registeredNode1,
});
await shouldRevert(claimRewards(registeredNode1, [0], [rewards], {
from: registeredNode1,
}), 'Was able to claim again', 'Already claimed');
await shouldRevert(claimRewards(registeredNode1, [1], [rewards], {
from: registeredNode1,
}), 'Was able to claim again', 'Already claimed');
await shouldRevert(claimRewards(registeredNode1, [0, 1], [rewards, rewards], {
from: registeredNode1,
}), 'Was able to claim again', 'Already claimed');
await shouldRevert(claimRewards(registeredNode1, [0, 2], [rewards, rewards], {
from: registeredNode1,
}), 'Was able to claim again', 'Already claimed');
});
it(printTitle('node', 'can claim mulitiple periods in a single tx'), async () => {
// Initialize RPL inflation & claims contract
let rplInflationStartTime = await rplInflationSetup();
await rewardsContractSetup('rocketClaimNode', '0.5'.ether);
// Move to inflation start plus one claim interval
let currentTime = await getCurrentTime(web3);
assert.isBelow(currentTime, rplInflationStartTime, 'Current block should be below RPL inflation start time');
await increaseTime(web3, rplInflationStartTime - currentTime + claimIntervalTime);
// Submit rewards snapshot
const rewards = [
{
address: registeredNode1,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '1'.ether,
nodeETH: '0'.ether
},
{
address: registeredNode2,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '2'.ether,
nodeETH: '0'.ether
}
]
// Submit 2 snapshots
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
await submitRewards(1, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(1, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
await submitRewards(2, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(2, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
// Claim RPL
await claimRewards(registeredNode1, [0], [rewards], {
from: registeredNode1,
});
await claimRewards(registeredNode1, [1, 2], [rewards, rewards], {
from: registeredNode1,
});
await claimRewards(registeredNode2, [0, 1, 2], [rewards, rewards, rewards], {
from: registeredNode2,
});
});
it(printTitle('node', 'can claim RPL and stake'), async () => {
// Initialize RPL inflation & claims contract
let rplInflationStartTime = await rplInflationSetup();
await rewardsContractSetup('rocketClaimNode', '0.5'.ether);
// Move to inflation start plus one claim interval
let currentTime = await getCurrentTime(web3);
assert.isBelow(currentTime, rplInflationStartTime, 'Current block should be below RPL inflation start time');
await increaseTime(web3, rplInflationStartTime - currentTime + claimIntervalTime);
// Submit rewards snapshot
const rewards = [
{
address: registeredNode1,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '1'.ether,
nodeETH: '0'.ether
},
{
address: registeredNode2,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '2'.ether,
nodeETH: '0'.ether
}
]
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
// Claim RPL
await claimAndStakeRewards(registeredNode1, [0], [rewards], '1'.ether, {
from: registeredNode1,
});
await claimAndStakeRewards(registeredNode2, [0], [rewards], '2'.ether, {
from: registeredNode2,
});
// Do a second claim interval
await submitRewards(1, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(1, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
// Claim RPL
await claimAndStakeRewards(registeredNode1, [1], [rewards], '0.5'.ether, {
from: registeredNode1,
});
await claimAndStakeRewards(registeredNode2, [1], [rewards], '1'.ether, {
from: registeredNode2,
});
});
it(printTitle('node', 'can not stake amount greater than claim'), async () => {
// Initialize RPL inflation & claims contract
let rplInflationStartTime = await rplInflationSetup();
await rewardsContractSetup('rocketClaimNode', '0.5'.ether);
// Move to inflation start plus one claim interval
let currentTime = await getCurrentTime(web3);
assert.isBelow(currentTime, rplInflationStartTime, 'Current block should be below RPL inflation start time');
await increaseTime(web3, rplInflationStartTime - currentTime + claimIntervalTime);
// Submit rewards snapshot
const rewards = [
{
address: registeredNode1,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '1'.ether,
nodeETH: '0'.ether
},
]
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
// Claim RPL
await shouldRevert(claimAndStakeRewards(registeredNode1, [0], [rewards], '2'.ether, {
from: registeredNode1,
}), 'Was able to stake amount greater than reward', 'Invalid stake amount');
});
it(printTitle('node', 'can claim RPL and stake multiple snapshots'), async () => {
// Initialize RPL inflation & claims contract
let rplInflationStartTime = await rplInflationSetup();
await rewardsContractSetup('rocketClaimNode', '0.5'.ether);
// Move to inflation start plus one claim interval
let currentTime = await getCurrentTime(web3);
assert.isBelow(currentTime, rplInflationStartTime, 'Current block should be below RPL inflation start time');
await increaseTime(web3, rplInflationStartTime - currentTime + claimIntervalTime);
// Submit rewards snapshot
const rewards = [
{
address: registeredNode1,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '1'.ether,
nodeETH: '0'.ether
}
]
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
await submitRewards(1, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(1, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
// Claim RPL
await claimAndStakeRewards(registeredNode1, [0, 1], [rewards, rewards], '2'.ether, {
from: registeredNode1,
});
});
/*** Random *************************/
it(printTitle('random', 'can execute reward period if consensus is reached'), async () => {
// Initialize RPL inflation & claims contract
let rplInflationStartTime = await rplInflationSetup();
await rewardsContractSetup('rocketClaimNode', '0.5'.ether);
// Move to inflation start plus one claim interval
let currentTime = await getCurrentTime(web3);
assert.isBelow(currentTime, rplInflationStartTime, 'Current block should be below RPL inflation start time');
await increaseTime(web3, rplInflationStartTime - currentTime + claimIntervalTime);
// Add another 2 trusted nodes so consensus becomes 3 votes
await setNodeTrusted(unregisteredNodeTrusted1, 'saas_3', 'node@home.com', owner);
await setNodeTrusted(unregisteredNodeTrusted2, 'saas_4', 'node@home.com', owner);
// Submit rewards snapshot
const rewards = [
{
address: registeredNode1,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '1'.ether,
nodeETH: '0'.ether
},
]
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(0, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
// Kick a trusted node so consensus becomes 2 votes again
await kickTrustedNode(unregisteredNodeTrusted1, [registeredNodeTrusted1, registeredNodeTrusted2, unregisteredNodeTrusted1]);
// Now we should be able to execute the reward period
await executeRewards(0, rewards, '0'.ether, '0'.ether, {from: random});
});
/*** Misc *************************/
it(printTitle('misc', 'claim bitmap is correct'), async () => {
// Initialize RPL inflation & claims contract
let rplInflationStartTime = await rplInflationSetup();
await rewardsContractSetup('rocketClaimNode', '0.5'.ether);
// Move to inflation start plus one claim interval
let currentTime = await getCurrentTime(web3);
assert.isBelow(currentTime, rplInflationStartTime, 'Current block should be below RPL inflation start time');
await increaseTime(web3, rplInflationStartTime - currentTime + claimIntervalTime);
// Submit rewards snapshot
const rewards = [
{
address: registeredNode1,
network: 0,
trustedNodeRPL: '0'.ether,
nodeRPL: '1'.ether,
nodeETH: '0'.ether
},
]
// Submit 10 reward intervals
for (let i = 0; i < 10; i++) {
await submitRewards(i, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted1});
await submitRewards(i, rewards, '0'.ether, '0'.ether, {from: registeredNodeTrusted2});
}
// Some arbitrary intervals to claim
let claimIntervals = [ 0, 4, 6, 9 ];
await claimRewards(registeredNode1, claimIntervals, Array(claimIntervals.length).fill(rewards), {
from: registeredNode1,
});
// Retrieve the bitmap of claims
const rocketStorage = await RocketStorage.deployed();
const key = web3.utils.soliditySha3(
{type: 'string', value: 'rewards.interval.claimed'},
{type: 'address', value: registeredNode1},
{type: 'uint256', value: 0}
)
const bitmap = (await rocketStorage.getUint.call(key)).toNumber();
// Construct the expected bitmap and compare
let expected = 0;
for (let i = 0; i < claimIntervals.length; i++) {
expected |= 1 << claimIntervals[i];
}
assert.strictEqual(bitmap, expected, 'Incorrect claimed bitmap');
// Confirm second claim fails for each interval
for (let i = 0; i < claimIntervals.length; i++) {
await shouldRevert(claimRewards(registeredNode1, [claimIntervals[i]], [rewards], {
from: registeredNode1,
}), 'Was able to claim again', 'Already claimed');
}
});
});
}