diff --git a/contracts/ClaimsReward.sol b/contracts/ClaimsReward.sol index 5c3339e385..63332c3d4e 100644 --- a/contracts/ClaimsReward.sol +++ b/contracts/ClaimsReward.sol @@ -222,6 +222,7 @@ contract ClaimsReward is Iupgradable { * @return total reward amount of the user */ function getAllPendingRewardOfUser(address _add) public view returns(uint total) { + require(!pooledStaking.hasPendingActions(), "Pooled staking actions are not all processed yet."); uint caReward = getRewardToBeDistributedByUser(_add); uint pooledStakingReward = pooledStaking.stakerReward(_add); uint stakedTokens = pooledStaking.stakerStake(_add); diff --git a/contracts/interfaces/IPooledStaking.sol b/contracts/interfaces/IPooledStaking.sol index c8b28467e3..3d507d2521 100644 --- a/contracts/interfaces/IPooledStaking.sol +++ b/contracts/interfaces/IPooledStaking.sol @@ -13,5 +13,7 @@ interface IPooledStaking { function getMaxUnstakable(address stakerAddress) external view returns (uint); function withdrawReward(uint amount) external; + + function hasPendingActions() external view returns (bool); } diff --git a/test/09_ClaimReward.test.js b/test/09_ClaimReward.test.js index 74e5d33832..c791d0b99e 100644 --- a/test/09_ClaimReward.test.js +++ b/test/09_ClaimReward.test.js @@ -214,6 +214,8 @@ contract('ClaimsReward', function([ claimed[1].should.be.equal(false); let apiid = await pd.allAPIcall((await pd.getApilCallLength()) - 1); await P1.__callback(apiid, ''); + + await ps.processPendingActions(); }); it('9.1 should change claim reward contract', async function() { let newCr = await ClaimsReward.new(); @@ -264,12 +266,15 @@ contract('ClaimsReward', function([ let initialBalance; let rewardToGet; let lockedStakedNXM; + let stakerRewardAmount; before(async function() { initialBalance = await tk.balanceOf(staker1); lockedStakedNXM = await tf.getStakerAllLockedTokens(staker1); await increaseTimeTo((await latestTime()) + duration.days(3)); + rewardToGet = await cr.getAllPendingRewardOfUser(staker1); + stakerRewardAmount = await ps.stakerReward(staker1); unlockableStakedNXM = await tf.getStakerAllUnlockableStakedTokens( staker1 @@ -278,18 +283,18 @@ contract('ClaimsReward', function([ it('9.4 should be able to claim reward', async function() { let proposalIds = []; await cr.claimAllPendingReward(20, {from: staker1}); + await ps.withdrawReward(staker1, stakerRewardAmount); (await cr.getAllPendingRewardOfUser(staker1)) .toString() - .should.be.equal((0).toString()); + .should.be.equal(stakeTokens.toString()); }); it('9.5 should increase balance of staker', async function() { - (await tk.balanceOf(staker1)) - .toString() - .should.be.equal( - new BN(initialBalance.toString()) - .add(new BN(rewardToGet.toString())) - .toString() - ); + (await tk.balanceOf(staker1)).toString().should.be.equal( + new BN(initialBalance.toString()) + .add(new BN(rewardToGet.toString())) + .sub(new BN(stakeTokens.toString())) + .toString() + ); }); it('9.6 should decrease locked staked tokens of staker', async function() { (await tf.getStakerAllLockedTokens(staker1)) @@ -317,18 +322,30 @@ contract('ClaimsReward', function([ }); }); - describe('Test for claim reward for particular numbers of records', function() { + describe.only('Test for claim reward for particular numbers of records', function() { let apiidArr = []; let conAdds = []; + let totalCoverPrice = new BN(0); before(async function() { conAdds.push(smartConAdd1); conAdds.push(smartConAdd2); conAdds.push(smartConAdd3); conAdds.push(smartConAdd4); conAdds.push(smartConAdd5); + + const stakeAmount = toWei(30).toString(); + const stakeAmounts = []; for (let j = 0; j < conAdds.length; j++) { - await tf.addStake(conAdds[j], toWei(30), {from: newMember1}); + stakeAmounts.push(stakeAmount); } + + await tk.approve(ps.address, stakeAmount, { + from: newMember1 + }); + await ps.stake(stakeAmount, conAdds, stakeAmounts, { + from: newMember1 + }); + let coverDetailsTest = [ 1, '3362445813369838', @@ -336,6 +353,7 @@ contract('ClaimsReward', function([ '7972408607', '7972408607201' ]; + for (let i = 0; i < conAdds.length; i++) { coverDetailsTest[4] = coverDetailsTest[4] / 1 + 1; @@ -343,6 +361,8 @@ contract('ClaimsReward', function([ if (i == 3) coverDetailsTest[2] = toWei(50) / 1; coverDetailsTest[2] = coverDetailsTest[2].toString(); + + totalCoverPrice = totalCoverPrice.add(new BN(coverDetailsTest[2])); var vrsdata = await getQuoteValues( coverDetailsTest, toHex('ETH'), @@ -361,33 +381,22 @@ contract('ClaimsReward', function([ {from: newMember2, value: coverDetailsTest[1].toString()} ); } + await ps.processPendingActions(); }); it('9.10 should claim commision for covers', async function() { - assert.equal( - await td.getStakerTotalReedmedStakeCommission(newMember1), - 0 - ); - let initialLastClaimed = await td.lastCompletedStakeCommission( - newMember1 - ); - await cr.claimAllPendingReward(3, {from: newMember1}); - assert.equal( - await td.getStakerTotalReedmedStakeCommission(newMember1), - toWei(45) - ); - assert.equal( - await td.lastCompletedStakeCommission(newMember1), - initialLastClaimed / 1 + 3 - ); let initialBal = await tk.balanceOf(newMember1); - await cr.claimAllPendingReward(3, {from: newMember1}); + const stakerRewardAmount = await ps.stakerReward(newMember1); + await ps.withdrawReward(newMember1, stakerRewardAmount); let finalBal = await tk.balanceOf(newMember1); - assert.equal(finalBal - initialBal, toWei(25)); - assert.equal( - await td.lastCompletedStakeCommission(newMember1), - initialLastClaimed / 1 + 3 - ); + + const stakerRewardPercentage = await td.stakerCommissionPer(); + const expectedTotalReward = totalCoverPrice + .mul(new BN(stakerRewardPercentage)) + .div(new BN(100)); + + assert.equal(finalBal - initialBal, expectedTotalReward); + let coverDetailsTest = [ 1, '3362445813369838', @@ -395,7 +404,9 @@ contract('ClaimsReward', function([ '7972408607', '7972408607501' ]; - coverDetailsTest[2] = toWei(500); + + const coverNXMPrice = toWei(500); + coverDetailsTest[2] = coverNXMPrice; var vrsdata = await getQuoteValues( coverDetailsTest, toHex('ETH'), @@ -414,14 +425,16 @@ contract('ClaimsReward', function([ {from: newMember2, value: coverDetailsTest[1].toString()} ); + await ps.processPendingActions(); + initialBal = await tk.balanceOf(newMember1); - await cr.claimAllPendingReward(5, {from: newMember1}); + const secondStakerRewardAmount = await ps.stakerReward(newMember1); + await ps.withdrawReward(newMember1, secondStakerRewardAmount); finalBal = await tk.balanceOf(newMember1); - assert.equal(finalBal - initialBal, toWei(5)); - assert.equal( - await td.lastCompletedStakeCommission(newMember1), - initialLastClaimed / 1 + 5 - ); + const secondExpectedReward = new BN(coverNXMPrice.toString()) + .mul(new BN(stakerRewardPercentage)) + .div(new BN(100)); + assert.equal(finalBal - initialBal, secondExpectedReward); }); it('9.11 should claim reward for CA votes', async function() { diff --git a/test/10_EmergencyPause.test.js b/test/10_EmergencyPause.test.js index ba3666086f..824bc3f4a7 100644 --- a/test/10_EmergencyPause.test.js +++ b/test/10_EmergencyPause.test.js @@ -1,7 +1,7 @@ const Pool1 = artifacts.require('Pool1Mock'); const Pool2 = artifacts.require('Pool2'); const PoolData = artifacts.require('PoolDataMock'); -const NXMaster = artifacts.require('NXMaster'); +const NXMaster = artifacts.require('NXMasterMock'); const NXMToken = artifacts.require('NXMToken'); const TokenFunctions = artifacts.require('TokenFunctionMock'); const TokenController = artifacts.require('TokenController'); @@ -16,11 +16,12 @@ const MCR = artifacts.require('MCR'); const Governance = artifacts.require('Governance'); const ProposalCategory = artifacts.require('ProposalCategory'); const MemberRoles = artifacts.require('MemberRoles'); -const { assertRevert } = require('./utils/assertRevert'); -const { advanceBlock } = require('./utils/advanceToBlock'); -const { ether, toHex, toWei } = require('./utils/ethTools'); -const { increaseTimeTo, duration } = require('./utils/increaseTime'); -const { latestTime } = require('./utils/latestTime'); +const PooledStaking = artifacts.require('PooledStakingMock'); +const {assertRevert} = require('./utils/assertRevert'); +const {advanceBlock} = require('./utils/advanceToBlock'); +const {ether, toHex, toWei} = require('./utils/ethTools'); +const {increaseTimeTo, duration} = require('./utils/increaseTime'); +const {latestTime} = require('./utils/latestTime'); const getQuoteValues = require('./utils/getQuote.js').getQuoteValues; const getValue = require('./utils/getMCRPerThreshold.js').getValue; @@ -64,7 +65,7 @@ contract('NXMaster: Emergency Pause', function([ coverHolder3, newMember ]) { - const stakeTokens = ether(1); + const stakeTokens = ether(20); const tokens = ether(200); const validity = duration.days(30); const UNLIMITED_ALLOWANCE = new BN((2).toString()) @@ -91,6 +92,7 @@ contract('NXMaster: Emergency Pause', function([ let address = await nxms.getLatestAddress(toHex('MR')); mr = await MemberRoles.at(address); tc = await TokenController.at(await nxms.getLatestAddress(toHex('TC'))); + ps = await PooledStaking.deployed(); await mr.addMembersBeforeLaunch([], []); (await mr.launched()).should.be.equal(true); await mcr.addMCRData( @@ -103,47 +105,55 @@ contract('NXMaster: Emergency Pause', function([ ); // await mr.payJoiningFee(owner, { from: owner, value: fee }); // await mr.kycVerdict(owner, true); - await mr.payJoiningFee(member1, { from: member1, value: fee }); + await mr.payJoiningFee(member1, {from: member1, value: fee}); await mr.kycVerdict(member1, true); - await tk.approve(tc.address, UNLIMITED_ALLOWANCE, { from: member1 }); - await mr.payJoiningFee(member2, { from: member2, value: fee }); + await tk.approve(tc.address, UNLIMITED_ALLOWANCE, {from: member1}); + await mr.payJoiningFee(member2, {from: member2, value: fee}); await mr.kycVerdict(member2, true); - await tk.approve(tc.address, UNLIMITED_ALLOWANCE, { from: member2 }); - await mr.payJoiningFee(member3, { from: member3, value: fee }); + await tk.approve(tc.address, UNLIMITED_ALLOWANCE, {from: member2}); + await mr.payJoiningFee(member3, {from: member3, value: fee}); await mr.kycVerdict(member3, true); - await tk.approve(tc.address, UNLIMITED_ALLOWANCE, { from: member3 }); + await tk.approve(tc.address, UNLIMITED_ALLOWANCE, {from: member3}); - await mr.payJoiningFee(member4, { from: member4, value: fee }); + await mr.payJoiningFee(member4, {from: member4, value: fee}); await mr.kycVerdict(member4, true); - await tk.approve(tc.address, UNLIMITED_ALLOWANCE, { from: member4 }); - await tk.approve(tc.address, UNLIMITED_ALLOWANCE, { from: owner }); + await tk.approve(tc.address, UNLIMITED_ALLOWANCE, {from: member4}); + await tk.approve(tc.address, UNLIMITED_ALLOWANCE, {from: owner}); await mr.payJoiningFee(coverHolder1, { from: coverHolder1, value: fee }); await mr.kycVerdict(coverHolder1, true); - await tk.approve(tc.address, UNLIMITED_ALLOWANCE, { from: coverHolder1 }); + await tk.approve(tc.address, UNLIMITED_ALLOWANCE, {from: coverHolder1}); await mr.payJoiningFee(coverHolder2, { from: coverHolder2, value: fee }); await mr.kycVerdict(coverHolder2, true); - await tk.approve(tc.address, UNLIMITED_ALLOWANCE, { from: coverHolder2 }); + await tk.approve(tc.address, UNLIMITED_ALLOWANCE, {from: coverHolder2}); await mr.payJoiningFee(coverHolder3, { from: coverHolder3, value: fee }); await mr.kycVerdict(coverHolder3, true); - await tk.approve(tc.address, UNLIMITED_ALLOWANCE, { from: coverHolder3 }); + await tk.approve(tc.address, UNLIMITED_ALLOWANCE, {from: coverHolder3}); await tk.transfer(member1, tokens); await tk.transfer(member2, tokens); await tk.transfer(member3, tokens); await tk.transfer(member4, tokens); await tk.transfer(coverHolder1, tokens); await tk.transfer(coverHolder2, tokens); - await tf.addStake(smartConAdd, stakeTokens, { from: member1 }); - await tf.addStake(smartConAdd, stakeTokens, { from: member2 }); + + const stakers = [member1, member2]; + for (const staker of stakers) { + await tk.approve(ps.address, stakeTokens, { + from: staker + }); + await ps.stake(stakeTokens, [smartConAdd], [stakeTokens], { + from: staker + }); + } maxVotingTime = await cd.maxVotingTime(); }); @@ -165,7 +175,7 @@ contract('NXMaster: Emergency Pause', function([ vrsdata[0], vrsdata[1], vrsdata[2], - { from: coverHolder1, value: coverDetails[1] } + {from: coverHolder1, value: coverDetails[1]} ); coverDetails[4] = 7972408607002; vrsdata = await getQuoteValues( @@ -183,7 +193,7 @@ contract('NXMaster: Emergency Pause', function([ vrsdata[0], vrsdata[1], vrsdata[2], - { from: coverHolder2, value: coverDetails[1] } + {from: coverHolder2, value: coverDetails[1]} ); coverDetails[4] = 7972408607003; vrsdata = await getQuoteValues( @@ -201,7 +211,7 @@ contract('NXMaster: Emergency Pause', function([ vrsdata[0], vrsdata[1], vrsdata[2], - { from: coverHolder3, value: coverDetails[1] } + {from: coverHolder3, value: coverDetails[1]} ); await tc.lock(CLA, ether(60), validity, { @@ -211,14 +221,17 @@ contract('NXMaster: Emergency Pause', function([ from: member2 }); let proposalsIDs = []; - await cr.claimAllPendingReward(20, { from: member4 }); + + await ps.processPendingActions(); + + await cr.claimAllPendingReward(20, {from: member4}); }); it('10.1 should return false for isPause', async function() { (await nxms.isPause()).should.equal(false); }); it('10.2 should let deny claim', async function() { const coverID = await qd.getAllCoversOfUser(coverHolder3); - await cl.submitClaim(coverID[0], { from: coverHolder3 }); + await cl.submitClaim(coverID[0], {from: coverHolder3}); var APIID = await pd.allAPIcall((await pd.getApilCallLength()) - 1); const claimId = (await cd.actualClaimLength()) - 1; let nowTime = await latestTime(); @@ -234,7 +247,7 @@ contract('NXMaster: Emergency Pause', function([ }); it('10.2 should let submit claim', async function() { const coverID = await qd.getAllCoversOfUser(coverHolder1); - await cl.submitClaim(coverID[0], { from: coverHolder1 }); + await cl.submitClaim(coverID[0], {from: coverHolder1}); const claimId = (await cd.actualClaimLength()) - 1; claimId.toString().should.be.equal((2).toString()); let cid = await cd.getAllClaimsByIndex(claimId); @@ -243,17 +256,17 @@ contract('NXMaster: Emergency Pause', function([ .should.be.equal((4).toString()); }); it('10.3 should be able to do claim assessment or stake NXM for claim', async function() { - await tc.lock(CLA, ether(60), validity, { from: member3 }); + await tc.lock(CLA, ether(60), validity, {from: member3}); }); it('10.4 should be able to buy nxm token', async function() { - await P1.buyToken({ value: ether(60), from: member1 }); + await P1.buyToken({value: ether(60), from: member1}); }); it('10.5 should be able to redeem NXM tokens', async function() { - await P1.sellNXMTokens(await mcr.getMaxSellTokens(), { from: member1 }); + await P1.sellNXMTokens(await mcr.getMaxSellTokens(), {from: member1}); }); it('10.6 should be able to withdraw membership', async function() { - await mr.withdrawMembership({ from: member4 }); + await mr.withdrawMembership({from: member4}); }); }); @@ -279,7 +292,7 @@ contract('NXMaster: Emergency Pause', function([ vrsdata[0], vrsdata[1], vrsdata[2], - { from: newMember, value: totalFee } + {from: newMember, value: totalFee} ); let p = await gv.getProposalLength(); @@ -309,7 +322,7 @@ contract('NXMaster: Emergency Pause', function([ v, r, s, - { from: newMember, value: totalFee } + {from: newMember, value: totalFee} ) ); }); @@ -325,7 +338,7 @@ contract('NXMaster: Emergency Pause', function([ }); it('10.9 should not be able to pay joining fee', async function() { await assertRevert( - mr.payJoiningFee(member5, { from: member5, value: fee }) + mr.payJoiningFee(member5, {from: member5, value: fee}) ); }); it('10.10 should not be able to trigger kyc', async function() { @@ -333,18 +346,18 @@ contract('NXMaster: Emergency Pause', function([ }); it('10.11 add claim to queue', async function() { const coverID = await qd.getAllCoversOfUser(coverHolder2); - await cl.submitClaim(coverID[0], { from: coverHolder2 }); + await cl.submitClaim(coverID[0], {from: coverHolder2}); (await qd.getCoverStatusNo(coverID[0])) .toString() .should.be.equal((5).toString()); }); it('10.12 should not let member vote for claim assessment', async function() { const claimId = (await cd.actualClaimLength()) - 1; - await assertRevert(cl.submitCAVote(claimId, -1, { from: member1 })); + await assertRevert(cl.submitCAVote(claimId, -1, {from: member1})); }); it('10.13 should not be able to change claim status', async function() { const claimId = (await cd.actualClaimLength()) - 1; - await assertRevert(cr.changeClaimStatus(claimId, { from: owner })); + await assertRevert(cr.changeClaimStatus(claimId, {from: owner})); }); it('10.14 should not be able to make cover', async function() { await assertRevert( @@ -356,31 +369,38 @@ contract('NXMaster: Emergency Pause', function([ v, r, s, - { from: coverHolder1, value: coverDetails[1] } + {from: coverHolder1, value: coverDetails[1]} ) ); }); it('10.15 should not be able to assess risk', async function() { - await assertRevert(tf.addStake(smartConAdd, 1, { from: member1 })); + await tk.approve(ps.address, stakeTokens, { + from: member3 + }); + await assertRevert( + ps.stake(stakeTokens, [smartConAdd], [stakeTokens], { + from: member3 + }) + ); }); it('10.16 should not be able to submit CA Vote', async function() { const claimId = (await cd.actualClaimLength()) - 1; - await assertRevert(cl.submitCAVote(claimId, 0, { from: member1 })); + await assertRevert(cl.submitCAVote(claimId, 0, {from: member1})); }); it('10.17 should not be able to do claim assessment or stake NXM for claim', async function() { - await assertRevert(tc.lock(CLA, ether(60), validity, { from: member3 })); + await assertRevert(tc.lock(CLA, ether(60), validity, {from: member3})); // dont use member1 or member2 as they are already locked }); it('10.18 should not be able to buy nxm token', async function() { - await assertRevert(P1.buyToken({ value: ether(60), from: member1 })); + await assertRevert(P1.buyToken({value: ether(60), from: member1})); }); it('10.19 should not be able to redeem NXM tokens', async function() { - await assertRevert(P1.sellNXMTokens(ether(1), { from: member1 })); + await assertRevert(P1.sellNXMTokens(ether(1), {from: member1})); }); it('10.20 should not be able to withdraw membership', async function() { - await assertRevert(mr.withdrawMembership({ from: member4 })); + await assertRevert(mr.withdrawMembership({from: member4})); }); it('10.21 Should not be able to save IA details', async function() {