From 46fb0a0c6f21e96d7483881c21ff66672f6f434f Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Sun, 2 Aug 2020 14:19:59 +0300 Subject: [PATCH 01/19] start implementing --- contracts/BlockReward.sol | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/contracts/BlockReward.sol b/contracts/BlockReward.sol index 8191e88..9368a06 100644 --- a/contracts/BlockReward.sol +++ b/contracts/BlockReward.sol @@ -85,7 +85,7 @@ contract BlockReward is EternalStorage, BlockRewardBase { require(benefactors.length == 1); require(kind[0] == 0); - uint256 blockRewardAmount = getBlockRewardAmount(); + uint256 blockRewardAmount = getBlockRewardAmountPerValidator(benefactors[0]); (address[] memory _delegators, uint256[] memory _rewards) = IConsensus(ProxyStorage(getProxyStorage()).getConsensus()).getDelegatorsForRewardDistribution(benefactors[0], blockRewardAmount); @@ -183,6 +183,13 @@ contract BlockReward is EternalStorage, BlockRewardBase { return uintStorage[BLOCK_REWARD_AMOUNT]; } + function getBlockRewardAmountPerValidator(address _validator) public view returns(uint256) { + uint256 blockRewardAmount = getBlockRewardAmount(); + return blockRewardAmount + // return uintStorage[BLOCK_REWARD_AMOUNT]; + } + + function getProxyStorage() public view returns(address) { return addressStorage[PROXY_STORAGE]; } From ce0978304a5ac889a7cf0cf39ca14e617788a16f Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Wed, 5 Aug 2020 16:26:58 +0300 Subject: [PATCH 02/19] moving contracts --- {test/contracts => contracts/test}/BlockRewardMock.sol | 2 +- {test/contracts => contracts/test}/ConsensusMock.sol | 2 +- {test/contracts => contracts/test}/EternalStorageProxyMock.sol | 2 +- {test/contracts => contracts/test}/ProxyStorageMock.sol | 2 +- {test/contracts => contracts/test}/VotingMock.sol | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename {test/contracts => contracts/test}/BlockRewardMock.sol (92%) rename {test/contracts => contracts/test}/ConsensusMock.sol (97%) rename {test/contracts => contracts/test}/EternalStorageProxyMock.sol (84%) rename {test/contracts => contracts/test}/ProxyStorageMock.sol (93%) rename {test/contracts => contracts/test}/VotingMock.sol (81%) diff --git a/test/contracts/BlockRewardMock.sol b/contracts/test/BlockRewardMock.sol similarity index 92% rename from test/contracts/BlockRewardMock.sol rename to contracts/test/BlockRewardMock.sol index 4032fbe..82b3109 100644 --- a/test/contracts/BlockRewardMock.sol +++ b/contracts/test/BlockRewardMock.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../../contracts/BlockReward.sol"; +import "../BlockReward.sol"; contract BlockRewardMock is BlockReward { function setSystemAddressMock(address _newAddress) public onlyOwner { diff --git a/test/contracts/ConsensusMock.sol b/contracts/test/ConsensusMock.sol similarity index 97% rename from test/contracts/ConsensusMock.sol rename to contracts/test/ConsensusMock.sol index 36a9058..9be0adb 100644 --- a/test/contracts/ConsensusMock.sol +++ b/contracts/test/ConsensusMock.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../../contracts/Consensus.sol"; +import "../Consensus.sol"; contract ConsensusMock is Consensus { function setSystemAddressMock(address _newAddress) public onlyOwner { diff --git a/test/contracts/EternalStorageProxyMock.sol b/contracts/test/EternalStorageProxyMock.sol similarity index 84% rename from test/contracts/EternalStorageProxyMock.sol rename to contracts/test/EternalStorageProxyMock.sol index 72730d4..ebcf07c 100644 --- a/test/contracts/EternalStorageProxyMock.sol +++ b/contracts/test/EternalStorageProxyMock.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import '../../contracts/eternal-storage/EternalStorageProxy.sol'; +import '../eternal-storage/EternalStorageProxy.sol'; contract EternalStorageProxyMock is EternalStorageProxy { constructor(address _proxyStorage, address _implementation) EternalStorageProxy(_proxyStorage, _implementation) public {} diff --git a/test/contracts/ProxyStorageMock.sol b/contracts/test/ProxyStorageMock.sol similarity index 93% rename from test/contracts/ProxyStorageMock.sol rename to contracts/test/ProxyStorageMock.sol index 92e4a0b..7f92f04 100644 --- a/test/contracts/ProxyStorageMock.sol +++ b/contracts/test/ProxyStorageMock.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../../contracts/ProxyStorage.sol"; +import "../ProxyStorage.sol"; contract ProxyStorageMock is ProxyStorage { function setBlockRewardMock(address _newAddress) public { diff --git a/test/contracts/VotingMock.sol b/contracts/test/VotingMock.sol similarity index 81% rename from test/contracts/VotingMock.sol rename to contracts/test/VotingMock.sol index 721f71c..f2e21ac 100644 --- a/test/contracts/VotingMock.sol +++ b/contracts/test/VotingMock.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../../contracts/Voting.sol"; +import "../Voting.sol"; contract VotingMock is Voting { From 52f335c7aa41470f1446f7c72aabbb5ac4aa136f Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Mon, 10 Aug 2020 15:52:22 +0300 Subject: [PATCH 03/19] Block reward per validator function --- contracts/BlockReward.sol | 8 +- contracts/ConsensusUtils.sol | 22 ++ contracts/interfaces/IConsensus.sol | 2 + contracts/test/ConsensusMock.sol | 17 + package.json | 9 + test/blockReward.test.js | 492 +++++++++++++++++----------- 6 files changed, 351 insertions(+), 199 deletions(-) diff --git a/contracts/BlockReward.sol b/contracts/BlockReward.sol index 9368a06..296e5e9 100644 --- a/contracts/BlockReward.sol +++ b/contracts/BlockReward.sol @@ -184,9 +184,11 @@ contract BlockReward is EternalStorage, BlockRewardBase { } function getBlockRewardAmountPerValidator(address _validator) public view returns(uint256) { - uint256 blockRewardAmount = getBlockRewardAmount(); - return blockRewardAmount - // return uintStorage[BLOCK_REWARD_AMOUNT]; + IConsensus consensus = IConsensus(ProxyStorage(getProxyStorage()).getConsensus()); + uint256 stakeAmount = consensus.stakeAmount(_validator); + uint256 totalStakeAmount = consensus.totalStakeAmount(); + uint256 currentValidatorsLength = consensus.currentValidatorsLength(); + return getBlockRewardAmount().mul(stakeAmount).mul(currentValidatorsLength).div(totalStakeAmount); } diff --git a/contracts/ConsensusUtils.sol b/contracts/ConsensusUtils.sol index 90f73be..45bbc7e 100644 --- a/contracts/ConsensusUtils.sol +++ b/contracts/ConsensusUtils.sol @@ -232,10 +232,16 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { } function _currentValidatorsAdd(address _address) internal { + _totalStakeAmountAddValidator(_address); addressArrayStorage[CURRENT_VALIDATORS].push(_address); } function _setCurrentValidators(address[] _currentValidators) internal { + uint256 totalStake = 0; + for (uint i = 0; i < _currentValidators.length; i++) { + uint256 stakedAmount = stakeAmount(_currentValidators[i]); + totalStake = totalStake + stakedAmount; + } addressArrayStorage[CURRENT_VALIDATORS] = _currentValidators; } @@ -293,6 +299,11 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { return uintStorage[keccak256(abi.encodePacked("stakeAmount", _address))]; } + function totalStakeAmount() public view returns(uint256) { + // return 0; + return uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))]; + } + function _stakeAmountAdd(address _address, uint256 _amount) internal { uintStorage[keccak256(abi.encodePacked("stakeAmount", _address))] = uintStorage[keccak256(abi.encodePacked("stakeAmount", _address))].add(_amount); } @@ -393,6 +404,17 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { addressArrayStorage[NEW_VALIDATOR_SET] = _newSet; } + function _setTotalStakeAmount(uint256 _totalStake) internal { + uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = _totalStake; + } + + function _totalStakeAmountAddValidator(address _address) internal { + uint256 stakedAmount = stakeAmount(_address); + uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))].add(stakedAmount); + + // uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = _totalStake; + } + function shouldEmitInitiateChange() public view returns(bool) { return boolStorage[SHOULD_EMIT_INITIATE_CHANGE]; } diff --git a/contracts/interfaces/IConsensus.sol b/contracts/interfaces/IConsensus.sol index 44653db..6428da5 100644 --- a/contracts/interfaces/IConsensus.sol +++ b/contracts/interfaces/IConsensus.sol @@ -9,4 +9,6 @@ interface IConsensus { function isValidator(address _address) external view returns(bool); function getDelegatorsForRewardDistribution(address _validator, uint256 _rewardAmount) external view returns(address[], uint256[]); function isFinalized() external view returns(bool); + function stakeAmount(address _address) external view returns(uint256); + function totalStakeAmount() external view returns(uint256); } diff --git a/contracts/test/ConsensusMock.sol b/contracts/test/ConsensusMock.sol index 9be0adb..f30774d 100644 --- a/contracts/test/ConsensusMock.sol +++ b/contracts/test/ConsensusMock.sol @@ -3,6 +3,8 @@ pragma solidity ^0.4.24; import "../Consensus.sol"; contract ConsensusMock is Consensus { + uint256 currentValidatorsLengthMock = 0; + function setSystemAddressMock(address _newAddress) public onlyOwner { addressStorage[SYSTEM_ADDRESS] = _newAddress; } @@ -51,8 +53,23 @@ contract ConsensusMock is Consensus { return 10; } + function setCurrentValidatorsLengthMock(uint256 _currentValidatorsLengthMock) external { + currentValidatorsLengthMock = _currentValidatorsLengthMock; + } + + function currentValidatorsLength() public view returns(uint256) { + if (currentValidatorsLengthMock != 0) { + return currentValidatorsLengthMock; + } + return super.currentValidatorsLength(); + } + function setValidatorFeeMock(uint256 _amount) external { require (_amount <= 1 * DECIMALS); _setValidatorFee(msg.sender, _amount); } + + function setTotalStakeAmountMock(uint256 _totalStake) public { + _setTotalStakeAmount(_totalStake); + } } diff --git a/package.json b/package.json index 8bfddd1..b25d780 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,15 @@ "type": "git", "url": "git+https://github.com/fuseio/fuse-network.git" }, + "standard": { + "env": { + "mocha": true, + "truffle/globals": true + }, + "plugins": [ + "truffle" + ] + }, "author": "Lior Rabin", "license": "MIT", "dependencies": { diff --git a/test/blockReward.test.js b/test/blockReward.test.js index f31e7c3..0aaeec5 100644 --- a/test/blockReward.test.js +++ b/test/blockReward.test.js @@ -3,7 +3,7 @@ const ProxyStorage = artifacts.require('ProxyStorageMock.sol') const EternalStorageProxy = artifacts.require('EternalStorageProxyMock.sol') const BlockReward = artifacts.require('BlockRewardMock.sol') const Voting = artifacts.require('Voting.sol') -const {ERROR_MSG, ZERO_ADDRESS, RANDOM_ADDRESS} = require('./helpers') +const { ERROR_MSG, ZERO_ADDRESS, RANDOM_ADDRESS } = require('./helpers') const {toBN, toWei, toChecksumAddress} = web3.utils const INITIAL_SUPPLY = toWei(toBN(300000000000000000 || 0), 'gwei') @@ -12,7 +12,7 @@ const YEARLY_INFLATION_PERCENTAGE = 5 const SYSTEM_ADDRESS = '0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE' contract('BlockReward', async (accounts) => { - let blockRewardImpl, proxy, blockReward + let blockRewardImpl, proxy, blockReward, consensusImpl, consensus, proxyStorageImpl, proxyStorage let owner = accounts[0] let nonOwner = accounts[1] let mockSystemAddress = accounts[2] @@ -38,9 +38,9 @@ contract('BlockReward', async (accounts) => { blockReward = await BlockReward.at(proxy.address) // Voting - let votingImpl = await Voting.new() + const votingImpl = await Voting.new() proxy = await EternalStorageProxy.new(proxyStorage.address, votingImpl.address) - let voting = await Voting.at(proxy.address) + const voting = await Voting.at(proxy.address) // Initialize ProxyStorage await proxyStorage.initializeAddresses( @@ -72,201 +72,301 @@ contract('BlockReward', async (accounts) => { beforeEach(async () => { await blockReward.initialize(INITIAL_SUPPLY) }) - it('can only be called by system address', async () => { - await blockReward.reward([accounts[3]], [0]).should.be.rejectedWith(ERROR_MSG) - await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled - }) - it('should revert if input array contains more than one item', async () => { - await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - await blockReward.reward([accounts[3], accounts[4]], [0, 0], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) - }) - it('should revert if lengths of input arrays are not equal', async () => { - await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - await blockReward.reward([accounts[3]], [0, 0], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) - }) - it('should revert if "kind" parameter is not 0', async () => { - await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - await blockReward.reward([accounts[3]], [1], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) - }) - it('should give reward to validator and total supply should be updated', async () => { - await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - let initialSupply = await blockReward.getTotalSupply() - let blockRewardAmount = await blockReward.getBlockRewardAmount() - let {logs} = await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled - logs.length.should.be.equal(1) - logs[0].event.should.be.equal('Rewarded') - logs[0].args['receivers'].should.deep.equal([accounts[3]]) - logs[0].args['rewards'][0].should.be.bignumber.equal(blockRewardAmount) - let expectedSupply = initialSupply.add(blockRewardAmount) - expectedSupply.should.be.bignumber.equal(await blockReward.getTotalSupply()) - }) - it('should give rewards to validator and its delegators', async () => { - let decimals = await consensus.DECIMALS() - let minStakeAmount = await consensus.getMinStake() - let delegatorsCount = accounts.length - 2 - let delegateAmountValue = parseInt(minStakeAmount.div(decimals).toNumber() * 0.99 / delegatorsCount) - let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') - let stakeAmountValue = minStakeAmount.div(decimals).toNumber() - delegateAmountValue * delegatorsCount - let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') - let fee = 5 - let validator = accounts[1] - await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled - for (let i = 2; i < accounts.length; i++) { - await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled - } - await consensus.setValidatorFeeMock(fee, {from: validator}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(validator) - await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - let initialSupply = await blockReward.getTotalSupply() - let blockRewardAmount = await blockReward.getBlockRewardAmount() - let {logs} = await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled - logs.length.should.be.equal(1) - logs[0].event.should.be.equal('Rewarded') - let receivers = logs[0].args['receivers'] - let rewards = logs[0].args['rewards'] - receivers.length.should.be.equal(delegatorsCount + 1) - rewards.length.should.be.equal(receivers.length) - let expectedRewardForValidator = blockRewardAmount - let expectedRewardForDelegators = blockRewardAmount.mul(delegateAmount).div(minStakeAmount).mul(decimals.sub(validatorFee)).div(decimals) - receivers[0].should.be.equal(validator) - for (let i = 1; i <= delegatorsCount; i++) { - receivers[i].should.be.equal(accounts[i + 1]) - rewards[i].should.be.bignumber.equal(expectedRewardForDelegators) - expectedRewardForValidator = expectedRewardForValidator.sub(expectedRewardForDelegators) - } - rewards[0].should.be.bignumber.equal(expectedRewardForValidator) - }) - it('reward amount should update after BLOCKS_PER_YEAR and total yearly inflation should be calculated correctly', async () => { - await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - let decimals = await blockReward.DECIMALS() - let initialSupply = await blockReward.getTotalSupply() - let blocksPerYear = await blockReward.getBlocksPerYear() - let inflation = await blockReward.getInflation() - let blockRewardAmount = await blockReward.getBlockRewardAmount() - // console.log(`initialSupply: ${initialSupply.div(decimals).toNumber()}, blockRewardAmount: ${blockRewardAmount.div(decimals).toNumber()}`) - - // each of the following calls advances a block - let i = 0 - let blockNumber = await web3.eth.getBlockNumber() - while (blockNumber % BLOCKS_PER_YEAR !== 0) { - // console.log('block #', blockNumber) - await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled - blockNumber = await web3.eth.getBlockNumber() - i++ - } - // console.log('i', i) - - let totalSupply = await blockReward.getTotalSupply() - let newBlockRewardAmount = await blockReward.getBlockRewardAmount() - // console.log(`totalSupply: ${totalSupply.div(decimals).toNumber()}, newBlockRewardAmount: ${newBlockRewardAmount.div(decimals).toNumber()}`) - let expectedSupply = initialSupply - for (let j = 0; j < i; j++) { - expectedSupply = expectedSupply.add(blockRewardAmount) - } - // console.log(`expectedSupply: ${expectedSupply.div(decimals).toNumber()}`) - totalSupply.should.be.bignumber.equal(expectedSupply) - newBlockRewardAmount.should.be.bignumber.equal((totalSupply.mul(decimals).mul(inflation).div(toBN(100))).div(blocksPerYear).div(decimals)) - }) - }) + describe('#getBlockRewardAmountPerValidator', () => { + let blockRewardAmount + beforeEach(async () => { + blockRewardAmount = await blockReward.getBlockRewardAmount() + }) + it('block reward with one validator', async () => { + const minStakeAmount = await consensus.getMinStake() + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) - describe('emitRewardedOnCycle', function() { - beforeEach(async () => { - await blockReward.initialize(INITIAL_SUPPLY) - }) - it('should fail if not called by validator', async () => { - await blockReward.emitRewardedOnCycle({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) - }) - it('should be successful if `shouldEmitRewardedOnCycle` and `consensus.isFinalized` are true', async () => { - await blockReward.setShouldEmitRewardedOnCycleMock(false) - await consensus.setFinalizedMock(false) - await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) - - await blockReward.setShouldEmitRewardedOnCycleMock(true) - await consensus.setFinalizedMock(false) - await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) - - await blockReward.setShouldEmitRewardedOnCycleMock(false) - await consensus.setFinalizedMock(true) - await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) - - await blockReward.setShouldEmitRewardedOnCycleMock(true) - await consensus.setFinalizedMock(true) - await blockReward.emitRewardedOnCycle({from: owner}).should.be.fulfilled - }) - it('should be successful and emit event', async () => { - let BLOCKS_TO_REWARD = 10 - let blockRewardAmount = await blockReward.getBlockRewardAmount() - let expectedAmount = blockRewardAmount.mul(toBN(BLOCKS_TO_REWARD)) - - await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - for (let i = 0; i < BLOCKS_TO_REWARD; i++) { - await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled - } - - await blockReward.setShouldEmitRewardedOnCycleMock(true) - let {logs} = await blockReward.emitRewardedOnCycle({from: owner}).should.be.fulfilled - false.should.be.equal(await blockReward.shouldEmitRewardedOnCycle()) - logs.length.should.be.equal(1) - logs[0].event.should.be.equal('RewardedOnCycle') - logs[0].args['amount'].should.be.bignumber.equal(expectedAmount) - }) - }) + const validator = accounts[1] + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + const l = await consensus.currentValidatorsLength() + console.log(l.toString(10)) + console.log(blockRewardAmount.toString(10)) + '1'.should.be.equal(l.toString(10)) - describe('upgradeTo', async () => { - let blockRewardOldImplementation, blockRewardNew - let proxyStorageStub = accounts[3] - beforeEach(async () => { - blockReward = await BlockReward.new() - blockRewardOldImplementation = blockReward.address - proxy = await EternalStorageProxy.new(proxyStorage.address, blockReward.address) - blockReward = await BlockReward.at(proxy.address) - blockRewardNew = await BlockReward.new() - }) - it('should only be called by ProxyStorage', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(blockRewardNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) - let {logs} = await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - logs[0].event.should.be.equal('Upgraded') - await proxy.setProxyStorageMock(proxyStorage.address) - }) - it('should change implementation address', async () => { - blockRewardOldImplementation.should.be.equal(await proxy.getImplementation()) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - blockRewardNew.address.should.be.equal(await proxy.getImplementation()) - }) - it('should increment implementation version', async () => { - let blockRewardOldVersion = await proxy.getVersion() - let blockRewardNewVersion = blockRewardOldVersion.add(toBN(1)) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - blockRewardNewVersion.should.be.bignumber.equal(await proxy.getVersion()) - }) - it('should work after upgrade', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - blockRewardNew = await BlockReward.at(proxy.address) - false.should.be.equal(await blockRewardNew.isInitialized()) - await blockRewardNew.initialize(INITIAL_SUPPLY).should.be.fulfilled - true.should.be.equal(await blockRewardNew.isInitialized()) - }) - it('should use same proxyStorage after upgrade', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - blockRewardNew = await BlockReward.at(proxy.address) - proxyStorageStub.should.be.equal(await blockRewardNew.getProxyStorage()) - }) - it('should use same storage after upgrade', async () => { - await blockReward.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - blockRewardNew = await BlockReward.at(proxy.address) - RANDOM_ADDRESS.should.be.equal(await blockReward.getSystemAddress()) + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + const expectedReward = blockRewardAmount.div(toBN(10)) + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) + + it('block reward of one validator staking 100% of the total stake', async () => { + const minStakeAmount = await consensus.getMinStake() + await consensus.setTotalStakeAmountMock(minStakeAmount) + + const validator = accounts[1] + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + const l = await consensus.currentValidatorsLength() + console.log(l.toString(10)) + console.log(blockRewardAmount.toString(10)) + '1'.should.be.equal(l.toString(10)) + + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + const expectedReward = blockRewardAmount + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) + + it('block reward of 1 validator of 2, staking 10% of the total stake', async () => { + const minStakeAmount = await consensus.getMinStake() + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) + await consensus.setCurrentValidatorsLengthMock(toBN(2)) + const validator = accounts[1] + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + + const l = await consensus.currentValidatorsLength() + '2'.should.be.equal(l.toString(10)) + + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + + // expected reward calculation + const expectedReward = blockRewardAmount.div(toBN(10)).mul(toBN(2)) + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) + + it('block reward of 1 validator of 2, staking 50% of the total stake', async () => { + const minStakeAmount = await consensus.getMinStake() + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) + await consensus.setCurrentValidatorsLengthMock(toBN(2)) + const validator = accounts[1] + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + + const l = await consensus.currentValidatorsLength() + '2'.should.be.equal(l.toString(10)) + + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + + // expected reward calculation + const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) + + it('block reward does not changed if the propotion stays the same', async () => { + const minStakeAmount = await consensus.getMinStake() + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) + await consensus.setCurrentValidatorsLengthMock(toBN(2)) + const validator = accounts[1] + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + + const l = await consensus.currentValidatorsLength() + '2'.should.be.equal(l.toString(10)) + + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + + // total stake is 50 * minStakeAmount now + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(100))) + // validator stake is 50 * minStakeAmount now + await consensus.sendTransaction({ from: validator, value: minStakeAmount.mul(toBN(49)) }).should.be.fulfilled + + // expected reward calculation + const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) }) + + // it('can only be called by system address', async () => { + // await blockReward.reward([accounts[3]], [0]).should.be.rejectedWith(ERROR_MSG) + // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + // await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled + // }) + // it('should revert if input array contains more than one item', async () => { + // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + // await blockReward.reward([accounts[3], accounts[4]], [0, 0], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should revert if lengths of input arrays are not equal', async () => { + // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + // await blockReward.reward([accounts[3]], [0, 0], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should revert if "kind" parameter is not 0', async () => { + // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + // await blockReward.reward([accounts[3]], [1], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should give reward to validator and total supply should be updated', async () => { + // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + // let initialSupply = await blockReward.getTotalSupply() + // let blockRewardAmount = await blockReward.getBlockRewardAmount() + // let {logs} = await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled + // logs.length.should.be.equal(1) + // logs[0].event.should.be.equal('Rewarded') + // logs[0].args['receivers'].should.deep.equal([accounts[3]]) + // logs[0].args['rewards'][0].should.be.bignumber.equal(blockRewardAmount) + // let expectedSupply = initialSupply.add(blockRewardAmount) + // expectedSupply.should.be.bignumber.equal(await blockReward.getTotalSupply()) + // }) + // it('should give rewards to validator and its delegators', async () => { + // let decimals = await consensus.DECIMALS() + // let minStakeAmount = await consensus.getMinStake() + // let delegatorsCount = accounts.length - 2 + // let delegateAmountValue = parseInt(minStakeAmount.div(decimals).toNumber() * 0.99 / delegatorsCount) + // let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') + // let stakeAmountValue = minStakeAmount.div(decimals).toNumber() - delegateAmountValue * delegatorsCount + // let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') + // let fee = 5 + // let validator = accounts[1] + // await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled + // for (let i = 2; i < accounts.length; i++) { + // await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled + // } + // await consensus.setValidatorFeeMock(fee, {from: validator}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(validator) + // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + // let initialSupply = await blockReward.getTotalSupply() + // let blockRewardAmount = await blockReward.getBlockRewardAmount() + // let {logs} = await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled + // logs.length.should.be.equal(1) + // logs[0].event.should.be.equal('Rewarded') + // let receivers = logs[0].args['receivers'] + // let rewards = logs[0].args['rewards'] + // receivers.length.should.be.equal(delegatorsCount + 1) + // rewards.length.should.be.equal(receivers.length) + // let expectedRewardForValidator = blockRewardAmount + // let expectedRewardForDelegators = blockRewardAmount.mul(delegateAmount).div(minStakeAmount).mul(decimals.sub(validatorFee)).div(decimals) + // receivers[0].should.be.equal(validator) + // for (let i = 1; i <= delegatorsCount; i++) { + // receivers[i].should.be.equal(accounts[i + 1]) + // rewards[i].should.be.bignumber.equal(expectedRewardForDelegators) + // expectedRewardForValidator = expectedRewardForValidator.sub(expectedRewardForDelegators) + // } + // rewards[0].should.be.bignumber.equal(expectedRewardForValidator) + // }) + // it('reward amount should update after BLOCKS_PER_YEAR and total yearly inflation should be calculated correctly', async () => { + // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + + // let decimals = await blockReward.DECIMALS() + // let initialSupply = await blockReward.getTotalSupply() + // let blocksPerYear = await blockReward.getBlocksPerYear() + // let inflation = await blockReward.getInflation() + // let blockRewardAmount = await blockReward.getBlockRewardAmount() + // // console.log(`initialSupply: ${initialSupply.div(decimals).toNumber()}, blockRewardAmount: ${blockRewardAmount.div(decimals).toNumber()}`) + + // // each of the following calls advances a block + // let i = 0 + // let blockNumber = await web3.eth.getBlockNumber() + // while (blockNumber % BLOCKS_PER_YEAR !== 0) { + // // console.log('block #', blockNumber) + // await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled + // blockNumber = await web3.eth.getBlockNumber() + // i++ + // } + // // console.log('i', i) + + // let totalSupply = await blockReward.getTotalSupply() + // let newBlockRewardAmount = await blockReward.getBlockRewardAmount() + // // console.log(`totalSupply: ${totalSupply.div(decimals).toNumber()}, newBlockRewardAmount: ${newBlockRewardAmount.div(decimals).toNumber()}`) + // let expectedSupply = initialSupply + // for (let j = 0; j < i; j++) { + // expectedSupply = expectedSupply.add(blockRewardAmount) + // } + // // console.log(`expectedSupply: ${expectedSupply.div(decimals).toNumber()}`) + // totalSupply.should.be.bignumber.equal(expectedSupply) + // newBlockRewardAmount.should.be.bignumber.equal((totalSupply.mul(decimals).mul(inflation).div(toBN(100))).div(blocksPerYear).div(decimals)) + // }) }) + + // describe('emitRewardedOnCycle', function() { + // beforeEach(async () => { + // await blockReward.initialize(INITIAL_SUPPLY) + // }) + // it('should fail if not called by validator', async () => { + // await blockReward.emitRewardedOnCycle({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should be successful if `shouldEmitRewardedOnCycle` and `consensus.isFinalized` are true', async () => { + // await blockReward.setShouldEmitRewardedOnCycleMock(false) + // await consensus.setFinalizedMock(false) + // await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) + + // await blockReward.setShouldEmitRewardedOnCycleMock(true) + // await consensus.setFinalizedMock(false) + // await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) + + // await blockReward.setShouldEmitRewardedOnCycleMock(false) + // await consensus.setFinalizedMock(true) + // await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) + + // await blockReward.setShouldEmitRewardedOnCycleMock(true) + // await consensus.setFinalizedMock(true) + // await blockReward.emitRewardedOnCycle({from: owner}).should.be.fulfilled + // }) + // it('should be successful and emit event', async () => { + // let BLOCKS_TO_REWARD = 10 + // let blockRewardAmount = await blockReward.getBlockRewardAmount() + // let expectedAmount = blockRewardAmount.mul(toBN(BLOCKS_TO_REWARD)) + + // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + // for (let i = 0; i < BLOCKS_TO_REWARD; i++) { + // await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled + // } + + // await blockReward.setShouldEmitRewardedOnCycleMock(true) + // let {logs} = await blockReward.emitRewardedOnCycle({from: owner}).should.be.fulfilled + // false.should.be.equal(await blockReward.shouldEmitRewardedOnCycle()) + // logs.length.should.be.equal(1) + // logs[0].event.should.be.equal('RewardedOnCycle') + // logs[0].args['amount'].should.be.bignumber.equal(expectedAmount) + // }) + // }) + + // describe('upgradeTo', async () => { + // let blockRewardOldImplementation, blockRewardNew + // let proxyStorageStub = accounts[3] + // beforeEach(async () => { + // blockReward = await BlockReward.new() + // blockRewardOldImplementation = blockReward.address + // proxy = await EternalStorageProxy.new(proxyStorage.address, blockReward.address) + // blockReward = await BlockReward.at(proxy.address) + // blockRewardNew = await BlockReward.new() + // }) + // it('should only be called by ProxyStorage', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(blockRewardNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) + // let {logs} = await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + // logs[0].event.should.be.equal('Upgraded') + // await proxy.setProxyStorageMock(proxyStorage.address) + // }) + // it('should change implementation address', async () => { + // blockRewardOldImplementation.should.be.equal(await proxy.getImplementation()) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // blockRewardNew.address.should.be.equal(await proxy.getImplementation()) + // }) + // it('should increment implementation version', async () => { + // let blockRewardOldVersion = await proxy.getVersion() + // let blockRewardNewVersion = blockRewardOldVersion.add(toBN(1)) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // blockRewardNewVersion.should.be.bignumber.equal(await proxy.getVersion()) + // }) + // it('should work after upgrade', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // blockRewardNew = await BlockReward.at(proxy.address) + // false.should.be.equal(await blockRewardNew.isInitialized()) + // await blockRewardNew.initialize(INITIAL_SUPPLY).should.be.fulfilled + // true.should.be.equal(await blockRewardNew.isInitialized()) + // }) + // it('should use same proxyStorage after upgrade', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + // blockRewardNew = await BlockReward.at(proxy.address) + // proxyStorageStub.should.be.equal(await blockRewardNew.getProxyStorage()) + // }) + // it('should use same storage after upgrade', async () => { + // await blockReward.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + // blockRewardNew = await BlockReward.at(proxy.address) + // RANDOM_ADDRESS.should.be.equal(await blockReward.getSystemAddress()) + // }) + // }) }) From 7df013a00911af9d0d1dd66904b3ff266ed3b459 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Tue, 11 Aug 2020 20:44:19 +0300 Subject: [PATCH 04/19] save --- contracts/Consensus.sol | 28 +- contracts/ConsensusUtils.sol | 67 +- test/consensus.test.js | 1964 ++++++++++++++++++---------------- 3 files changed, 1085 insertions(+), 974 deletions(-) diff --git a/contracts/Consensus.sol b/contracts/Consensus.sol index afcf1a4..f8e18e3 100644 --- a/contracts/Consensus.sol +++ b/contracts/Consensus.sol @@ -108,22 +108,22 @@ contract Consensus is ConsensusUtils { * @dev Function to be called by the block reward contract each block to handle cycles and snapshots logic */ function cycle() external onlyBlockReward { - if (_shouldTakeSnapshot()) { - uint256 snapshotId = getNextSnapshotId(); - if (snapshotId == getSnapshotsPerCycle().sub(1)) { - _setNextSnapshotId(0); - } else { - _setNextSnapshotId(snapshotId.add(1)); - } - _setSnapshot(snapshotId, pendingValidators()); - _setLastSnapshotTakenAtBlock(block.number); - delete snapshotId; - } + // if (_shouldTakeSnapshot()) { + // uint256 snapshotId = getNextSnapshotId(); + // if (snapshotId == getSnapshotsPerCycle().sub(1)) { + // _setNextSnapshotId(0); + // } else { + // _setNextSnapshotId(snapshotId.add(1)); + // } + // _setSnapshot(snapshotId, pendingValidators()); + // _setLastSnapshotTakenAtBlock(block.number); + // delete snapshotId; + // } if (_hasCycleEnded()) { IVoting(ProxyStorage(getProxyStorage()).getVoting()).onCycleEnd(currentValidators()); _setCurrentCycle(); - uint256 randomSnapshotId = _getRandom(0, getSnapshotsPerCycle() - 1); - address[] memory newSet = getSnapshotAddresses(randomSnapshotId); + // uint256 randomSnapshotId = _getRandom(0, getSnapshotsPerCycle() - 1); + address[] memory newSet = pendingValidators(); if (newSet.length > 0) { _setNewValidatorSet(newSet); } @@ -132,7 +132,7 @@ contract Consensus is ConsensusUtils { _setShouldEmitInitiateChange(true); emit ShouldEmitInitiateChange(); } - delete randomSnapshotId; + // delete randomSnapshotId; IBlockReward(ProxyStorage(getProxyStorage()).getBlockReward()).onCycleEnd(); } } diff --git a/contracts/ConsensusUtils.sol b/contracts/ConsensusUtils.sol index 45bbc7e..a5ba926 100644 --- a/contracts/ConsensusUtils.sol +++ b/contracts/ConsensusUtils.sol @@ -91,15 +91,33 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { require(_validator != address(0)); // overstaking should not be possible - require (stakeAmount(_validator) < getMinStake()); - require (stakeAmount(_validator).add(_amount) <= getMinStake()); - - _delegatedAmountAdd(_staker, _validator, _amount); - _stakeAmountAdd(_validator, _amount); - - if (stakeAmount(_validator) >= getMinStake() && !isPendingValidator(_validator)) { - _pendingValidatorsAdd(_validator); + // require (stakeAmount(_validator) < getMinStake()); + // require (stakeAmount(_validator).add(_amount) <= getMinStake()); + + // _stakeAmountAdd(_validator, _amount); + uint256 currentAmount = stakeAmount(_validator); + uint256 addedAmount = currentAmount.add(currentAmount); + if (addedAmount < getMinStake()) { + _delegatedAmountAdd(_staker, _validator, _amount); + _stakeAmountAdd(_validator, _amount); + return; + } + if (currentAmount > getMinStake()) { + // get index of the validator + // find the validator to move + // updating the validator + } else { + for (uint256 i; i < pendingValidatorsLength(); i++) { + address validatorAddress = pendingValidatorsAtPosition(i) + if (addedAmount > stakeAmount(validatorAddress)) { + // put validator in place i and move the rest + } + } + // adding validator as a new one } + // if (stakeAmount(_validator) >= getMinStake() && !isPendingValidator(_validator)) { + // _pendingValidatorsAdd(_validator); + // } } function _setSystemAddress(address _newAddress) internal { @@ -270,11 +288,44 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { addressArrayStorage[PENDING_VALIDATORS][_p] = _address; } + function _findPosition(address _address) internal { + uint256 stake = stakeAmount(_address); + if (stake == 0) { + uint256 l = pendingValidatorsLength(); + uint256 i = 0; + while (i < l) { + address va = pendingValidatorsAtPosition(i); + uint256 sa = stakeAmount(va); + if (stake > sa) { + + } else { + i++; + } + } + } + } + function _pendingValidatorsAdd(address _address) internal { + uint256 l = pendingValidatorsLength(); + uint256 i = 1; + while (i < l) { + uint256 j = i; + while (j > 0 && stakeAmount(pendingValidatorsAtPosition(j - 1)) > stakeAmount(pendingValidatorsAtPosition(j))) { + _pendingValidatorsSwap(j, i); + j = j - 1; + } + i = i + 1; + } addressArrayStorage[PENDING_VALIDATORS].push(_address); _setValidatorFee(_address, DEFAULT_VALIDATOR_FEE); } + function _pendingValidatorsSwap(uint256 _firstPosition, uint256 _secondPosition) { + address x = pendingValidatorsAtPosition(_secondPosition); + _setPendingValidatorsAtPosition(_secondPosition, pendingValidatorsAtPosition(_firstPosition)); + _setPendingValidatorsAtPosition(_firstPosition, x); + } + function _pendingValidatorsRemove(address _address) internal { bool found = false; uint256 removeIndex; diff --git a/test/consensus.test.js b/test/consensus.test.js index ca4faa0..4c93034 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -1,3 +1,4 @@ +/* eslint-disable prefer-const */ const Consensus = artifacts.require('ConsensusMock.sol') const ProxyStorage = artifacts.require('ProxyStorageMock.sol') const EternalStorageProxy = artifacts.require('EternalStorageProxyMock.sol') @@ -11,13 +12,14 @@ const MIN_STAKE_AMOUNT = 10000 const MULTIPLY_AMOUNT = 3 const MIN_STAKE = toWei(toBN(MIN_STAKE_AMOUNT), 'ether') const ONE_ETHER = toWei(toBN(1), 'ether') +const TWO_ETHER = toWei(toBN(2), 'ether') const LESS_THAN_MIN_STAKE = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') const MORE_THAN_MIN_STAKE = toWei(toBN(MIN_STAKE_AMOUNT + 1), 'ether') const CYCLE_DURATION_BLOCKS = 120 const SNAPSHOTS_PER_CYCLE = 10 contract('Consensus', async (accounts) => { - let consensusImpl, proxy, consensus, blockReward, blockRewardAmount, decimals + let consensusImpl, proxy, proxyStorageImpl, proxyStorage, consensus, blockReward, blockRewardAmount, decimals, pendingValidators let owner = accounts[0] let nonOwner = accounts[1] let initialValidator = accounts[0] @@ -60,469 +62,526 @@ contract('Consensus', async (accounts) => { }) describe('initialize', async () => { - it('default values', async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - owner.should.equal(await proxy.getOwner()) - toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await consensus.getSystemAddress())) - true.should.be.equal(await consensus.isFinalized()) - MIN_STAKE.should.be.bignumber.equal(await consensus.getMinStake()) - toBN(MAX_VALIDATORS).should.be.bignumber.equal(await consensus.getMaxValidators()) - toBN(CYCLE_DURATION_BLOCKS).should.be.bignumber.equal(await consensus.getCycleDurationBlocks()) - toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) - toBN(CYCLE_DURATION_BLOCKS / SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getBlocksToSnapshot()) - false.should.be.equal(await consensus.hasCycleEnded()) - toBN(0).should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) - toBN(0).should.be.bignumber.equal(await consensus.getNextSnapshotId()) - let validators = await consensus.getValidators() - validators.length.should.be.equal(1) - validators[0].should.be.equal(initialValidator) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - }) - it('initial validator address not defined - owner should be initial validator', async () => { - await consensus.initialize(ZERO_ADDRESS) - await consensus.setProxyStorage(proxyStorage.address) - let validators = await consensus.getValidators() - validators.length.should.be.equal(1) - validators[0].should.be.equal(owner) - }) - it('initial validator address defined', async () => { - await consensus.initialize(initialValidator) - let validators = await consensus.getValidators() - validators.length.should.be.equal(1) - validators[0].should.be.equal(initialValidator) - }) + // it('default values', async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // owner.should.equal(await proxy.getOwner()) + // toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await consensus.getSystemAddress())) + // true.should.be.equal(await consensus.isFinalized()) + // MIN_STAKE.should.be.bignumber.equal(await consensus.getMinStake()) + // toBN(MAX_VALIDATORS).should.be.bignumber.equal(await consensus.getMaxValidators()) + // toBN(CYCLE_DURATION_BLOCKS).should.be.bignumber.equal(await consensus.getCycleDurationBlocks()) + // toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) + // toBN(CYCLE_DURATION_BLOCKS / SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getBlocksToSnapshot()) + // false.should.be.equal(await consensus.hasCycleEnded()) + // toBN(0).should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) + // toBN(0).should.be.bignumber.equal(await consensus.getNextSnapshotId()) + // let validators = await consensus.getValidators() + // validators.length.should.be.equal(1) + // validators[0].should.be.equal(initialValidator) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // }) + // it('initial validator address not defined - owner should be initial validator', async () => { + // await consensus.initialize(ZERO_ADDRESS) + // await consensus.setProxyStorage(proxyStorage.address) + // let validators = await consensus.getValidators() + // validators.length.should.be.equal(1) + // validators[0].should.be.equal(owner) + // }) + // it('initial validator address defined', async () => { + // await consensus.initialize(initialValidator) + // let validators = await consensus.getValidators() + // validators.length.should.be.equal(1) + // validators[0].should.be.equal(initialValidator) + // }) }) describe('setProxyStorage', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - }) - it('setProxyStorage should fail if no address', async () => { - await consensus.setProxyStorage(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG) - }) - it('setProxyStorage should fail if not called by owner', async () => { - await consensus.setProxyStorage(proxyStorage.address, {from: nonOwner}).should.be.rejectedWith(ERROR_MSG) - // success - await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) - // should not be able to set again if already set - await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) - }) - it('setProxyStorage successfully', async () => { - await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) - }) - it('setProxyStorage should not be able to set again if already set', async () => { - await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) - }) + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // }) + // it('setProxyStorage should fail if no address', async () => { + // await consensus.setProxyStorage(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG) + // }) + // it('setProxyStorage should fail if not called by owner', async () => { + // await consensus.setProxyStorage(proxyStorage.address, {from: nonOwner}).should.be.rejectedWith(ERROR_MSG) + // // success + // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + // proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) + // // should not be able to set again if already set + // await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) + // }) + // it('setProxyStorage successfully', async () => { + // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + // proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) + // }) + // it('setProxyStorage should not be able to set again if already set', async () => { + // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + // await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) + // }) }) describe('emitInitiateChange', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - await consensus.setFinalizedMock(false) - }) - it('should fail if not called by validator', async () => { - await consensus.emitInitiateChange({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) - }) - it('should fail if newValidatorSet is empty', async () => { - await consensus.setShouldEmitInitiateChangeMock(true) - await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - }) - it('should fail if `shouldEmitInitiateChange` is false', async () => { - let mockSet = [firstCandidate, secondCandidate] - await consensus.setNewValidatorSetMock(mockSet) - await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - }) - it('should be successful and emit event', async () => { - await consensus.setShouldEmitInitiateChangeMock(true) - let mockSet = [firstCandidate, secondCandidate] - await consensus.setNewValidatorSetMock(mockSet) - let {logs} = await consensus.emitInitiateChange({from: initialValidator}).should.be.fulfilled - false.should.be.equal(await consensus.shouldEmitInitiateChange()) - logs.length.should.be.equal(1) - logs[0].event.should.be.equal('InitiateChange') - logs[0].args['newSet'].should.deep.equal(mockSet) - }) + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // await consensus.setFinalizedMock(false) + // }) + // it('should fail if not called by validator', async () => { + // await consensus.emitInitiateChange({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should fail if newValidatorSet is empty', async () => { + // await consensus.setShouldEmitInitiateChangeMock(true) + // await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should fail if `shouldEmitInitiateChange` is false', async () => { + // let mockSet = [firstCandidate, secondCandidate] + // await consensus.setNewValidatorSetMock(mockSet) + // await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should be successful and emit event', async () => { + // await consensus.setShouldEmitInitiateChangeMock(true) + // let mockSet = [firstCandidate, secondCandidate] + // await consensus.setNewValidatorSetMock(mockSet) + // let {logs} = await consensus.emitInitiateChange({from: initialValidator}).should.be.fulfilled + // false.should.be.equal(await consensus.shouldEmitInitiateChange()) + // logs.length.should.be.equal(1) + // logs[0].event.should.be.equal('InitiateChange') + // logs[0].args['newSet'].should.deep.equal(mockSet) + // }) }) describe('finalizeChange', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - await consensus.setFinalizedMock(false) - }) - it('should only be called by SYSTEM_ADDRESS', async () => { - await consensus.finalizeChange().should.be.rejectedWith(ERROR_MSG) - await consensus.setSystemAddressMock(accounts[0], {from: owner}) - await consensus.finalizeChange().should.be.fulfilled - }) - it('should set finalized to true', async () => { - false.should.be.equal(await consensus.isFinalized()) - await consensus.setSystemAddressMock(accounts[0]) - await consensus.finalizeChange().should.be.fulfilled - true.should.be.equal(await consensus.isFinalized()) - }) - it('should not update current validators set if new set is empty', async () => { - let initialValidators = await consensus.getValidators() - let mockSet = [] - await consensus.setNewValidatorSetMock(mockSet) - await consensus.setSystemAddressMock(accounts[0]) - let {logs} = await consensus.finalizeChange().should.be.fulfilled - let currentValidators = await consensus.getValidators() - currentValidators.length.should.be.equal(1) - currentValidators.should.deep.equal(initialValidators) - logs.length.should.be.equal(0) - }) - it('should update current validators set', async () => { - let mockSet = [firstCandidate, secondCandidate] - await consensus.setNewValidatorSetMock(mockSet) - await consensus.setSystemAddressMock(accounts[0]) - let {logs} = await consensus.finalizeChange().should.be.fulfilled - let currentValidators = await consensus.getValidators() - currentValidators.length.should.be.equal(2) - currentValidators.should.deep.equal(mockSet) - logs[0].event.should.be.equal('ChangeFinalized') - logs[0].args['newSet'].should.deep.equal(mockSet) - }) + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // await consensus.setFinalizedMock(false) + // }) + // it('should only be called by SYSTEM_ADDRESS', async () => { + // await consensus.finalizeChange().should.be.rejectedWith(ERROR_MSG) + // await consensus.setSystemAddressMock(accounts[0], {from: owner}) + // await consensus.finalizeChange().should.be.fulfilled + // }) + // it('should set finalized to true', async () => { + // false.should.be.equal(await consensus.isFinalized()) + // await consensus.setSystemAddressMock(accounts[0]) + // await consensus.finalizeChange().should.be.fulfilled + // true.should.be.equal(await consensus.isFinalized()) + // }) + // it('should not update current validators set if new set is empty', async () => { + // let initialValidators = await consensus.getValidators() + // let mockSet = [] + // await consensus.setNewValidatorSetMock(mockSet) + // await consensus.setSystemAddressMock(accounts[0]) + // let {logs} = await consensus.finalizeChange().should.be.fulfilled + // let currentValidators = await consensus.getValidators() + // currentValidators.length.should.be.equal(1) + // currentValidators.should.deep.equal(initialValidators) + // logs.length.should.be.equal(0) + // }) + // it('should update current validators set', async () => { + // let mockSet = [firstCandidate, secondCandidate] + // await consensus.setNewValidatorSetMock(mockSet) + // await consensus.setSystemAddressMock(accounts[0]) + // let {logs} = await consensus.finalizeChange().should.be.fulfilled + // let currentValidators = await consensus.getValidators() + // currentValidators.length.should.be.equal(2) + // currentValidators.should.deep.equal(mockSet) + // logs[0].event.should.be.equal('ChangeFinalized') + // logs[0].args['newSet'].should.deep.equal(mockSet) + // }) }) describe('stake (fallback function)', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - }) - describe('basic', async () => { - it('should not allow zero stake', async () => { - await consensus.send(0, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) - }) - it('less than minimum stake - should not be added to pending validators', async () => { - await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // contract balance should be updated - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // sender stake amount should be updated - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // pending validators should not be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - // validator fee should not be set - toBN(0).should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - }) - it('minimum stake amount', async () => { - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) - // default validator fee should be set - let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - }) - it('should not allow more than minimum stake', async () => { - await consensus.sendTransaction({from: firstCandidate, value: MORE_THAN_MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) - }) - }) - describe('advanced', async () => { - it('minimum stake amount, in more than one transaction', async () => { - // 1st stake - await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // }) + // describe('basic', async () => { + // it('should not allow zero stake', async () => { + // await consensus.send(0, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('less than minimum stake - should not be added to pending validators', async () => { + // await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // // contract balance should be updated + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // // sender stake amount should be updated + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // // pending validators should not be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // validator fee should not be set + // toBN(0).should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + // }) + // it('minimum stake amount', async () => { + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(firstCandidate) + // // default validator fee should be set + // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + // }) + // it('should allow more than minimum stake', async () => { + // await consensus.sendTransaction({from: firstCandidate, value: MORE_THAN_MIN_STAKE}).should.be.fulfilled + // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(firstCandidate) + // // default validator fee should be set + // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + // }) + // }) + // describe('advanced', async () => { + // it('minimum stake amount, in more than one transaction', async () => { + // // 1st stake + // await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) - // 2nd stake - await consensus.sendTransaction({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) - }) - it('more than one validator', async () => { - // add 1st validator - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - // add 2nd validator - await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(2) - }) - it('multiple validators, multiple times', async () => { - let expectedValidators = [] - // add 1st validator - expectedValidators.push(firstCandidate) - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(expectedValidators.length) - pendingValidators.should.deep.equal(expectedValidators) - // add 2nd validator - expectedValidators.push(secondCandidate) - await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(expectedValidators.length) - pendingValidators.should.deep.equal(expectedValidators) - // try to add 1st validator one more time - should reject - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) - // try to add 2nd validator one more time - should reject - await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) - }) - }) + // // 2nd stake + // await consensus.sendTransaction({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(firstCandidate) + // }) + + // it('more than minimum stake amount, in more than one transaction', async () => { + // // 1st stake + // await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + + // // 2nd stake + // await consensus.sendTransaction({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled + // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(firstCandidate) + // }) + + // it('more than one validator', async () => { + // // add 1st validator + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // // add 2nd validator + // await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(2) + // }) + // it('multiple validators, multiple times', async () => { + // const expectedValidators = [] + // // add 1st validator + // expectedValidators.push(firstCandidate) + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // // add 2nd validator + // expectedValidators.push(secondCandidate) + // await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + + // // doubling the stake for the 1st validator + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + + // // doubling the stake for the 2st validator + // await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + // }) + // }) }) describe('stake', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - }) - describe('basic', async () => { - it('should not allow zero stake', async () => { - await consensus.stake({from: firstCandidate, value: 0}).should.be.rejectedWith(ERROR_MSG) - }) - it('less than minimum stake - should not be added to pending validators', async () => { - await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // contract balance should be updated - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // sender stake amount should be updated - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // pending validators should not be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - }) - it('minimum stake amount', async () => { - await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) - }) - it('should not allow more than minimum stake', async () => { - await consensus.stake({from: firstCandidate, value: MORE_THAN_MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) - }) - }) - describe('advanced', async () => { - it('minimum stake amount, in more than one transaction', async () => { - // 1st stake - await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // }) + // describe('basic', async () => { + // it('should not allow zero stake', async () => { + // await consensus.stake({from: firstCandidate, value: 0}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('less than minimum stake - should not be added to pending validators', async () => { + // await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // // contract balance should be updated + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // // sender stake amount should be updated + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // // pending validators should not be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // }) + // it('minimum stake amount', async () => { + // await consensus.stake({ from: firstCandidate, value: MIN_STAKE }).should.be.fulfilled + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(firstCandidate) + // }) - // 2nd stake - await consensus.stake({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) - }) - it('more than one validator', async () => { - // add 1st validator - await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - // add 2nd validator - await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(2) - }) - it('multiple times according to staked amount, in more than one transaction', async () => { - // 1st stake - await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) + // it('should allow more than minimum stake', async () => { + // await consensus.stake({ from: firstCandidate, value: MORE_THAN_MIN_STAKE }).should.be.fulfilled - // 2nd stake - added once - let expectedValidators = [firstCandidate] - await consensus.stake({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) + // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(firstCandidate) + // // default validator fee should be set + // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + // }) + // }) + // describe('advanced', async () => { + // it('minimum stake amount, in more than one transaction', async () => { + // // 1st stake + // await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) - // 3rd stake - should be rejected - await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) - }) - it('multiple validators, multiple times', async () => { - let expectedValidators = [] - // add 1st validator - expectedValidators.push(firstCandidate) - await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(expectedValidators.length) - pendingValidators.should.deep.equal(expectedValidators) - // add 2nd validator - expectedValidators.push(secondCandidate) - await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(expectedValidators.length) - pendingValidators.should.deep.equal(expectedValidators) - // try to add 1st validator one more time - should reject - await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) - // try to add 2nd validator one more time - should reject - await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) - }) - }) + // // 2nd stake + // await consensus.stake({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(firstCandidate) + // }) + + // it('more than minimum stake amount, in more than one transaction', async () => { + // // 1st stake + // await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + + // // 2nd stake + // await consensus.stake({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled + // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(firstCandidate) + // }) + + // it('more than one validator', async () => { + // // add 1st validator + // await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // // add 2nd validator + // await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(2) + // }) + + // it('multiple validators, multiple times', async () => { + // let expectedValidators = [] + // // add 1st validator + // expectedValidators.push(firstCandidate) + // await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // // add 2nd validator + // expectedValidators.push(secondCandidate) + // await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + + // // doubling the stake for the 1st validator + // await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + + // // doubling the stake for the 2st validator + // await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + // }) + // }) }) describe('delegate', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - }) - describe('basic', async () => { - it('should not allow zero stake', async () => { - await consensus.delegate(firstCandidate, {from: firstDelegator, value: 0}).should.be.rejectedWith(ERROR_MSG) - }) - it('should fail if no staker address', async () => { - await consensus.delegate(ZERO_ADDRESS, {from: firstDelegator, value: MORE_THAN_MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) - }) - it('less than minimum stake - should not be added to pending validators', async () => { - await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // contract balance should be updated - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // sender stake amount should be updated - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // delegated amount should be updated - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - // pending validators should not be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - // delegators list should be updated - let delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - }) - it('minimum stake', async () => { - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - // contract balance should be updated - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // sender stake amount should be updated - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // delegated amount should be updated - MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - // pending validators should be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) - // delegators list should be updated - let delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - }) - }) - describe('advanced', async () => { - it('minimum stake amount, in more than one transaction', async () => { - // 1st stake - await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - let delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // }) + // describe('basic', async () => { + // it('should not allow zero stake', async () => { + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: 0}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should fail if no staker address', async () => { + // await consensus.delegate(ZERO_ADDRESS, {from: firstDelegator, value: MORE_THAN_MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('less than minimum stake - should not be added to pending validators', async () => { + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // // contract balance should be updated + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // // sender stake amount should be updated + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // // delegated amount should be updated + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // // pending validators should not be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // delegators list should be updated + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // }) + // it('minimum stake', async () => { + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + // // contract balance should be updated + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // // sender stake amount should be updated + // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // // delegated amount should be updated + // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // // pending validators should be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(firstCandidate) + // // delegators list should be updated + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // }) + // }) + // describe('advanced', async () => { + // it('minimum stake amount, in more than one transaction', async () => { + // // 1st stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // 2nd stake - await consensus.delegate(firstCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) - delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - }) - it('more than one validator', async () => { - // add 1st validator - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - // delegators list should be updated - let delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // add 2nd validator - await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(2) - // delegators list should be updated - delegators = await consensus.delegators(secondCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - delegatorsLength = await consensus.delegatorsLength(secondCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) - }) - it('multiple times according to staked amount, in more than one transaction', async () => { - // 1st stake - await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - let delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // // 2nd stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(firstCandidate) + // delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // }) + // it('more than one validator', async () => { + // // add 1st validator + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // // delegators list should be updated + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // // add 2nd validator + // await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(2) + // // delegators list should be updated + // delegators = await consensus.delegators(secondCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(secondCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) + // }) + // it('multiple times according to staked amount, in more than one transaction', async () => { + // // 1st stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // 2nd stake - added once - let expectedValidators = [firstCandidate] - await consensus.delegate(firstCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) - delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // // 2nd stake - added once + // let expectedValidators = [firstCandidate] + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(firstCandidate) + // delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) - delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - }) - }) + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + // delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // }) + // }) }) describe('cycles and snapshots', async () => { @@ -535,7 +594,8 @@ contract('Consensus', async (accounts) => { let currentBlockNumber = await web3.eth.getBlockNumber() let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() let blocksToAdvance = currentCycleEndBlock.toNumber() - currentBlockNumber - await advanceBlocks(blocksToAdvance - 1) + console.log({ currentBlockNumber, currentCycleEndBlock: currentCycleEndBlock.toNumber(), blocksToAdvance }) + await advanceBlocks(blocksToAdvance) true.should.be.equal(await consensus.hasCycleEnded()) }) it('shouldTakeSnapshot', async () => { @@ -583,529 +643,529 @@ contract('Consensus', async (accounts) => { }) expectedValidators.length.should.be.equal(0) }) - it('snapshot with exactly MAX_VALIDATORS validators - entire set should be saved', async () => { - let expectedValidators = [] - for (let i = 1; i <= MAX_VALIDATORS; i++) { - await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - expectedValidators.push(accounts[i-1]) - } - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(expectedValidators.length) - pendingValidators.should.deep.equal(expectedValidators) - let blocksToSnapshot = await consensus.getBlocksToSnapshot() - let snapshotId = await consensus.getNextSnapshotId() - await advanceBlocks(blocksToSnapshot) - await proxyStorage.setBlockRewardMock(owner) - await consensus.cycle().should.be.fulfilled - let snapshot = await consensus.getSnapshotAddresses(snapshotId) - snapshot.length.should.be.equal(expectedValidators.length) - snapshot.forEach(address => { - expectedValidators.splice(expectedValidators.indexOf(address), 1) - }) - expectedValidators.length.should.be.equal(0) - }) - it('snapshot with more validators than MAX_VALIDATORS - random set should be saved', async () => { - let expectedValidators = [] - for (let i = 1; i <= MAX_VALIDATORS + 1; i++) { - await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - expectedValidators.push(accounts[i-1]) - } - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(expectedValidators.length) - pendingValidators.should.deep.equal(expectedValidators) - let blocksToSnapshot = await consensus.getBlocksToSnapshot() - let snapshotId = await consensus.getNextSnapshotId() - await advanceBlocks(blocksToSnapshot) - await proxyStorage.setBlockRewardMock(owner) - await consensus.cycle().should.be.fulfilled - let snapshot = await consensus.getSnapshotAddresses(snapshotId) - snapshot.length.should.be.equal(MAX_VALIDATORS) - snapshot.forEach(address => { - expectedValidators.splice(expectedValidators.indexOf(address), 1) - }) - expectedValidators.length.should.be.equal(pendingValidators.length - MAX_VALIDATORS) - }) + // it('snapshot with exactly MAX_VALIDATORS validators - entire set should be saved', async () => { + // let expectedValidators = [] + // for (let i = 1; i <= MAX_VALIDATORS; i++) { + // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled + // expectedValidators.push(accounts[i-1]) + // } + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // let snapshotId = await consensus.getNextSnapshotId() + // await advanceBlocks(blocksToSnapshot) + // await proxyStorage.setBlockRewardMock(owner) + // await consensus.cycle().should.be.fulfilled + // let snapshot = await consensus.getSnapshotAddresses(snapshotId) + // snapshot.length.should.be.equal(expectedValidators.length) + // snapshot.forEach(address => { + // expectedValidators.splice(expectedValidators.indexOf(address), 1) + // }) + // expectedValidators.length.should.be.equal(0) + // }) + // it('snapshot with more validators than MAX_VALIDATORS - random set should be saved', async () => { + // let expectedValidators = [] + // for (let i = 1; i <= MAX_VALIDATORS + 1; i++) { + // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled + // expectedValidators.push(accounts[i-1]) + // } + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // let snapshotId = await consensus.getNextSnapshotId() + // await advanceBlocks(blocksToSnapshot) + // await proxyStorage.setBlockRewardMock(owner) + // await consensus.cycle().should.be.fulfilled + // let snapshot = await consensus.getSnapshotAddresses(snapshotId) + // snapshot.length.should.be.equal(MAX_VALIDATORS) + // snapshot.forEach(address => { + // expectedValidators.splice(expectedValidators.indexOf(address), 1) + // }) + // expectedValidators.length.should.be.equal(pendingValidators.length - MAX_VALIDATORS) + // }) }) describe('withdraw', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - }) - describe('stakers', async () => { - it('cannot withdraw zero', async () => { - await consensus.methods['withdraw(uint256)'](ZERO_AMOUNT, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) - }) - it('cannot withdraw more than staked amount', async () => { - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - await consensus.methods['withdraw(uint256)'](MORE_THAN_MIN_STAKE).should.be.rejectedWith(ERROR_MSG) - }) - it('can withdraw all staked amount', async () => { - // stake - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // stake - await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}) - // withdraw - await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}) - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // pendingValidators should be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators.should.deep.equal([secondCandidate]) - }) - it('can withdraw less than staked amount', async () => { - // stake - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // withdraw - await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) - let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - let expectedValidators = [] - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // pendingValidators should be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - }) - it('can withdraw multiple times', async () => { - // stake - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // withdraw 1st time - await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) - let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - let expectedValidators = [] - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - // withdraw 2nd time - await consensus.withdraw(ONE_ETHER, {from: firstCandidate}) - expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - }) - }) - describe('delegators', async () => { - it('cannot withdraw zero', async () => { - await consensus.methods['withdraw(address,uint256)'](firstCandidate, ZERO_AMOUNT, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - }) - it('cannot withdraw if no staker address defined', async () => { - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - await consensus.methods['withdraw(address,uint256)'](ZERO_ADDRESS, MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - }) - it('cannot withdraw more than staked amount', async () => { - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - await consensus.methods['withdraw(address,uint256)'](firstCandidate, MORE_THAN_MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - }) - it('can withdraw all staked amount', async () => { - // stake - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // stake - await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}) - // withdraw - await consensus.methods['withdraw(address,uint256)'](firstCandidate, MIN_STAKE, {from: firstDelegator}) - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - ZERO_AMOUNT.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, secondCandidate)) - // pendingValidators should be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators.should.deep.equal([secondCandidate]) - // delegators list should be updated for firstCandidate - let delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(0) - let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(0)) - // delegators list should be updated for secondCandidate - delegators = await consensus.delegators(secondCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - delegatorsLength = await consensus.delegatorsLength(secondCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) - }) - it('can withdraw less than staked amount', async () => { - // stake - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // withdraw - await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - let expectedValidators = [] - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // pendingValidators should be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - // delegators list should be updated - delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - }) - it('can withdraw multiple times', async () => { - // stake - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // withdraw 1st time - await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - let expectedValidators = [firstCandidate] - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - // delegators list should be updated - delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // withdraw 2nd time - await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - // delegators list should be updated - delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - }) - }) + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // }) + // describe('stakers', async () => { + // it('cannot withdraw zero', async () => { + // await consensus.methods['withdraw(uint256)'](ZERO_AMOUNT, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('cannot withdraw more than staked amount', async () => { + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // await consensus.methods['withdraw(uint256)'](MORE_THAN_MIN_STAKE).should.be.rejectedWith(ERROR_MSG) + // }) + // it('can withdraw all staked amount', async () => { + // // stake + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // // stake + // await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}) + // // withdraw + // await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}) + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // // pendingValidators should be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators.should.deep.equal([secondCandidate]) + // }) + // it('can withdraw less than staked amount', async () => { + // // stake + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // // withdraw + // await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) + // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + // let expectedValidators = [] + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // // pendingValidators should be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // }) + // it('can withdraw multiple times', async () => { + // // stake + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // // withdraw 1st time + // await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) + // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + // let expectedValidators = [] + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // withdraw 2nd time + // await consensus.withdraw(ONE_ETHER, {from: firstCandidate}) + // expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // }) + // }) + // describe('delegators', async () => { + // it('cannot withdraw zero', async () => { + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ZERO_AMOUNT, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('cannot withdraw if no staker address defined', async () => { + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + // await consensus.methods['withdraw(address,uint256)'](ZERO_ADDRESS, MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('cannot withdraw more than staked amount', async () => { + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MORE_THAN_MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('can withdraw all staked amount', async () => { + // // stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // stake + // await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // withdraw + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MIN_STAKE, {from: firstDelegator}) + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, secondCandidate)) + // // pendingValidators should be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators.should.deep.equal([secondCandidate]) + // // delegators list should be updated for firstCandidate + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(0) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(0)) + // // delegators list should be updated for secondCandidate + // delegators = await consensus.delegators(secondCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(secondCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) + // }) + // it('can withdraw less than staked amount', async () => { + // // stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // withdraw + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + // let expectedValidators = [] + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // // pendingValidators should be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // delegators list should be updated + // delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // }) + // it('can withdraw multiple times', async () => { + // // stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // withdraw 1st time + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + // let expectedValidators = [firstCandidate] + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // delegators list should be updated + // delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // // withdraw 2nd time + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + // expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // delegators list should be updated + // delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // }) + // }) }) describe('setValidatorFee', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - }) - it('should only be called by validator', async () => { - decimals = await consensus.DECIMALS() - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - let newValidatorFee = defaultValidatorFee.sub(toBN(0.01 * decimals)) - await consensus.setValidatorFee(newValidatorFee, {from: initialValidator}).should.be.fulfilled - newValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(initialValidator)) - await consensus.setValidatorFee(newValidatorFee, {from: secondCandidate}).should.be.rejectedWith(ERROR_MSG) - }) - it('should only be able to set a valid fee', async () => { - decimals = await consensus.DECIMALS() - let i; - for (i = 0; i <= 100; i++) { - await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.fulfilled - } - await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - }) + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // }) + // it('should only be called by validator', async () => { + // decimals = await consensus.DECIMALS() + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + // let newValidatorFee = defaultValidatorFee.sub(toBN(0.01 * decimals)) + // await consensus.setValidatorFee(newValidatorFee, {from: initialValidator}).should.be.fulfilled + // newValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(initialValidator)) + // await consensus.setValidatorFee(newValidatorFee, {from: secondCandidate}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should only be able to set a valid fee', async () => { + // decimals = await consensus.DECIMALS() + // let i; + // for (i = 0; i <= 100; i++) { + // await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.fulfilled + // } + // await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + // }) }) describe('getDelegatorsForRewardDistribution', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - }) - it('validator without delegators', async () => { - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(0) - rewards.length.should.be.equal(0) - }) - describe('validator with one delegator', async () => { - it('total delegated more than total staked - no fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let fee = toBN(0 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - it('total delegated less than total staked - no fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let fee = toBN(0 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - it('total delegated more than total staked - 100% fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let fee = toBN(1 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - it('total delegated less than total staked - 100% fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let fee = toBN(1 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - it('total delegated more than total staked - other fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let fee = toBN(0.225 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - it('total delegated less than total staked - other fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let fee = toBN(0.225 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - }) - describe('validator with multiple delegators', async () => { - it('total delegated more than total staked - no fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let fee = toBN(0 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - it('total delegated less than total staked - no fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let fee = toBN(0 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - it('total delegated more than total staked - 100% fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let fee = toBN(1 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - it('total delegated less than total staked - 100% fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let fee = toBN(1 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - it('total delegated more than total staked - other fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let fee = toBN(0.15 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - it('total delegated less than total staked - other fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let fee = toBN(0.15 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - }) - it('validator with many delegators', async () => { - decimals = await consensus.DECIMALS() - let delegatorsCount = accounts.length - 2 - let delegateAmountValue = parseInt(MIN_STAKE_AMOUNT * 0.99 / delegatorsCount) - let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') - let stakeAmountValue = MIN_STAKE_AMOUNT - delegateAmountValue * delegatorsCount - let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') - let fee = toBN(0.05 * decimals) - let validator = accounts[1] - await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled - for (let i = 2; i < accounts.length; i++) { - await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled - } - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(delegatorsCount) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - for (let i = 0; i < delegatorsCount; i++) { - delegators[i].should.be.equal(accounts[i + 2]) - rewards[i].should.be.bignumber.equal(expectedReward) - } - }) + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // }) + // it('validator without delegators', async () => { + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(0) + // rewards.length.should.be.equal(0) + // }) + // describe('validator with one delegator', async () => { + // it('total delegated more than total staked - no fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let fee = toBN(0 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // it('total delegated less than total staked - no fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let fee = toBN(0 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // it('total delegated more than total staked - 100% fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let fee = toBN(1 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // it('total delegated less than total staked - 100% fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let fee = toBN(1 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // it('total delegated more than total staked - other fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let fee = toBN(0.225 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // it('total delegated less than total staked - other fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let fee = toBN(0.225 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // }) + // describe('validator with multiple delegators', async () => { + // it('total delegated more than total staked - no fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let fee = toBN(0 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // it('total delegated less than total staked - no fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let fee = toBN(0 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // it('total delegated more than total staked - 100% fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let fee = toBN(1 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // it('total delegated less than total staked - 100% fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let fee = toBN(1 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // it('total delegated more than total staked - other fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let fee = toBN(0.15 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // it('total delegated less than total staked - other fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let fee = toBN(0.15 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // }) + // it('validator with many delegators', async () => { + // decimals = await consensus.DECIMALS() + // let delegatorsCount = accounts.length - 2 + // let delegateAmountValue = parseInt(MIN_STAKE_AMOUNT * 0.99 / delegatorsCount) + // let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') + // let stakeAmountValue = MIN_STAKE_AMOUNT - delegateAmountValue * delegatorsCount + // let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') + // let fee = toBN(0.05 * decimals) + // let validator = accounts[1] + // await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled + // for (let i = 2; i < accounts.length; i++) { + // await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled + // } + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(delegatorsCount) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // for (let i = 0; i < delegatorsCount; i++) { + // delegators[i].should.be.equal(accounts[i + 2]) + // rewards[i].should.be.bignumber.equal(expectedReward) + // } + // }) }) describe('upgradeTo', async () => { - let consensusOldImplementation, consensusNew - let proxyStorageStub = accounts[3] - beforeEach(async () => { - consensus = await Consensus.new() - consensusOldImplementation = consensus.address - proxy = await EternalStorageProxy.new(proxyStorage.address, consensus.address) - consensus = await Consensus.at(proxy.address) - consensusNew = await Consensus.new() - }) - it('should only be called by ProxyStorage', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) - let {logs} = await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - logs[0].event.should.be.equal('Upgraded') - await proxy.setProxyStorageMock(proxyStorage.address) - }) - it('should change implementation address', async () => { - consensusOldImplementation.should.be.equal(await proxy.getImplementation()) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - consensusNew.address.should.be.equal(await proxy.getImplementation()) - }) - it('should increment implementation version', async () => { - let consensusOldVersion = await proxy.getVersion() - let consensusNewVersion = consensusOldVersion.add(toBN(1)) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - consensusNewVersion.should.be.bignumber.equal(await proxy.getVersion()) - }) - it('should work after upgrade', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - consensusNew = await Consensus.at(proxy.address) - false.should.be.equal(await consensusNew.isInitialized()) - await consensusNew.initialize(initialValidator).should.be.fulfilled - true.should.be.equal(await consensusNew.isInitialized()) - }) - it('should use same proxyStorage after upgrade', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - consensusNew = await Consensus.at(proxy.address) - proxyStorageStub.should.be.equal(await consensusNew.getProxyStorage()) - }) - it('should use same storage after upgrade', async () => { - await consensus.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - consensusNew = await Consensus.at(proxy.address) - RANDOM_ADDRESS.should.be.equal(await consensus.getSystemAddress()) - }) + // let consensusOldImplementation, consensusNew + // let proxyStorageStub = accounts[3] + // beforeEach(async () => { + // consensus = await Consensus.new() + // consensusOldImplementation = consensus.address + // proxy = await EternalStorageProxy.new(proxyStorage.address, consensus.address) + // consensus = await Consensus.at(proxy.address) + // consensusNew = await Consensus.new() + // }) + // it('should only be called by ProxyStorage', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) + // let {logs} = await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // logs[0].event.should.be.equal('Upgraded') + // await proxy.setProxyStorageMock(proxyStorage.address) + // }) + // it('should change implementation address', async () => { + // consensusOldImplementation.should.be.equal(await proxy.getImplementation()) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // consensusNew.address.should.be.equal(await proxy.getImplementation()) + // }) + // it('should increment implementation version', async () => { + // let consensusOldVersion = await proxy.getVersion() + // let consensusNewVersion = consensusOldVersion.add(toBN(1)) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // consensusNewVersion.should.be.bignumber.equal(await proxy.getVersion()) + // }) + // it('should work after upgrade', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // consensusNew = await Consensus.at(proxy.address) + // false.should.be.equal(await consensusNew.isInitialized()) + // await consensusNew.initialize(initialValidator).should.be.fulfilled + // true.should.be.equal(await consensusNew.isInitialized()) + // }) + // it('should use same proxyStorage after upgrade', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // consensusNew = await Consensus.at(proxy.address) + // proxyStorageStub.should.be.equal(await consensusNew.getProxyStorage()) + // }) + // it('should use same storage after upgrade', async () => { + // await consensus.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // consensusNew = await Consensus.at(proxy.address) + // RANDOM_ADDRESS.should.be.equal(await consensus.getSystemAddress()) + // }) }) }) From 588b646b4edfb0045df7c8341e38cf842d646485 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Thu, 13 Aug 2020 11:53:15 +0300 Subject: [PATCH 05/19] finishing the MVP --- contracts/ConsensusUtils.sol | 74 +- contracts/test/ConsensusMock.sol | 12 +- test/blockReward.test.js | 482 ++++---- test/consensus.test.js | 1988 +++++++++++++++--------------- 4 files changed, 1257 insertions(+), 1299 deletions(-) diff --git a/contracts/ConsensusUtils.sol b/contracts/ConsensusUtils.sol index a5ba926..f1abecf 100644 --- a/contracts/ConsensusUtils.sol +++ b/contracts/ConsensusUtils.sol @@ -94,30 +94,12 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { // require (stakeAmount(_validator) < getMinStake()); // require (stakeAmount(_validator).add(_amount) <= getMinStake()); - // _stakeAmountAdd(_validator, _amount); - uint256 currentAmount = stakeAmount(_validator); - uint256 addedAmount = currentAmount.add(currentAmount); - if (addedAmount < getMinStake()) { - _delegatedAmountAdd(_staker, _validator, _amount); - _stakeAmountAdd(_validator, _amount); - return; - } - if (currentAmount > getMinStake()) { - // get index of the validator - // find the validator to move - // updating the validator - } else { - for (uint256 i; i < pendingValidatorsLength(); i++) { - address validatorAddress = pendingValidatorsAtPosition(i) - if (addedAmount > stakeAmount(validatorAddress)) { - // put validator in place i and move the rest - } - } - // adding validator as a new one + _delegatedAmountAdd(_staker, _validator, _amount); + _stakeAmountAdd(_validator, _amount); + + if (stakeAmount(_validator) >= getMinStake() && !isPendingValidator(_validator)) { + _pendingValidatorsAdd(_validator); } - // if (stakeAmount(_validator) >= getMinStake() && !isPendingValidator(_validator)) { - // _pendingValidatorsAdd(_validator); - // } } function _setSystemAddress(address _newAddress) internal { @@ -288,44 +270,11 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { addressArrayStorage[PENDING_VALIDATORS][_p] = _address; } - function _findPosition(address _address) internal { - uint256 stake = stakeAmount(_address); - if (stake == 0) { - uint256 l = pendingValidatorsLength(); - uint256 i = 0; - while (i < l) { - address va = pendingValidatorsAtPosition(i); - uint256 sa = stakeAmount(va); - if (stake > sa) { - - } else { - i++; - } - } - } - } - function _pendingValidatorsAdd(address _address) internal { - uint256 l = pendingValidatorsLength(); - uint256 i = 1; - while (i < l) { - uint256 j = i; - while (j > 0 && stakeAmount(pendingValidatorsAtPosition(j - 1)) > stakeAmount(pendingValidatorsAtPosition(j))) { - _pendingValidatorsSwap(j, i); - j = j - 1; - } - i = i + 1; - } addressArrayStorage[PENDING_VALIDATORS].push(_address); _setValidatorFee(_address, DEFAULT_VALIDATOR_FEE); } - function _pendingValidatorsSwap(uint256 _firstPosition, uint256 _secondPosition) { - address x = pendingValidatorsAtPosition(_secondPosition); - _setPendingValidatorsAtPosition(_secondPosition, pendingValidatorsAtPosition(_firstPosition)); - _setPendingValidatorsAtPosition(_firstPosition, x); - } - function _pendingValidatorsRemove(address _address) internal { bool found = false; uint256 removeIndex; @@ -351,7 +300,6 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { } function totalStakeAmount() public view returns(uint256) { - // return 0; return uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))]; } @@ -474,13 +422,13 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { boolStorage[SHOULD_EMIT_INITIATE_CHANGE] = _status; } - function _getBlocksToSnapshot() internal pure returns(uint256) { - return getCycleDurationBlocks().div(getSnapshotsPerCycle()); - } + // function _getBlocksToSnapshot() internal pure returns(uint256) { + // return getCycleDurationBlocks().div(getSnapshotsPerCycle()); + // } - function _shouldTakeSnapshot() internal view returns(bool) { - return (block.number - getLastSnapshotTakenAtBlock() >= _getBlocksToSnapshot()); - } + // function _shouldTakeSnapshot() internal view returns(bool) { + // return (block.number - getLastSnapshotTakenAtBlock() >= _getBlocksToSnapshot()); + // } function _hasCycleEnded() internal view returns(bool) { return (block.number >= getCurrentCycleEndBlock()); diff --git a/contracts/test/ConsensusMock.sol b/contracts/test/ConsensusMock.sol index f30774d..4ae4be1 100644 --- a/contracts/test/ConsensusMock.sol +++ b/contracts/test/ConsensusMock.sol @@ -17,17 +17,17 @@ contract ConsensusMock is Consensus { return _hasCycleEnded(); } - function shouldTakeSnapshot() public view returns(bool) { - return _shouldTakeSnapshot(); - } + // function shouldTakeSnapshot() public view returns(bool) { + // return _shouldTakeSnapshot(); + // } function getRandom(uint256 _from, uint256 _to) public view returns(uint256) { return _getRandom(_from, _to); } - function getBlocksToSnapshot() public pure returns(uint256) { - return _getBlocksToSnapshot(); - } + // function getBlocksToSnapshot() public pure returns(uint256) { + // return _getBlocksToSnapshot(); + // } function setNewValidatorSetMock(address[] _newSet) public { addressArrayStorage[NEW_VALIDATOR_SET] = _newSet; diff --git a/test/blockReward.test.js b/test/blockReward.test.js index 0aaeec5..fc495eb 100644 --- a/test/blockReward.test.js +++ b/test/blockReward.test.js @@ -1,3 +1,4 @@ +/* eslint-disable prefer-const */ const Consensus = artifacts.require('ConsensusMock.sol') const ProxyStorage = artifacts.require('ProxyStorageMock.sol') const EternalStorageProxy = artifacts.require('EternalStorageProxyMock.sol') @@ -69,250 +70,259 @@ contract('BlockReward', async (accounts) => { }) describe('reward', async () => { + let minStakeAmount beforeEach(async () => { await blockReward.initialize(INITIAL_SUPPLY) + minStakeAmount = await consensus.getMinStake() + await consensus.setTotalStakeAmountMock(minStakeAmount) }) - describe('#getBlockRewardAmountPerValidator', () => { - let blockRewardAmount - beforeEach(async () => { - blockRewardAmount = await blockReward.getBlockRewardAmount() - }) - it('block reward with one validator', async () => { - const minStakeAmount = await consensus.getMinStake() - await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) - - const validator = accounts[1] - await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - const l = await consensus.currentValidatorsLength() - console.log(l.toString(10)) - console.log(blockRewardAmount.toString(10)) - '1'.should.be.equal(l.toString(10)) - - const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - const expectedReward = blockRewardAmount.div(toBN(10)) - expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) - }) - - it('block reward of one validator staking 100% of the total stake', async () => { - const minStakeAmount = await consensus.getMinStake() - await consensus.setTotalStakeAmountMock(minStakeAmount) - - const validator = accounts[1] - await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - const l = await consensus.currentValidatorsLength() - console.log(l.toString(10)) - console.log(blockRewardAmount.toString(10)) - '1'.should.be.equal(l.toString(10)) - - const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - const expectedReward = blockRewardAmount - expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) - }) - - it('block reward of 1 validator of 2, staking 10% of the total stake', async () => { - const minStakeAmount = await consensus.getMinStake() - await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) - await consensus.setCurrentValidatorsLengthMock(toBN(2)) - const validator = accounts[1] - await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - - const l = await consensus.currentValidatorsLength() - '2'.should.be.equal(l.toString(10)) - - const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - - // expected reward calculation - const expectedReward = blockRewardAmount.div(toBN(10)).mul(toBN(2)) - expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) - }) - - it('block reward of 1 validator of 2, staking 50% of the total stake', async () => { - const minStakeAmount = await consensus.getMinStake() - await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) - await consensus.setCurrentValidatorsLengthMock(toBN(2)) - const validator = accounts[1] - await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - - const l = await consensus.currentValidatorsLength() - '2'.should.be.equal(l.toString(10)) - - const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - - // expected reward calculation - const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) - expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) - }) - - it('block reward does not changed if the propotion stays the same', async () => { - const minStakeAmount = await consensus.getMinStake() - await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) - await consensus.setCurrentValidatorsLengthMock(toBN(2)) - const validator = accounts[1] - await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - - const l = await consensus.currentValidatorsLength() - '2'.should.be.equal(l.toString(10)) - - const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - - // total stake is 50 * minStakeAmount now - await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(100))) - // validator stake is 50 * minStakeAmount now - await consensus.sendTransaction({ from: validator, value: minStakeAmount.mul(toBN(49)) }).should.be.fulfilled - - // expected reward calculation - const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) - expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) - }) + // describe('#getBlockRewardAmountPerValidator', () => { + // let blockRewardAmount + // beforeEach(async () => { + // blockRewardAmount = await blockReward.getBlockRewardAmount() + // }) + // it('block reward with one validator', async () => { + // const minStakeAmount = await consensus.getMinStake() + // // await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) + + // const validator = accounts[1] + // await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + // const l = await consensus.currentValidatorsLength() + // console.log(l.toString(10)) + // console.log(blockRewardAmount.toString(10)) + // '1'.should.be.equal(l.toString(10)) + + // const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + // console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + // const expectedReward = blockRewardAmount.div(toBN(10)) + // expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + // }) + + // it('block reward of one validator staking 100% of the total stake', async () => { + // const minStakeAmount = await consensus.getMinStake() + // await consensus.setTotalStakeAmountMock(minStakeAmount) + + // const validator = accounts[1] + // await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + // const l = await consensus.currentValidatorsLength() + // console.log(l.toString(10)) + // console.log(blockRewardAmount.toString(10)) + // '1'.should.be.equal(l.toString(10)) + + // const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + // console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + // const expectedReward = blockRewardAmount + // expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + // }) + + // it('block reward of 1 validator of 2, staking 10% of the total stake', async () => { + // const minStakeAmount = await consensus.getMinStake() + // await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) + // await consensus.setCurrentValidatorsLengthMock(toBN(2)) + // const validator = accounts[1] + // await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + + // const l = await consensus.currentValidatorsLength() + // '2'.should.be.equal(l.toString(10)) + + // const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + // console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + + // // expected reward calculation + // const expectedReward = blockRewardAmount.div(toBN(10)).mul(toBN(2)) + // expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + // }) + + // it('block reward of 1 validator of 2, staking 50% of the total stake', async () => { + // const minStakeAmount = await consensus.getMinStake() + // await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) + // await consensus.setCurrentValidatorsLengthMock(toBN(2)) + // const validator = accounts[1] + // await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + + // const l = await consensus.currentValidatorsLength() + // '2'.should.be.equal(l.toString(10)) + + // const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + // console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + + // // expected reward calculation + // const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) + // expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + // }) + + // it('block reward does not changed if the propotion stays the same', async () => { + // const minStakeAmount = await consensus.getMinStake() + // await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) + // await consensus.setCurrentValidatorsLengthMock(toBN(2)) + // const validator = accounts[1] + // await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + + // const l = await consensus.currentValidatorsLength() + // '2'.should.be.equal(l.toString(10)) + + // const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + // console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + + // // total stake is 50 * minStakeAmount now + // await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(100))) + // // validator stake is 50 * minStakeAmount now + // await consensus.sendTransaction({ from: validator, value: minStakeAmount.mul(toBN(49)) }).should.be.fulfilled + + // // expected reward calculation + // const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) + // expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + // }) + // }) + + it('can only be called by system address', async () => { + await blockReward.reward([accounts[3]], [0]).should.be.rejectedWith(ERROR_MSG) + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled + }) + it('should revert if input array contains more than one item', async () => { + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + await blockReward.reward([accounts[3], accounts[4]], [0, 0], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) + }) + it('should revert if lengths of input arrays are not equal', async () => { + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + await blockReward.reward([accounts[3]], [0, 0], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) + }) + it('should revert if "kind" parameter is not 0', async () => { + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + await blockReward.reward([accounts[3]], [1], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) }) + it('should give reward to validator and total supply should be updated', async () => { + const validator = accounts[3] + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + await consensus.setTotalStakeAmountMock(minStakeAmount) + await consensus.sendTransaction({from: validator, value: minStakeAmount}).should.be.fulfilled - // it('can only be called by system address', async () => { - // await blockReward.reward([accounts[3]], [0]).should.be.rejectedWith(ERROR_MSG) - // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - // await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled - // }) - // it('should revert if input array contains more than one item', async () => { - // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - // await blockReward.reward([accounts[3], accounts[4]], [0, 0], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should revert if lengths of input arrays are not equal', async () => { - // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - // await blockReward.reward([accounts[3]], [0, 0], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should revert if "kind" parameter is not 0', async () => { - // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - // await blockReward.reward([accounts[3]], [1], {from: mockSystemAddress}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should give reward to validator and total supply should be updated', async () => { - // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - // let initialSupply = await blockReward.getTotalSupply() - // let blockRewardAmount = await blockReward.getBlockRewardAmount() - // let {logs} = await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled - // logs.length.should.be.equal(1) - // logs[0].event.should.be.equal('Rewarded') - // logs[0].args['receivers'].should.deep.equal([accounts[3]]) - // logs[0].args['rewards'][0].should.be.bignumber.equal(blockRewardAmount) - // let expectedSupply = initialSupply.add(blockRewardAmount) - // expectedSupply.should.be.bignumber.equal(await blockReward.getTotalSupply()) - // }) - // it('should give rewards to validator and its delegators', async () => { - // let decimals = await consensus.DECIMALS() - // let minStakeAmount = await consensus.getMinStake() - // let delegatorsCount = accounts.length - 2 - // let delegateAmountValue = parseInt(minStakeAmount.div(decimals).toNumber() * 0.99 / delegatorsCount) - // let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') - // let stakeAmountValue = minStakeAmount.div(decimals).toNumber() - delegateAmountValue * delegatorsCount - // let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') - // let fee = 5 - // let validator = accounts[1] - // await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled - // for (let i = 2; i < accounts.length; i++) { - // await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled - // } - // await consensus.setValidatorFeeMock(fee, {from: validator}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(validator) - // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - // let initialSupply = await blockReward.getTotalSupply() - // let blockRewardAmount = await blockReward.getBlockRewardAmount() - // let {logs} = await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled - // logs.length.should.be.equal(1) - // logs[0].event.should.be.equal('Rewarded') - // let receivers = logs[0].args['receivers'] - // let rewards = logs[0].args['rewards'] - // receivers.length.should.be.equal(delegatorsCount + 1) - // rewards.length.should.be.equal(receivers.length) - // let expectedRewardForValidator = blockRewardAmount - // let expectedRewardForDelegators = blockRewardAmount.mul(delegateAmount).div(minStakeAmount).mul(decimals.sub(validatorFee)).div(decimals) - // receivers[0].should.be.equal(validator) - // for (let i = 1; i <= delegatorsCount; i++) { - // receivers[i].should.be.equal(accounts[i + 1]) - // rewards[i].should.be.bignumber.equal(expectedRewardForDelegators) - // expectedRewardForValidator = expectedRewardForValidator.sub(expectedRewardForDelegators) - // } - // rewards[0].should.be.bignumber.equal(expectedRewardForValidator) - // }) - // it('reward amount should update after BLOCKS_PER_YEAR and total yearly inflation should be calculated correctly', async () => { - // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - - // let decimals = await blockReward.DECIMALS() - // let initialSupply = await blockReward.getTotalSupply() - // let blocksPerYear = await blockReward.getBlocksPerYear() - // let inflation = await blockReward.getInflation() - // let blockRewardAmount = await blockReward.getBlockRewardAmount() - // // console.log(`initialSupply: ${initialSupply.div(decimals).toNumber()}, blockRewardAmount: ${blockRewardAmount.div(decimals).toNumber()}`) - - // // each of the following calls advances a block - // let i = 0 - // let blockNumber = await web3.eth.getBlockNumber() - // while (blockNumber % BLOCKS_PER_YEAR !== 0) { - // // console.log('block #', blockNumber) - // await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled - // blockNumber = await web3.eth.getBlockNumber() - // i++ - // } - // // console.log('i', i) - - // let totalSupply = await blockReward.getTotalSupply() - // let newBlockRewardAmount = await blockReward.getBlockRewardAmount() - // // console.log(`totalSupply: ${totalSupply.div(decimals).toNumber()}, newBlockRewardAmount: ${newBlockRewardAmount.div(decimals).toNumber()}`) - // let expectedSupply = initialSupply - // for (let j = 0; j < i; j++) { - // expectedSupply = expectedSupply.add(blockRewardAmount) - // } - // // console.log(`expectedSupply: ${expectedSupply.div(decimals).toNumber()}`) - // totalSupply.should.be.bignumber.equal(expectedSupply) - // newBlockRewardAmount.should.be.bignumber.equal((totalSupply.mul(decimals).mul(inflation).div(toBN(100))).div(blocksPerYear).div(decimals)) - // }) + let initialSupply = await blockReward.getTotalSupply() + let blockRewardAmount = await blockReward.getBlockRewardAmountPerValidator(validator) + let {logs} = await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled + logs.length.should.be.equal(1) + logs[0].event.should.be.equal('Rewarded') + logs[0].args['receivers'].should.deep.equal([validator]) + logs[0].args['rewards'][0].should.be.bignumber.equal(blockRewardAmount) + let expectedSupply = initialSupply.add(blockRewardAmount) + console.log({ blockRewardAmount }) + expectedSupply.should.be.bignumber.equal(await blockReward.getTotalSupply()) + }) + it('should give rewards to validator and its delegators', async () => { + let decimals = await consensus.DECIMALS() + let minStakeAmount = await consensus.getMinStake() + let delegatorsCount = accounts.length - 2 + let delegateAmountValue = parseInt(minStakeAmount.div(decimals).toNumber() * 0.99 / delegatorsCount) + let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') + let stakeAmountValue = minStakeAmount.div(decimals).toNumber() - delegateAmountValue * delegatorsCount + let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') + let fee = 5 + let validator = accounts[1] + await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled + for (let i = 2; i < accounts.length; i++) { + await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled + } + await consensus.setValidatorFeeMock(fee, {from: validator}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(validator) + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + let initialSupply = await blockReward.getTotalSupply() + let blockRewardAmount = await blockReward.getBlockRewardAmountPerValidator(validator) + console.log({ blockRewardAmount }) + let {logs} = await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled + logs.length.should.be.equal(1) + logs[0].event.should.be.equal('Rewarded') + let receivers = logs[0].args['receivers'] + let rewards = logs[0].args['rewards'] + receivers.length.should.be.equal(delegatorsCount + 1) + rewards.length.should.be.equal(receivers.length) + let expectedRewardForValidator = blockRewardAmount + let expectedRewardForDelegators = blockRewardAmount.mul(delegateAmount).div(minStakeAmount).mul(decimals.sub(validatorFee)).div(decimals) + receivers[0].should.be.equal(validator) + for (let i = 1; i <= delegatorsCount; i++) { + receivers[i].should.be.equal(accounts[i + 1]) + rewards[i].should.be.bignumber.equal(expectedRewardForDelegators) + expectedRewardForValidator = expectedRewardForValidator.sub(expectedRewardForDelegators) + } + rewards[0].should.be.bignumber.equal(expectedRewardForValidator) + }) + it('reward amount should update after BLOCKS_PER_YEAR and total yearly inflation should be calculated correctly', async () => { + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + + let decimals = await blockReward.DECIMALS() + let initialSupply = await blockReward.getTotalSupply() + let blocksPerYear = await blockReward.getBlocksPerYear() + let inflation = await blockReward.getInflation() + let blockRewardAmount = await blockReward.getBlockRewardAmount() + // console.log(`initialSupply: ${initialSupply.div(decimals).toNumber()}, blockRewardAmount: ${blockRewardAmount.div(decimals).toNumber()}`) + + // each of the following calls advances a block + let i = 0 + let blockNumber = await web3.eth.getBlockNumber() + while (blockNumber % BLOCKS_PER_YEAR !== 0) { + // console.log('block #', blockNumber) + await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled + blockNumber = await web3.eth.getBlockNumber() + i++ + } + // console.log('i', i) + + let totalSupply = await blockReward.getTotalSupply() + let newBlockRewardAmount = await blockReward.getBlockRewardAmount() + // console.log(`totalSupply: ${totalSupply.div(decimals).toNumber()}, newBlockRewardAmount: ${newBlockRewardAmount.div(decimals).toNumber()}`) + let expectedSupply = initialSupply + for (let j = 0; j < i; j++) { + expectedSupply = expectedSupply.add(blockRewardAmount) + } + // console.log(`expectedSupply: ${expectedSupply.div(decimals).toNumber()}`) + totalSupply.should.be.bignumber.equal(expectedSupply) + newBlockRewardAmount.should.be.bignumber.equal((totalSupply.mul(decimals).mul(inflation).div(toBN(100))).div(blocksPerYear).div(decimals)) + }) }) - // describe('emitRewardedOnCycle', function() { - // beforeEach(async () => { - // await blockReward.initialize(INITIAL_SUPPLY) - // }) - // it('should fail if not called by validator', async () => { - // await blockReward.emitRewardedOnCycle({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should be successful if `shouldEmitRewardedOnCycle` and `consensus.isFinalized` are true', async () => { - // await blockReward.setShouldEmitRewardedOnCycleMock(false) - // await consensus.setFinalizedMock(false) - // await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) - - // await blockReward.setShouldEmitRewardedOnCycleMock(true) - // await consensus.setFinalizedMock(false) - // await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) - - // await blockReward.setShouldEmitRewardedOnCycleMock(false) - // await consensus.setFinalizedMock(true) - // await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) - - // await blockReward.setShouldEmitRewardedOnCycleMock(true) - // await consensus.setFinalizedMock(true) - // await blockReward.emitRewardedOnCycle({from: owner}).should.be.fulfilled - // }) - // it('should be successful and emit event', async () => { - // let BLOCKS_TO_REWARD = 10 - // let blockRewardAmount = await blockReward.getBlockRewardAmount() - // let expectedAmount = blockRewardAmount.mul(toBN(BLOCKS_TO_REWARD)) - - // await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - // for (let i = 0; i < BLOCKS_TO_REWARD; i++) { - // await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled - // } - - // await blockReward.setShouldEmitRewardedOnCycleMock(true) - // let {logs} = await blockReward.emitRewardedOnCycle({from: owner}).should.be.fulfilled - // false.should.be.equal(await blockReward.shouldEmitRewardedOnCycle()) - // logs.length.should.be.equal(1) - // logs[0].event.should.be.equal('RewardedOnCycle') - // logs[0].args['amount'].should.be.bignumber.equal(expectedAmount) - // }) - // }) + describe('emitRewardedOnCycle', function() { + beforeEach(async () => { + await blockReward.initialize(INITIAL_SUPPLY) + }) + it('should fail if not called by validator', async () => { + await blockReward.emitRewardedOnCycle({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) + }) + it('should be successful if `shouldEmitRewardedOnCycle` and `consensus.isFinalized` are true', async () => { + await blockReward.setShouldEmitRewardedOnCycleMock(false) + await consensus.setFinalizedMock(false) + await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) + + await blockReward.setShouldEmitRewardedOnCycleMock(true) + await consensus.setFinalizedMock(false) + await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) + + await blockReward.setShouldEmitRewardedOnCycleMock(false) + await consensus.setFinalizedMock(true) + await blockReward.emitRewardedOnCycle({from: owner}).should.be.rejectedWith(ERROR_MSG) + + await blockReward.setShouldEmitRewardedOnCycleMock(true) + await consensus.setFinalizedMock(true) + await blockReward.emitRewardedOnCycle({from: owner}).should.be.fulfilled + }) + it('should be successful and emit event', async () => { + let BLOCKS_TO_REWARD = 10 + let blockRewardAmount = await blockReward.getBlockRewardAmount() + let expectedAmount = blockRewardAmount.mul(toBN(BLOCKS_TO_REWARD)) + + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + for (let i = 0; i < BLOCKS_TO_REWARD; i++) { + await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled + } + + await blockReward.setShouldEmitRewardedOnCycleMock(true) + let {logs} = await blockReward.emitRewardedOnCycle({from: owner}).should.be.fulfilled + false.should.be.equal(await blockReward.shouldEmitRewardedOnCycle()) + logs.length.should.be.equal(1) + logs[0].event.should.be.equal('RewardedOnCycle') + logs[0].args['amount'].should.be.bignumber.equal(expectedAmount) + }) + }) // describe('upgradeTo', async () => { // let blockRewardOldImplementation, blockRewardNew diff --git a/test/consensus.test.js b/test/consensus.test.js index 4c93034..2529a79 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -62,526 +62,526 @@ contract('Consensus', async (accounts) => { }) describe('initialize', async () => { - // it('default values', async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // owner.should.equal(await proxy.getOwner()) - // toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await consensus.getSystemAddress())) - // true.should.be.equal(await consensus.isFinalized()) - // MIN_STAKE.should.be.bignumber.equal(await consensus.getMinStake()) - // toBN(MAX_VALIDATORS).should.be.bignumber.equal(await consensus.getMaxValidators()) - // toBN(CYCLE_DURATION_BLOCKS).should.be.bignumber.equal(await consensus.getCycleDurationBlocks()) - // toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) - // toBN(CYCLE_DURATION_BLOCKS / SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getBlocksToSnapshot()) - // false.should.be.equal(await consensus.hasCycleEnded()) - // toBN(0).should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) - // toBN(0).should.be.bignumber.equal(await consensus.getNextSnapshotId()) - // let validators = await consensus.getValidators() - // validators.length.should.be.equal(1) - // validators[0].should.be.equal(initialValidator) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // }) - // it('initial validator address not defined - owner should be initial validator', async () => { - // await consensus.initialize(ZERO_ADDRESS) - // await consensus.setProxyStorage(proxyStorage.address) - // let validators = await consensus.getValidators() - // validators.length.should.be.equal(1) - // validators[0].should.be.equal(owner) - // }) - // it('initial validator address defined', async () => { - // await consensus.initialize(initialValidator) - // let validators = await consensus.getValidators() - // validators.length.should.be.equal(1) - // validators[0].should.be.equal(initialValidator) - // }) + it('default values', async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + owner.should.equal(await proxy.getOwner()) + toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await consensus.getSystemAddress())) + true.should.be.equal(await consensus.isFinalized()) + MIN_STAKE.should.be.bignumber.equal(await consensus.getMinStake()) + toBN(MAX_VALIDATORS).should.be.bignumber.equal(await consensus.getMaxValidators()) + toBN(CYCLE_DURATION_BLOCKS).should.be.bignumber.equal(await consensus.getCycleDurationBlocks()) + toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) + // toBN(CYCLE_DURATION_BLOCKS / SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getBlocksToSnapshot()) + false.should.be.equal(await consensus.hasCycleEnded()) + toBN(0).should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) + toBN(0).should.be.bignumber.equal(await consensus.getNextSnapshotId()) + let validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(initialValidator) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + }) + it('initial validator address not defined - owner should be initial validator', async () => { + await consensus.initialize(ZERO_ADDRESS) + await consensus.setProxyStorage(proxyStorage.address) + let validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(owner) + }) + it('initial validator address defined', async () => { + await consensus.initialize(initialValidator) + let validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(initialValidator) + }) }) describe('setProxyStorage', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // }) - // it('setProxyStorage should fail if no address', async () => { - // await consensus.setProxyStorage(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG) - // }) - // it('setProxyStorage should fail if not called by owner', async () => { - // await consensus.setProxyStorage(proxyStorage.address, {from: nonOwner}).should.be.rejectedWith(ERROR_MSG) - // // success - // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - // proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) - // // should not be able to set again if already set - // await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) - // }) - // it('setProxyStorage successfully', async () => { - // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - // proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) - // }) - // it('setProxyStorage should not be able to set again if already set', async () => { - // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - // await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) - // }) + beforeEach(async () => { + await consensus.initialize(initialValidator) + }) + it('setProxyStorage should fail if no address', async () => { + await consensus.setProxyStorage(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG) + }) + it('setProxyStorage should fail if not called by owner', async () => { + await consensus.setProxyStorage(proxyStorage.address, {from: nonOwner}).should.be.rejectedWith(ERROR_MSG) + // success + await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) + // should not be able to set again if already set + await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) + }) + it('setProxyStorage successfully', async () => { + await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) + }) + it('setProxyStorage should not be able to set again if already set', async () => { + await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) + }) }) describe('emitInitiateChange', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // await consensus.setFinalizedMock(false) - // }) - // it('should fail if not called by validator', async () => { - // await consensus.emitInitiateChange({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should fail if newValidatorSet is empty', async () => { - // await consensus.setShouldEmitInitiateChangeMock(true) - // await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should fail if `shouldEmitInitiateChange` is false', async () => { - // let mockSet = [firstCandidate, secondCandidate] - // await consensus.setNewValidatorSetMock(mockSet) - // await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should be successful and emit event', async () => { - // await consensus.setShouldEmitInitiateChangeMock(true) - // let mockSet = [firstCandidate, secondCandidate] - // await consensus.setNewValidatorSetMock(mockSet) - // let {logs} = await consensus.emitInitiateChange({from: initialValidator}).should.be.fulfilled - // false.should.be.equal(await consensus.shouldEmitInitiateChange()) - // logs.length.should.be.equal(1) - // logs[0].event.should.be.equal('InitiateChange') - // logs[0].args['newSet'].should.deep.equal(mockSet) - // }) + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + await consensus.setFinalizedMock(false) + }) + it('should fail if not called by validator', async () => { + await consensus.emitInitiateChange({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) + }) + it('should fail if newValidatorSet is empty', async () => { + await consensus.setShouldEmitInitiateChangeMock(true) + await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + }) + it('should fail if `shouldEmitInitiateChange` is false', async () => { + let mockSet = [firstCandidate, secondCandidate] + await consensus.setNewValidatorSetMock(mockSet) + await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + }) + it('should be successful and emit event', async () => { + await consensus.setShouldEmitInitiateChangeMock(true) + let mockSet = [firstCandidate, secondCandidate] + await consensus.setNewValidatorSetMock(mockSet) + let {logs} = await consensus.emitInitiateChange({from: initialValidator}).should.be.fulfilled + false.should.be.equal(await consensus.shouldEmitInitiateChange()) + logs.length.should.be.equal(1) + logs[0].event.should.be.equal('InitiateChange') + logs[0].args['newSet'].should.deep.equal(mockSet) + }) }) describe('finalizeChange', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // await consensus.setFinalizedMock(false) - // }) - // it('should only be called by SYSTEM_ADDRESS', async () => { - // await consensus.finalizeChange().should.be.rejectedWith(ERROR_MSG) - // await consensus.setSystemAddressMock(accounts[0], {from: owner}) - // await consensus.finalizeChange().should.be.fulfilled - // }) - // it('should set finalized to true', async () => { - // false.should.be.equal(await consensus.isFinalized()) - // await consensus.setSystemAddressMock(accounts[0]) - // await consensus.finalizeChange().should.be.fulfilled - // true.should.be.equal(await consensus.isFinalized()) - // }) - // it('should not update current validators set if new set is empty', async () => { - // let initialValidators = await consensus.getValidators() - // let mockSet = [] - // await consensus.setNewValidatorSetMock(mockSet) - // await consensus.setSystemAddressMock(accounts[0]) - // let {logs} = await consensus.finalizeChange().should.be.fulfilled - // let currentValidators = await consensus.getValidators() - // currentValidators.length.should.be.equal(1) - // currentValidators.should.deep.equal(initialValidators) - // logs.length.should.be.equal(0) - // }) - // it('should update current validators set', async () => { - // let mockSet = [firstCandidate, secondCandidate] - // await consensus.setNewValidatorSetMock(mockSet) - // await consensus.setSystemAddressMock(accounts[0]) - // let {logs} = await consensus.finalizeChange().should.be.fulfilled - // let currentValidators = await consensus.getValidators() - // currentValidators.length.should.be.equal(2) - // currentValidators.should.deep.equal(mockSet) - // logs[0].event.should.be.equal('ChangeFinalized') - // logs[0].args['newSet'].should.deep.equal(mockSet) - // }) + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + await consensus.setFinalizedMock(false) + }) + it('should only be called by SYSTEM_ADDRESS', async () => { + await consensus.finalizeChange().should.be.rejectedWith(ERROR_MSG) + await consensus.setSystemAddressMock(accounts[0], {from: owner}) + await consensus.finalizeChange().should.be.fulfilled + }) + it('should set finalized to true', async () => { + false.should.be.equal(await consensus.isFinalized()) + await consensus.setSystemAddressMock(accounts[0]) + await consensus.finalizeChange().should.be.fulfilled + true.should.be.equal(await consensus.isFinalized()) + }) + it('should not update current validators set if new set is empty', async () => { + let initialValidators = await consensus.getValidators() + let mockSet = [] + await consensus.setNewValidatorSetMock(mockSet) + await consensus.setSystemAddressMock(accounts[0]) + let {logs} = await consensus.finalizeChange().should.be.fulfilled + let currentValidators = await consensus.getValidators() + currentValidators.length.should.be.equal(1) + currentValidators.should.deep.equal(initialValidators) + logs.length.should.be.equal(0) + }) + it('should update current validators set', async () => { + let mockSet = [firstCandidate, secondCandidate] + await consensus.setNewValidatorSetMock(mockSet) + await consensus.setSystemAddressMock(accounts[0]) + let {logs} = await consensus.finalizeChange().should.be.fulfilled + let currentValidators = await consensus.getValidators() + currentValidators.length.should.be.equal(2) + currentValidators.should.deep.equal(mockSet) + logs[0].event.should.be.equal('ChangeFinalized') + logs[0].args['newSet'].should.deep.equal(mockSet) + }) }) describe('stake (fallback function)', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // }) - // describe('basic', async () => { - // it('should not allow zero stake', async () => { - // await consensus.send(0, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('less than minimum stake - should not be added to pending validators', async () => { - // await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // // contract balance should be updated - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // // sender stake amount should be updated - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // // pending validators should not be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // validator fee should not be set - // toBN(0).should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - // }) - // it('minimum stake amount', async () => { - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(firstCandidate) - // // default validator fee should be set - // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - // }) - // it('should allow more than minimum stake', async () => { - // await consensus.sendTransaction({from: firstCandidate, value: MORE_THAN_MIN_STAKE}).should.be.fulfilled - // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(firstCandidate) - // // default validator fee should be set - // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - // }) - // }) - // describe('advanced', async () => { - // it('minimum stake amount, in more than one transaction', async () => { - // // 1st stake - // await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + }) + describe('basic', async () => { + it('should not allow zero stake', async () => { + await consensus.send(0, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) + }) + it('less than minimum stake - should not be added to pending validators', async () => { + await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // contract balance should be updated + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // sender stake amount should be updated + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // pending validators should not be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // validator fee should not be set + toBN(0).should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + }) + it('minimum stake amount', async () => { + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + // default validator fee should be set + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + }) + it('should allow more than minimum stake', async () => { + await consensus.sendTransaction({from: firstCandidate, value: MORE_THAN_MIN_STAKE}).should.be.fulfilled + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + // default validator fee should be set + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + }) + }) + describe('advanced', async () => { + it('minimum stake amount, in more than one transaction', async () => { + // 1st stake + await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) - // // 2nd stake - // await consensus.sendTransaction({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(firstCandidate) - // }) + // 2nd stake + await consensus.sendTransaction({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + }) - // it('more than minimum stake amount, in more than one transaction', async () => { - // // 1st stake - // await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) + it('more than minimum stake amount, in more than one transaction', async () => { + // 1st stake + await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) - // // 2nd stake - // await consensus.sendTransaction({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled - // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(firstCandidate) - // }) + // 2nd stake + await consensus.sendTransaction({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + }) - // it('more than one validator', async () => { - // // add 1st validator - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // // add 2nd validator - // await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(2) - // }) - // it('multiple validators, multiple times', async () => { - // const expectedValidators = [] - // // add 1st validator - // expectedValidators.push(firstCandidate) - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // // add 2nd validator - // expectedValidators.push(secondCandidate) - // await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + it('more than one validator', async () => { + // add 1st validator + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + // add 2nd validator + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(2) + }) + it('multiple validators, multiple times', async () => { + const expectedValidators = [] + // add 1st validator + expectedValidators.push(firstCandidate) + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // add 2nd validator + expectedValidators.push(secondCandidate) + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) - // // doubling the stake for the 1st validator - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // doubling the stake for the 1st validator + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // // doubling the stake for the 2st validator - // await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) - // }) - // }) + // doubling the stake for the 2st validator + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + }) + }) }) describe('stake', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // }) - // describe('basic', async () => { - // it('should not allow zero stake', async () => { - // await consensus.stake({from: firstCandidate, value: 0}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('less than minimum stake - should not be added to pending validators', async () => { - // await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // // contract balance should be updated - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // // sender stake amount should be updated - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // // pending validators should not be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // }) - // it('minimum stake amount', async () => { - // await consensus.stake({ from: firstCandidate, value: MIN_STAKE }).should.be.fulfilled - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(firstCandidate) - // }) + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + }) + describe('basic', async () => { + it('should not allow zero stake', async () => { + await consensus.stake({from: firstCandidate, value: 0}).should.be.rejectedWith(ERROR_MSG) + }) + it('less than minimum stake - should not be added to pending validators', async () => { + await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // contract balance should be updated + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // sender stake amount should be updated + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // pending validators should not be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + }) + it('minimum stake amount', async () => { + await consensus.stake({ from: firstCandidate, value: MIN_STAKE }).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + }) - // it('should allow more than minimum stake', async () => { - // await consensus.stake({ from: firstCandidate, value: MORE_THAN_MIN_STAKE }).should.be.fulfilled + it('should allow more than minimum stake', async () => { + await consensus.stake({ from: firstCandidate, value: MORE_THAN_MIN_STAKE }).should.be.fulfilled - // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(firstCandidate) - // // default validator fee should be set - // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - // }) - // }) - // describe('advanced', async () => { - // it('minimum stake amount, in more than one transaction', async () => { - // // 1st stake - // await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + // default validator fee should be set + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + }) + }) + describe('advanced', async () => { + it('minimum stake amount, in more than one transaction', async () => { + // 1st stake + await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) - // // 2nd stake - // await consensus.stake({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(firstCandidate) - // }) + // 2nd stake + await consensus.stake({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + }) - // it('more than minimum stake amount, in more than one transaction', async () => { - // // 1st stake - // await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) + it('more than minimum stake amount, in more than one transaction', async () => { + // 1st stake + await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) - // // 2nd stake - // await consensus.stake({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled - // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(firstCandidate) - // }) + // 2nd stake + await consensus.stake({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + }) - // it('more than one validator', async () => { - // // add 1st validator - // await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // // add 2nd validator - // await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(2) - // }) + it('more than one validator', async () => { + // add 1st validator + await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + // add 2nd validator + await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(2) + }) - // it('multiple validators, multiple times', async () => { - // let expectedValidators = [] - // // add 1st validator - // expectedValidators.push(firstCandidate) - // await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // // add 2nd validator - // expectedValidators.push(secondCandidate) - // await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) + it('multiple validators, multiple times', async () => { + let expectedValidators = [] + // add 1st validator + expectedValidators.push(firstCandidate) + await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + // add 2nd validator + expectedValidators.push(secondCandidate) + await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) - // // doubling the stake for the 1st validator - // await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // doubling the stake for the 1st validator + await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // // doubling the stake for the 2st validator - // await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) - // }) - // }) + // doubling the stake for the 2st validator + await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + }) + }) }) describe('delegate', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // }) - // describe('basic', async () => { - // it('should not allow zero stake', async () => { - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: 0}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should fail if no staker address', async () => { - // await consensus.delegate(ZERO_ADDRESS, {from: firstDelegator, value: MORE_THAN_MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('less than minimum stake - should not be added to pending validators', async () => { - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // // contract balance should be updated - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // // sender stake amount should be updated - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // // delegated amount should be updated - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - // // pending validators should not be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // delegators list should be updated - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // }) - // it('minimum stake', async () => { - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - // // contract balance should be updated - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // // sender stake amount should be updated - // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // // delegated amount should be updated - // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - // // pending validators should be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(firstCandidate) - // // delegators list should be updated - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // }) - // }) - // describe('advanced', async () => { - // it('minimum stake amount, in more than one transaction', async () => { - // // 1st stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + }) + describe('basic', async () => { + it('should not allow zero stake', async () => { + await consensus.delegate(firstCandidate, {from: firstDelegator, value: 0}).should.be.rejectedWith(ERROR_MSG) + }) + it('should fail if no staker address', async () => { + await consensus.delegate(ZERO_ADDRESS, {from: firstDelegator, value: MORE_THAN_MIN_STAKE}).should.be.rejectedWith(ERROR_MSG) + }) + it('less than minimum stake - should not be added to pending validators', async () => { + await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // contract balance should be updated + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // sender stake amount should be updated + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // delegated amount should be updated + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // pending validators should not be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // delegators list should be updated + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + }) + it('minimum stake', async () => { + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + // contract balance should be updated + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // sender stake amount should be updated + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // delegated amount should be updated + MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // pending validators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + // delegators list should be updated + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + }) + }) + describe('advanced', async () => { + it('minimum stake amount, in more than one transaction', async () => { + // 1st stake + await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // // 2nd stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(firstCandidate) - // delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // }) - // it('more than one validator', async () => { - // // add 1st validator - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // // delegators list should be updated - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // // add 2nd validator - // await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(2) - // // delegators list should be updated - // delegators = await consensus.delegators(secondCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(secondCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) - // }) - // it('multiple times according to staked amount, in more than one transaction', async () => { - // // 1st stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // 2nd stake + await consensus.delegate(firstCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + }) + it('more than one validator', async () => { + // add 1st validator + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + // delegators list should be updated + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // add 2nd validator + await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(2) + // delegators list should be updated + delegators = await consensus.delegators(secondCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + delegatorsLength = await consensus.delegatorsLength(secondCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) + }) + it('multiple times according to staked amount, in more than one transaction', async () => { + // 1st stake + await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // // 2nd stake - added once - // let expectedValidators = [firstCandidate] - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(firstCandidate) - // delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // 2nd stake - added once + let expectedValidators = [firstCandidate] + await consensus.delegate(firstCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - // delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // }) - // }) + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + }) + }) }) describe('cycles and snapshots', async () => { @@ -598,51 +598,51 @@ contract('Consensus', async (accounts) => { await advanceBlocks(blocksToAdvance) true.should.be.equal(await consensus.hasCycleEnded()) }) - it('shouldTakeSnapshot', async () => { - let blocksToSnapshot = await consensus.getBlocksToSnapshot() - let lastSnapshotTakenAtBlock = await consensus.getLastSnapshotTakenAtBlock() - let currentBlockNumber = toBN(await web3.eth.getBlockNumber()) - let shouldTakeSnapshot = (currentBlockNumber.sub(lastSnapshotTakenAtBlock)).gte(blocksToSnapshot) - shouldTakeSnapshot.should.be.equal(await consensus.shouldTakeSnapshot()) - }) - it('getRandom', async () => { - let repeats = 25 - let randoms = [] - for (let i = 0; i < repeats; i++) { - randoms.push((await consensus.getRandom(0, SNAPSHOTS_PER_CYCLE)).toNumber()) - await advanceBlocks(1) - } - randoms.length.should.be.equal(repeats) - let distincts = [...new Set(randoms)] - distincts.length.should.be.greaterThan(1) - distincts.length.should.be.most(SNAPSHOTS_PER_CYCLE) - }) + // it('shouldTakeSnapshot', async () => { + // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // let lastSnapshotTakenAtBlock = await consensus.getLastSnapshotTakenAtBlock() + // let currentBlockNumber = toBN(await web3.eth.getBlockNumber()) + // let shouldTakeSnapshot = (currentBlockNumber.sub(lastSnapshotTakenAtBlock)).gte(blocksToSnapshot) + // shouldTakeSnapshot.should.be.equal(await consensus.shouldTakeSnapshot()) + // }) + // it('getRandom', async () => { + // let repeats = 25 + // let randoms = [] + // for (let i = 0; i < repeats; i++) { + // randoms.push((await consensus.getRandom(0, SNAPSHOTS_PER_CYCLE)).toNumber()) + // await advanceBlocks(1) + // } + // randoms.length.should.be.equal(repeats) + // let distincts = [...new Set(randoms)] + // distincts.length.should.be.greaterThan(1) + // distincts.length.should.be.most(SNAPSHOTS_PER_CYCLE) + // }) it('cycle function should only be called by BlockReward', async () => { await consensus.cycle().should.be.rejectedWith(ERROR_MSG) await proxyStorage.setBlockRewardMock(owner) await consensus.cycle().should.be.fulfilled }) - it('snapshot with less validators than MAX_VALIDATORS - entire set should be saved', async () => { - let expectedValidators = [] - for (let i = 1; i <= MAX_VALIDATORS - 1; i++) { - await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - expectedValidators.push(accounts[i-1]) - } - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(expectedValidators.length) - pendingValidators.should.deep.equal(expectedValidators) - let blocksToSnapshot = await consensus.getBlocksToSnapshot() - let snapshotId = await consensus.getNextSnapshotId() - await advanceBlocks(blocksToSnapshot) - await proxyStorage.setBlockRewardMock(owner) - await consensus.cycle().should.be.fulfilled - let snapshot = await consensus.getSnapshotAddresses(snapshotId) - snapshot.length.should.be.equal(expectedValidators.length) - snapshot.forEach(address => { - expectedValidators.splice(expectedValidators.indexOf(address), 1) - }) - expectedValidators.length.should.be.equal(0) - }) + // it('snapshot with less validators than MAX_VALIDATORS - entire set should be saved', async () => { + // let expectedValidators = [] + // for (let i = 1; i <= MAX_VALIDATORS - 1; i++) { + // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled + // expectedValidators.push(accounts[i-1]) + // } + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // let snapshotId = await consensus.getNextSnapshotId() + // await advanceBlocks(blocksToSnapshot) + // await proxyStorage.setBlockRewardMock(owner) + // await consensus.cycle().should.be.fulfilled + // let snapshot = await consensus.getSnapshotAddresses(snapshotId) + // snapshot.length.should.be.equal(expectedValidators.length) + // snapshot.forEach(address => { + // expectedValidators.splice(expectedValidators.indexOf(address), 1) + // }) + // expectedValidators.length.should.be.equal(0) + // }) // it('snapshot with exactly MAX_VALIDATORS validators - entire set should be saved', async () => { // let expectedValidators = [] // for (let i = 1; i <= MAX_VALIDATORS; i++) { @@ -688,484 +688,484 @@ contract('Consensus', async (accounts) => { }) describe('withdraw', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // }) - // describe('stakers', async () => { - // it('cannot withdraw zero', async () => { - // await consensus.methods['withdraw(uint256)'](ZERO_AMOUNT, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('cannot withdraw more than staked amount', async () => { - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // await consensus.methods['withdraw(uint256)'](MORE_THAN_MIN_STAKE).should.be.rejectedWith(ERROR_MSG) - // }) - // it('can withdraw all staked amount', async () => { - // // stake - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // // stake - // await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}) - // // withdraw - // await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}) - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // // pendingValidators should be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators.should.deep.equal([secondCandidate]) - // }) - // it('can withdraw less than staked amount', async () => { - // // stake - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // // withdraw - // await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) - // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - // let expectedValidators = [] - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // // pendingValidators should be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // }) - // it('can withdraw multiple times', async () => { - // // stake - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // // withdraw 1st time - // await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) - // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - // let expectedValidators = [] - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // withdraw 2nd time - // await consensus.withdraw(ONE_ETHER, {from: firstCandidate}) - // expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // }) - // }) - // describe('delegators', async () => { - // it('cannot withdraw zero', async () => { - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ZERO_AMOUNT, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('cannot withdraw if no staker address defined', async () => { - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - // await consensus.methods['withdraw(address,uint256)'](ZERO_ADDRESS, MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('cannot withdraw more than staked amount', async () => { - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MORE_THAN_MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('can withdraw all staked amount', async () => { - // // stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // stake - // await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // withdraw - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MIN_STAKE, {from: firstDelegator}) - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, secondCandidate)) - // // pendingValidators should be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators.should.deep.equal([secondCandidate]) - // // delegators list should be updated for firstCandidate - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(0) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(0)) - // // delegators list should be updated for secondCandidate - // delegators = await consensus.delegators(secondCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(secondCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) - // }) - // it('can withdraw less than staked amount', async () => { - // // stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // withdraw - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - // let expectedValidators = [] - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // // pendingValidators should be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // delegators list should be updated - // delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // }) - // it('can withdraw multiple times', async () => { - // // stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // withdraw 1st time - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - // let expectedValidators = [firstCandidate] - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // delegators list should be updated - // delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // // withdraw 2nd time - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - // expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // delegators list should be updated - // delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // }) - // }) + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + }) + describe('stakers', async () => { + it('cannot withdraw zero', async () => { + await consensus.methods['withdraw(uint256)'](ZERO_AMOUNT, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) + }) + it('cannot withdraw more than staked amount', async () => { + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + await consensus.methods['withdraw(uint256)'](MORE_THAN_MIN_STAKE).should.be.rejectedWith(ERROR_MSG) + }) + it('can withdraw all staked amount', async () => { + // stake + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // stake + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}) + // withdraw + await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}) + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // pendingValidators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators.should.deep.equal([secondCandidate]) + }) + it('can withdraw less than staked amount', async () => { + // stake + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // withdraw + await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) + let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + let expectedValidators = [] + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // pendingValidators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + }) + it('can withdraw multiple times', async () => { + // stake + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // withdraw 1st time + await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) + let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + let expectedValidators = [] + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // withdraw 2nd time + await consensus.withdraw(ONE_ETHER, {from: firstCandidate}) + expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + }) + }) + describe('delegators', async () => { + it('cannot withdraw zero', async () => { + await consensus.methods['withdraw(address,uint256)'](firstCandidate, ZERO_AMOUNT, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + }) + it('cannot withdraw if no staker address defined', async () => { + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + await consensus.methods['withdraw(address,uint256)'](ZERO_ADDRESS, MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + }) + it('cannot withdraw more than staked amount', async () => { + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + await consensus.methods['withdraw(address,uint256)'](firstCandidate, MORE_THAN_MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + }) + it('can withdraw all staked amount', async () => { + // stake + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // stake + await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}) + // withdraw + await consensus.methods['withdraw(address,uint256)'](firstCandidate, MIN_STAKE, {from: firstDelegator}) + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO_AMOUNT.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, secondCandidate)) + // pendingValidators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators.should.deep.equal([secondCandidate]) + // delegators list should be updated for firstCandidate + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(0) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(0)) + // delegators list should be updated for secondCandidate + delegators = await consensus.delegators(secondCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + delegatorsLength = await consensus.delegatorsLength(secondCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) + }) + it('can withdraw less than staked amount', async () => { + // stake + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // withdraw + await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + let expectedValidators = [] + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // pendingValidators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // delegators list should be updated + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + }) + it('can withdraw multiple times', async () => { + // stake + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // withdraw 1st time + await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + let expectedValidators = [firstCandidate] + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // delegators list should be updated + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // withdraw 2nd time + await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // delegators list should be updated + delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + }) + }) }) describe('setValidatorFee', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // }) - // it('should only be called by validator', async () => { - // decimals = await consensus.DECIMALS() - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - // let newValidatorFee = defaultValidatorFee.sub(toBN(0.01 * decimals)) - // await consensus.setValidatorFee(newValidatorFee, {from: initialValidator}).should.be.fulfilled - // newValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(initialValidator)) - // await consensus.setValidatorFee(newValidatorFee, {from: secondCandidate}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should only be able to set a valid fee', async () => { - // decimals = await consensus.DECIMALS() - // let i; - // for (i = 0; i <= 100; i++) { - // await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.fulfilled - // } - // await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - // }) + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + }) + it('should only be called by validator', async () => { + decimals = await consensus.DECIMALS() + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + let newValidatorFee = defaultValidatorFee.sub(toBN(0.01 * decimals)) + await consensus.setValidatorFee(newValidatorFee, {from: initialValidator}).should.be.fulfilled + newValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(initialValidator)) + await consensus.setValidatorFee(newValidatorFee, {from: secondCandidate}).should.be.rejectedWith(ERROR_MSG) + }) + it('should only be able to set a valid fee', async () => { + decimals = await consensus.DECIMALS() + let i; + for (i = 0; i <= 100; i++) { + await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.fulfilled + } + await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + }) }) describe('getDelegatorsForRewardDistribution', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // }) - // it('validator without delegators', async () => { - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(0) - // rewards.length.should.be.equal(0) - // }) - // describe('validator with one delegator', async () => { - // it('total delegated more than total staked - no fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let fee = toBN(0 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // it('total delegated less than total staked - no fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let fee = toBN(0 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // it('total delegated more than total staked - 100% fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let fee = toBN(1 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // it('total delegated less than total staked - 100% fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let fee = toBN(1 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // it('total delegated more than total staked - other fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let fee = toBN(0.225 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // it('total delegated less than total staked - other fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let fee = toBN(0.225 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // }) - // describe('validator with multiple delegators', async () => { - // it('total delegated more than total staked - no fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let fee = toBN(0 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // it('total delegated less than total staked - no fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let fee = toBN(0 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // it('total delegated more than total staked - 100% fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let fee = toBN(1 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // it('total delegated less than total staked - 100% fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let fee = toBN(1 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // it('total delegated more than total staked - other fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let fee = toBN(0.15 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // it('total delegated less than total staked - other fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let fee = toBN(0.15 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // }) - // it('validator with many delegators', async () => { - // decimals = await consensus.DECIMALS() - // let delegatorsCount = accounts.length - 2 - // let delegateAmountValue = parseInt(MIN_STAKE_AMOUNT * 0.99 / delegatorsCount) - // let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') - // let stakeAmountValue = MIN_STAKE_AMOUNT - delegateAmountValue * delegatorsCount - // let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') - // let fee = toBN(0.05 * decimals) - // let validator = accounts[1] - // await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled - // for (let i = 2; i < accounts.length; i++) { - // await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled - // } - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(delegatorsCount) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // for (let i = 0; i < delegatorsCount; i++) { - // delegators[i].should.be.equal(accounts[i + 2]) - // rewards[i].should.be.bignumber.equal(expectedReward) - // } - // }) + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + }) + it('validator without delegators', async () => { + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(0) + rewards.length.should.be.equal(0) + }) + describe('validator with one delegator', async () => { + it('total delegated more than total staked - no fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let fee = toBN(0 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + it('total delegated less than total staked - no fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let fee = toBN(0 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + it('total delegated more than total staked - 100% fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let fee = toBN(1 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + it('total delegated less than total staked - 100% fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let fee = toBN(1 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + it('total delegated more than total staked - other fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let fee = toBN(0.225 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + it('total delegated less than total staked - other fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let fee = toBN(0.225 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + }) + describe('validator with multiple delegators', async () => { + it('total delegated more than total staked - no fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let fee = toBN(0 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + it('total delegated less than total staked - no fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let fee = toBN(0 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + it('total delegated more than total staked - 100% fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let fee = toBN(1 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + it('total delegated less than total staked - 100% fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let fee = toBN(1 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + it('total delegated more than total staked - other fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let fee = toBN(0.15 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + it('total delegated less than total staked - other fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let fee = toBN(0.15 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + }) + it('validator with many delegators', async () => { + decimals = await consensus.DECIMALS() + let delegatorsCount = accounts.length - 2 + let delegateAmountValue = parseInt(MIN_STAKE_AMOUNT * 0.99 / delegatorsCount) + let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') + let stakeAmountValue = MIN_STAKE_AMOUNT - delegateAmountValue * delegatorsCount + let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') + let fee = toBN(0.05 * decimals) + let validator = accounts[1] + await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled + for (let i = 2; i < accounts.length; i++) { + await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled + } + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(delegatorsCount) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + for (let i = 0; i < delegatorsCount; i++) { + delegators[i].should.be.equal(accounts[i + 2]) + rewards[i].should.be.bignumber.equal(expectedReward) + } + }) }) describe('upgradeTo', async () => { - // let consensusOldImplementation, consensusNew - // let proxyStorageStub = accounts[3] - // beforeEach(async () => { - // consensus = await Consensus.new() - // consensusOldImplementation = consensus.address - // proxy = await EternalStorageProxy.new(proxyStorage.address, consensus.address) - // consensus = await Consensus.at(proxy.address) - // consensusNew = await Consensus.new() - // }) - // it('should only be called by ProxyStorage', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) - // let {logs} = await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // logs[0].event.should.be.equal('Upgraded') - // await proxy.setProxyStorageMock(proxyStorage.address) - // }) - // it('should change implementation address', async () => { - // consensusOldImplementation.should.be.equal(await proxy.getImplementation()) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // consensusNew.address.should.be.equal(await proxy.getImplementation()) - // }) - // it('should increment implementation version', async () => { - // let consensusOldVersion = await proxy.getVersion() - // let consensusNewVersion = consensusOldVersion.add(toBN(1)) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // consensusNewVersion.should.be.bignumber.equal(await proxy.getVersion()) - // }) - // it('should work after upgrade', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // consensusNew = await Consensus.at(proxy.address) - // false.should.be.equal(await consensusNew.isInitialized()) - // await consensusNew.initialize(initialValidator).should.be.fulfilled - // true.should.be.equal(await consensusNew.isInitialized()) - // }) - // it('should use same proxyStorage after upgrade', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // consensusNew = await Consensus.at(proxy.address) - // proxyStorageStub.should.be.equal(await consensusNew.getProxyStorage()) - // }) - // it('should use same storage after upgrade', async () => { - // await consensus.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // consensusNew = await Consensus.at(proxy.address) - // RANDOM_ADDRESS.should.be.equal(await consensus.getSystemAddress()) - // }) + let consensusOldImplementation, consensusNew + let proxyStorageStub = accounts[3] + beforeEach(async () => { + consensus = await Consensus.new() + consensusOldImplementation = consensus.address + proxy = await EternalStorageProxy.new(proxyStorage.address, consensus.address) + consensus = await Consensus.at(proxy.address) + consensusNew = await Consensus.new() + }) + it('should only be called by ProxyStorage', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) + let {logs} = await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + logs[0].event.should.be.equal('Upgraded') + await proxy.setProxyStorageMock(proxyStorage.address) + }) + it('should change implementation address', async () => { + consensusOldImplementation.should.be.equal(await proxy.getImplementation()) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + consensusNew.address.should.be.equal(await proxy.getImplementation()) + }) + it('should increment implementation version', async () => { + let consensusOldVersion = await proxy.getVersion() + let consensusNewVersion = consensusOldVersion.add(toBN(1)) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + consensusNewVersion.should.be.bignumber.equal(await proxy.getVersion()) + }) + it('should work after upgrade', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + consensusNew = await Consensus.at(proxy.address) + false.should.be.equal(await consensusNew.isInitialized()) + await consensusNew.initialize(initialValidator).should.be.fulfilled + true.should.be.equal(await consensusNew.isInitialized()) + }) + it('should use same proxyStorage after upgrade', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + consensusNew = await Consensus.at(proxy.address) + proxyStorageStub.should.be.equal(await consensusNew.getProxyStorage()) + }) + it('should use same storage after upgrade', async () => { + await consensus.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + consensusNew = await Consensus.at(proxy.address) + RANDOM_ADDRESS.should.be.equal(await consensus.getSystemAddress()) + }) }) }) From a02a0cc6658485849c76401cb9efd9f3e5d66e9f Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Thu, 20 Aug 2020 17:01:47 +0300 Subject: [PATCH 06/19] fixing total supply --- contracts/ConsensusUtils.sol | 24 ++++++++++---- contracts/test/BlockRewardMock.sol | 4 +++ test/consensus.test.js | 52 ++++++++++++++++++++++++++---- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/contracts/ConsensusUtils.sol b/contracts/ConsensusUtils.sol index f1abecf..ad2499a 100644 --- a/contracts/ConsensusUtils.sol +++ b/contracts/ConsensusUtils.sol @@ -97,8 +97,14 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { _delegatedAmountAdd(_staker, _validator, _amount); _stakeAmountAdd(_validator, _amount); - if (stakeAmount(_validator) >= getMinStake() && !isPendingValidator(_validator)) { - _pendingValidatorsAdd(_validator); + if (stakeAmount(_validator) >= getMinStake()) { + // _totalStakeAmountAdd(_amount); + if (!isPendingValidator(_validator)) { + _totalStakeAmountAdd(stakeAmount(_validator)); + _pendingValidatorsAdd(_validator); + } else { + _totalStakeAmountAdd(_amount); + } } } @@ -232,7 +238,7 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { } function _currentValidatorsAdd(address _address) internal { - _totalStakeAmountAddValidator(_address); + // _totalStakeAmountAddValidator(_address); addressArrayStorage[CURRENT_VALIDATORS].push(_address); } @@ -407,11 +413,15 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = _totalStake; } - function _totalStakeAmountAddValidator(address _address) internal { - uint256 stakedAmount = stakeAmount(_address); - uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))].add(stakedAmount); + // function _totalStakeAmountAddValidator(address _address) internal { + // uint256 stakedAmount = stakeAmount(_address); + // uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))].add(stakedAmount); + + // // uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = _totalStake; + // } - // uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = _totalStake; + function _totalStakeAmountAdd(uint256 _stakeAmount) internal { + uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))].add(_stakeAmount); } function shouldEmitInitiateChange() public view returns(bool) { diff --git a/contracts/test/BlockRewardMock.sol b/contracts/test/BlockRewardMock.sol index 82b3109..2be02a6 100644 --- a/contracts/test/BlockRewardMock.sol +++ b/contracts/test/BlockRewardMock.sol @@ -18,4 +18,8 @@ contract BlockRewardMock is BlockReward { function setShouldEmitRewardedOnCycleMock(bool _status) public { boolStorage[SHOULD_EMIT_REWARDED_ON_CYCLE] = _status; } + + function cycleMock() public { + IConsensus(ProxyStorage(getProxyStorage()).getConsensus()).cycle(); + } } diff --git a/test/consensus.test.js b/test/consensus.test.js index 2529a79..387e142 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -1,11 +1,12 @@ /* eslint-disable prefer-const */ +/* eslint-disable object-curly-spacing */ const Consensus = artifacts.require('ConsensusMock.sol') const ProxyStorage = artifacts.require('ProxyStorageMock.sol') const EternalStorageProxy = artifacts.require('EternalStorageProxyMock.sol') -const BlockReward = artifacts.require('BlockReward.sol') +const BlockReward = artifacts.require('BlockRewardMock.sol') const Voting = artifacts.require('Voting.sol') -const {ERROR_MSG, ZERO_AMOUNT, SYSTEM_ADDRESS, ZERO_ADDRESS, RANDOM_ADDRESS, advanceBlocks} = require('./helpers') -const {toBN, toWei, toChecksumAddress} = web3.utils +const { ERROR_MSG, ZERO_AMOUNT, SYSTEM_ADDRESS, ZERO_ADDRESS, RANDOM_ADDRESS, advanceBlocks } = require('./helpers') +const { toBN, toWei, toChecksumAddress } = web3.utils const MAX_VALIDATORS = 100 const MIN_STAKE_AMOUNT = 10000 @@ -72,6 +73,8 @@ contract('Consensus', async (accounts) => { toBN(MAX_VALIDATORS).should.be.bignumber.equal(await consensus.getMaxValidators()) toBN(CYCLE_DURATION_BLOCKS).should.be.bignumber.equal(await consensus.getCycleDurationBlocks()) toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) + toBN(0).should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) + toBN(0).should.be.bignumber.equal(await consensus.totalStakeAmount()) // toBN(CYCLE_DURATION_BLOCKS / SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getBlocksToSnapshot()) false.should.be.equal(await consensus.hasCycleEnded()) toBN(0).should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) @@ -95,6 +98,26 @@ contract('Consensus', async (accounts) => { validators.length.should.be.equal(1) validators[0].should.be.equal(initialValidator) }) + + it('initial validator is added to pending after sending fuse', async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + true.should.be.equal(await consensus.isFinalized()) + let validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(initialValidator) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + + await consensus.sendTransaction({from: initialValidator, value: MIN_STAKE}).should.be.fulfilled + + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(initialValidator) + + toBN(MIN_STAKE).should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) + toBN(MIN_STAKE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) }) describe('setProxyStorage', async () => { @@ -121,7 +144,7 @@ contract('Consensus', async (accounts) => { await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) }) }) - + describe('emitInitiateChange', async () => { beforeEach(async () => { await consensus.initialize(initialValidator) @@ -151,7 +174,7 @@ contract('Consensus', async (accounts) => { logs[0].args['newSet'].should.deep.equal(mockSet) }) }) - + describe('finalizeChange', async () => { beforeEach(async () => { await consensus.initialize(initialValidator) @@ -591,12 +614,29 @@ contract('Consensus', async (accounts) => { }) it('hasCycleEnded', async () => { false.should.be.equal(await consensus.hasCycleEnded()) + + let currentBlockNumber = await web3.eth.getBlockNumber() + let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() + let blocksToAdvance = currentCycleEndBlock.toNumber() - currentBlockNumber + + await advanceBlocks(blocksToAdvance) + true.should.be.equal(await consensus.hasCycleEnded()) + }) + + it('cycle', async () => { + false.should.be.equal(await consensus.hasCycleEnded()) + let currentBlockNumber = await web3.eth.getBlockNumber() let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() let blocksToAdvance = currentCycleEndBlock.toNumber() - currentBlockNumber - console.log({ currentBlockNumber, currentCycleEndBlock: currentCycleEndBlock.toNumber(), blocksToAdvance }) + // console.log({ currentBlockNumber, currentCycleEndBlock: currentCycleEndBlock.toNumber(), blocksToAdvance }) await advanceBlocks(blocksToAdvance) true.should.be.equal(await consensus.hasCycleEnded()) + + await consensus.sendTransaction({from: initialValidator, value: MIN_STAKE}).should.be.fulfilled + + await blockReward.cycleMock().should.be.fulfilled + false.should.be.equal(await consensus.hasCycleEnded()) }) // it('shouldTakeSnapshot', async () => { // let blocksToSnapshot = await consensus.getBlocksToSnapshot() From 3be134f4ae5054c933aa66416294c931b9480351 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Tue, 25 Aug 2020 20:17:38 +0300 Subject: [PATCH 07/19] no validators case --- contracts/BlockReward.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/BlockReward.sol b/contracts/BlockReward.sol index 296e5e9..043790b 100644 --- a/contracts/BlockReward.sol +++ b/contracts/BlockReward.sol @@ -188,6 +188,9 @@ contract BlockReward is EternalStorage, BlockRewardBase { uint256 stakeAmount = consensus.stakeAmount(_validator); uint256 totalStakeAmount = consensus.totalStakeAmount(); uint256 currentValidatorsLength = consensus.currentValidatorsLength(); + if (currentValidatorsLength == 0) { + return getBlockRewardAmount(); + } return getBlockRewardAmount().mul(stakeAmount).mul(currentValidatorsLength).div(totalStakeAmount); } From 7d3aef01c5039bd41890a2c71eac85f11ebba85c Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Wed, 26 Aug 2020 18:09:55 +0300 Subject: [PATCH 08/19] fix save --- contracts/Consensus.sol | 10 +++++++++- contracts/ConsensusUtils.sol | 12 ++++++++---- test/blockReward.test.js | 16 +++++++++++++++- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/contracts/Consensus.sol b/contracts/Consensus.sol index f8e18e3..7cf7497 100644 --- a/contracts/Consensus.sol +++ b/contracts/Consensus.sol @@ -77,8 +77,16 @@ contract Consensus is ConsensusUtils { _delegatedAmountSub(msg.sender, msg.sender, _amount); _stakeAmountSub(msg.sender, _amount); + if (stakeAmount(msg.sender) < getMinStake()) { - _pendingValidatorsRemove(msg.sender); + if (isPendingValidator(msg.sender)) { + _pendingValidatorsRemove(msg.sender); + _totalStakeAmountSub(stakeAmount(msg.sender)); + } + } else { + if (isPendingValidator(msg.sender)) { + _totalStakeAmountSub(_amount); + } } msg.sender.transfer(_amount); diff --git a/contracts/ConsensusUtils.sol b/contracts/ConsensusUtils.sol index ad2499a..451036a 100644 --- a/contracts/ConsensusUtils.sol +++ b/contracts/ConsensusUtils.sol @@ -84,6 +84,7 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { bytes32 internal constant WAS_PROXY_STORAGE_SET = keccak256(abi.encodePacked("wasProxyStorageSet")); bytes32 internal constant NEW_VALIDATOR_SET = keccak256(abi.encodePacked("newValidatorSet")); bytes32 internal constant SHOULD_EMIT_INITIATE_CHANGE = keccak256(abi.encodePacked("shouldEmitInitiateChange")); + bytes32 internal constant TOTAL_STAKE_AMOUNT = keccak256(abi.encodePacked("totalStakeAmount")); function _delegate(address _staker, uint256 _amount, address _validator) internal { require(_staker != address(0)); @@ -98,7 +99,6 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { _stakeAmountAdd(_validator, _amount); if (stakeAmount(_validator) >= getMinStake()) { - // _totalStakeAmountAdd(_amount); if (!isPendingValidator(_validator)) { _totalStakeAmountAdd(stakeAmount(_validator)); _pendingValidatorsAdd(_validator); @@ -306,7 +306,7 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { } function totalStakeAmount() public view returns(uint256) { - return uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))]; + return uintStorage[TOTAL_STAKE_AMOUNT]; } function _stakeAmountAdd(address _address, uint256 _amount) internal { @@ -410,7 +410,7 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { } function _setTotalStakeAmount(uint256 _totalStake) internal { - uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = _totalStake; + uintStorage[TOTAL_STAKE_AMOUNT] = _totalStake; } // function _totalStakeAmountAddValidator(address _address) internal { @@ -421,7 +421,11 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { // } function _totalStakeAmountAdd(uint256 _stakeAmount) internal { - uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))].add(_stakeAmount); + uintStorage[TOTAL_STAKE_AMOUNT] = uintStorage[TOTAL_STAKE_AMOUNT].add(_stakeAmount); + } + + function _totalStakeAmountSub(uint256 _stakeAmount) internal { + uintStorage[TOTAL_STAKE_AMOUNT] = uintStorage[TOTAL_STAKE_AMOUNT].sub(_stakeAmount); } function shouldEmitInitiateChange() public view returns(bool) { diff --git a/test/blockReward.test.js b/test/blockReward.test.js index fc495eb..59ec74b 100644 --- a/test/blockReward.test.js +++ b/test/blockReward.test.js @@ -1,4 +1,5 @@ /* eslint-disable prefer-const */ +/* eslint-disable object-curly-spacing */ const Consensus = artifacts.require('ConsensusMock.sol') const ProxyStorage = artifacts.require('ProxyStorageMock.sol') const EternalStorageProxy = artifacts.require('EternalStorageProxyMock.sol') @@ -249,12 +250,18 @@ contract('BlockReward', async (accounts) => { }) it('reward amount should update after BLOCKS_PER_YEAR and total yearly inflation should be calculated correctly', async () => { await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) - + await consensus.setTotalStakeAmountMock(0) + await consensus.sendTransaction({ from: accounts[3], value: minStakeAmount }).should.be.fulfilled + console.log(await consensus.currentValidatorsLength()) + console.log((await consensus.stakeAmount(accounts[3])).toString(10)) + console.log((await consensus.totalStakeAmount()).toString(10)) + console.log((await blockReward.getBlockRewardAmountPerValidator(accounts[3])).toString(10)) let decimals = await blockReward.DECIMALS() let initialSupply = await blockReward.getTotalSupply() let blocksPerYear = await blockReward.getBlocksPerYear() let inflation = await blockReward.getInflation() let blockRewardAmount = await blockReward.getBlockRewardAmount() + console.log(blockRewardAmount.toString(10)) // console.log(`initialSupply: ${initialSupply.div(decimals).toNumber()}, blockRewardAmount: ${blockRewardAmount.div(decimals).toNumber()}`) // each of the following calls advances a block @@ -309,6 +316,13 @@ contract('BlockReward', async (accounts) => { let BLOCKS_TO_REWARD = 10 let blockRewardAmount = await blockReward.getBlockRewardAmount() let expectedAmount = blockRewardAmount.mul(toBN(BLOCKS_TO_REWARD)) + let minStakeAmount = await consensus.getMinStake() + await consensus.sendTransaction({from: accounts[3], value: minStakeAmount}).should.be.fulfilled + + console.log(await consensus.currentValidatorsLength()) + console.log((await consensus.stakeAmount(accounts[3])).toString(10)) + console.log((await consensus.totalStakeAmount()).toString(10)) + // console.log((await blockReward.getBlockRewardAmountPerValidator(accounts[3])).toString(10)) await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) for (let i = 0; i < BLOCKS_TO_REWARD; i++) { From 370f69a0e57e52df26ba4810f7d9b4434eca9c87 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Sun, 30 Aug 2020 14:19:14 +0300 Subject: [PATCH 09/19] fix voting tests --- contracts/ConsensusUtils.sol | 14 +- contracts/test/ConsensusMock.sol | 4 + test/blockReward.test.js | 357 +++---- test/consensus.test.js | 1505 ++++++++++++++++-------------- test/helpers.js | 6 + test/voting.test.js | 270 +++--- 6 files changed, 1152 insertions(+), 1004 deletions(-) diff --git a/contracts/ConsensusUtils.sol b/contracts/ConsensusUtils.sol index 451036a..b540ee6 100644 --- a/contracts/ConsensusUtils.sol +++ b/contracts/ConsensusUtils.sol @@ -16,8 +16,9 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { uint256 public constant DECIMALS = 10 ** 18; uint256 public constant MAX_VALIDATORS = 100; uint256 public constant MIN_STAKE = 1e23; // 100,000 - uint256 public constant CYCLE_DURATION_BLOCKS = 120960; // 7 days [7*24*60*60/5] - uint256 public constant SNAPSHOTS_PER_CYCLE = 10; // snapshot each 1008 minutes [120960/10/60*5] + uint256 public constant MAX_STAKE = 5e24; // 5,000,000 + uint256 public constant CYCLE_DURATION_BLOCKS = 34560; // 48 hours [48*60*60/5] + uint256 public constant SNAPSHOTS_PER_CYCLE = 0; // snapshot each 288 minutes [34560/10/60*5] uint256 public constant DEFAULT_VALIDATOR_FEE = 1e17; // 10% /** @@ -97,6 +98,8 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { _delegatedAmountAdd(_staker, _validator, _amount); _stakeAmountAdd(_validator, _amount); + + require(stakeAmount(_validator) <= getMaxStake()); if (stakeAmount(_validator) >= getMinStake()) { if (!isPendingValidator(_validator)) { @@ -145,6 +148,13 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { return MIN_STAKE; } + /** + * returns maximum stake (wei) for a validator + */ + function getMaxStake() public pure returns(uint256) { + return MAX_STAKE; + } + /** * returns number of blocks per cycle (block time is 5 seconds) */ diff --git a/contracts/test/ConsensusMock.sol b/contracts/test/ConsensusMock.sol index 4ae4be1..1483d5c 100644 --- a/contracts/test/ConsensusMock.sol +++ b/contracts/test/ConsensusMock.sol @@ -45,6 +45,10 @@ contract ConsensusMock is Consensus { return 1e22; } + function getMaxStake() public pure returns(uint256) { + return 5e22; + } + function getCycleDurationBlocks() public pure returns(uint256) { return 120; } diff --git a/test/blockReward.test.js b/test/blockReward.test.js index 59ec74b..42e9a41 100644 --- a/test/blockReward.test.js +++ b/test/blockReward.test.js @@ -6,6 +6,7 @@ const EternalStorageProxy = artifacts.require('EternalStorageProxyMock.sol') const BlockReward = artifacts.require('BlockRewardMock.sol') const Voting = artifacts.require('Voting.sol') const { ERROR_MSG, ZERO_ADDRESS, RANDOM_ADDRESS } = require('./helpers') +const { ZERO, ONE, TWO, THREE, FOUR } = require('./helpers') const {toBN, toWei, toChecksumAddress} = web3.utils const INITIAL_SUPPLY = toWei(toBN(300000000000000000 || 0), 'gwei') @@ -51,135 +52,147 @@ contract('BlockReward', async (accounts) => { ) }) - describe('initialize', async () => { - it('default values', async () => { - await blockReward.initialize(INITIAL_SUPPLY) - owner.should.equal(await proxy.getOwner()) - toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await blockReward.getSystemAddress())) - let decimals = await blockReward.DECIMALS() - let initialSupply = await blockReward.getTotalSupply() - let blocksPerYear = await blockReward.getBlocksPerYear() - let inflation = await blockReward.getInflation() - - INITIAL_SUPPLY.should.be.bignumber.equal(initialSupply) - toBN(BLOCKS_PER_YEAR).should.be.bignumber.equal(blocksPerYear) - toBN(YEARLY_INFLATION_PERCENTAGE).should.be.bignumber.equal(inflation) - - let blockRewardAmount = (initialSupply.mul(decimals).mul(inflation).div(toBN(100))).div(blocksPerYear).div(decimals) - blockRewardAmount.should.be.bignumber.equal(await blockReward.getBlockRewardAmount()) - }) - }) + // describe('initialize', async () => { + // it('default values', async () => { + // await blockReward.initialize(INITIAL_SUPPLY) + // owner.should.equal(await proxy.getOwner()) + // toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await blockReward.getSystemAddress())) + // let decimals = await blockReward.DECIMALS() + // let initialSupply = await blockReward.getTotalSupply() + // let blocksPerYear = await blockReward.getBlocksPerYear() + // let inflation = await blockReward.getInflation() + + // INITIAL_SUPPLY.should.be.bignumber.equal(initialSupply) + // toBN(BLOCKS_PER_YEAR).should.be.bignumber.equal(blocksPerYear) + // toBN(YEARLY_INFLATION_PERCENTAGE).should.be.bignumber.equal(inflation) + + // let blockRewardAmount = (initialSupply.mul(decimals).mul(inflation).div(toBN(100))).div(blocksPerYear).div(decimals) + // blockRewardAmount.should.be.bignumber.equal(await blockReward.getBlockRewardAmount()) + // }) + // }) describe('reward', async () => { let minStakeAmount beforeEach(async () => { await blockReward.initialize(INITIAL_SUPPLY) minStakeAmount = await consensus.getMinStake() - await consensus.setTotalStakeAmountMock(minStakeAmount) + // await consensus.setTotalStakeAmountMock(ZERO) }) - // describe('#getBlockRewardAmountPerValidator', () => { - // let blockRewardAmount - // beforeEach(async () => { - // blockRewardAmount = await blockReward.getBlockRewardAmount() - // }) - // it('block reward with one validator', async () => { - // const minStakeAmount = await consensus.getMinStake() - // // await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) - - // const validator = accounts[1] - // await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - // const l = await consensus.currentValidatorsLength() - // console.log(l.toString(10)) - // console.log(blockRewardAmount.toString(10)) - // '1'.should.be.equal(l.toString(10)) - - // const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - // console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - // const expectedReward = blockRewardAmount.div(toBN(10)) - // expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) - // }) - - // it('block reward of one validator staking 100% of the total stake', async () => { - // const minStakeAmount = await consensus.getMinStake() - // await consensus.setTotalStakeAmountMock(minStakeAmount) - - // const validator = accounts[1] - // await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - // const l = await consensus.currentValidatorsLength() - // console.log(l.toString(10)) - // console.log(blockRewardAmount.toString(10)) - // '1'.should.be.equal(l.toString(10)) - - // const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - // console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - // const expectedReward = blockRewardAmount - // expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) - // }) - - // it('block reward of 1 validator of 2, staking 10% of the total stake', async () => { - // const minStakeAmount = await consensus.getMinStake() - // await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) - // await consensus.setCurrentValidatorsLengthMock(toBN(2)) - // const validator = accounts[1] - // await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - - // const l = await consensus.currentValidatorsLength() - // '2'.should.be.equal(l.toString(10)) - - // const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - // console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - - // // expected reward calculation - // const expectedReward = blockRewardAmount.div(toBN(10)).mul(toBN(2)) - // expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) - // }) - - // it('block reward of 1 validator of 2, staking 50% of the total stake', async () => { - // const minStakeAmount = await consensus.getMinStake() - // await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) - // await consensus.setCurrentValidatorsLengthMock(toBN(2)) - // const validator = accounts[1] - // await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - - // const l = await consensus.currentValidatorsLength() - // '2'.should.be.equal(l.toString(10)) - - // const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - // console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - - // // expected reward calculation - // const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) - // expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) - // }) - - // it('block reward does not changed if the propotion stays the same', async () => { - // const minStakeAmount = await consensus.getMinStake() - // await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) - // await consensus.setCurrentValidatorsLengthMock(toBN(2)) - // const validator = accounts[1] - // await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - - // const l = await consensus.currentValidatorsLength() - // '2'.should.be.equal(l.toString(10)) - - // const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - // console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - - // // total stake is 50 * minStakeAmount now - // await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(100))) - // // validator stake is 50 * minStakeAmount now - // await consensus.sendTransaction({ from: validator, value: minStakeAmount.mul(toBN(49)) }).should.be.fulfilled - - // // expected reward calculation - // const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) - // expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) - // }) - // }) + describe('#getBlockRewardAmountPerValidator', () => { + let blockRewardAmount + let validator, secondValidator + beforeEach(async () => { + blockRewardAmount = await blockReward.getBlockRewardAmount() + validator = accounts[1] + secondValidator = accounts[2] + }) + it('block reward with one validator', async () => { + const minStakeAmount = await consensus.getMinStake() + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + // await consensus.sendTransaction({ from: validator, value: minStakeAmount.mul(toBN(4)) }).should.be.fulfilled + + // mocking total supply + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) + const l = await consensus.currentValidatorsLength() + console.log(l.toString(10)) + console.log(blockRewardAmount.toString(10)) + '1'.should.be.equal(l.toString(10)) + + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + const expectedReward = blockRewardAmount.div(toBN(10)) + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) + + it('block reward of one validator staking 100% of the total stake', async () => { + const minStakeAmount = await consensus.getMinStake() + + const validator = accounts[1] + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + await consensus.setTotalStakeAmountMock(minStakeAmount) + + const l = await consensus.currentValidatorsLength() + console.log(l.toString(10)) + console.log(blockRewardAmount.toString(10)) + '1'.should.be.equal(l.toString(10)) + + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + const expectedReward = blockRewardAmount + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) + + it('block reward of 1 validator of 2, staking 10% of the total stake', async () => { + const minStakeAmount = await consensus.getMinStake() + const validator = accounts[1] + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) + await consensus.setCurrentValidatorsLengthMock(toBN(2)) + + const l = await consensus.currentValidatorsLength() + '2'.should.be.equal(l.toString(10)) + + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + + // expected reward calculation + const expectedReward = blockRewardAmount.div(toBN(10)).mul(toBN(2)) + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) + + it('block reward of 1 validator of 2, staking 50% of the total stake', async () => { + const minStakeAmount = await consensus.getMinStake() + + const validator = accounts[1] + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) + await consensus.setCurrentValidatorsLengthMock(toBN(2)) + + const l = await consensus.currentValidatorsLength() + '2'.should.be.equal(l.toString(10)) + + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + + // expected reward calculation + const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) + + it('block reward does not changed if the propotion stays the same', async () => { + const minStakeAmount = await consensus.getMinStake() + + const validator = accounts[1] + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) + await consensus.setCurrentValidatorsLengthMock(toBN(2)) + + const l = await consensus.currentValidatorsLength() + '2'.should.be.equal(l.toString(10)) + + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) + + // validator stake is 5 * minStakeAmount now + await consensus.sendTransaction({ from: validator, value: minStakeAmount.mul(toBN(4)) }).should.be.fulfilled + // total stake is 10 * minStakeAmount now + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) + + + // expected reward calculation + const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) + }) it('can only be called by system address', async () => { await blockReward.reward([accounts[3]], [0]).should.be.rejectedWith(ERROR_MSG) await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + await consensus.sendTransaction({from: owner, value: minStakeAmount}).should.be.fulfilled await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled }) it('should revert if input array contains more than one item', async () => { @@ -338,59 +351,59 @@ contract('BlockReward', async (accounts) => { }) }) - // describe('upgradeTo', async () => { - // let blockRewardOldImplementation, blockRewardNew - // let proxyStorageStub = accounts[3] - // beforeEach(async () => { - // blockReward = await BlockReward.new() - // blockRewardOldImplementation = blockReward.address - // proxy = await EternalStorageProxy.new(proxyStorage.address, blockReward.address) - // blockReward = await BlockReward.at(proxy.address) - // blockRewardNew = await BlockReward.new() - // }) - // it('should only be called by ProxyStorage', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(blockRewardNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) - // let {logs} = await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - // logs[0].event.should.be.equal('Upgraded') - // await proxy.setProxyStorageMock(proxyStorage.address) - // }) - // it('should change implementation address', async () => { - // blockRewardOldImplementation.should.be.equal(await proxy.getImplementation()) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // blockRewardNew.address.should.be.equal(await proxy.getImplementation()) - // }) - // it('should increment implementation version', async () => { - // let blockRewardOldVersion = await proxy.getVersion() - // let blockRewardNewVersion = blockRewardOldVersion.add(toBN(1)) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // blockRewardNewVersion.should.be.bignumber.equal(await proxy.getVersion()) - // }) - // it('should work after upgrade', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // blockRewardNew = await BlockReward.at(proxy.address) - // false.should.be.equal(await blockRewardNew.isInitialized()) - // await blockRewardNew.initialize(INITIAL_SUPPLY).should.be.fulfilled - // true.should.be.equal(await blockRewardNew.isInitialized()) - // }) - // it('should use same proxyStorage after upgrade', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - // blockRewardNew = await BlockReward.at(proxy.address) - // proxyStorageStub.should.be.equal(await blockRewardNew.getProxyStorage()) - // }) - // it('should use same storage after upgrade', async () => { - // await blockReward.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) - // blockRewardNew = await BlockReward.at(proxy.address) - // RANDOM_ADDRESS.should.be.equal(await blockReward.getSystemAddress()) - // }) - // }) + describe('upgradeTo', async () => { + let blockRewardOldImplementation, blockRewardNew + let proxyStorageStub = accounts[3] + beforeEach(async () => { + blockReward = await BlockReward.new() + blockRewardOldImplementation = blockReward.address + proxy = await EternalStorageProxy.new(proxyStorage.address, blockReward.address) + blockReward = await BlockReward.at(proxy.address) + blockRewardNew = await BlockReward.new() + }) + it('should only be called by ProxyStorage', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(blockRewardNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) + let {logs} = await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + logs[0].event.should.be.equal('Upgraded') + await proxy.setProxyStorageMock(proxyStorage.address) + }) + it('should change implementation address', async () => { + blockRewardOldImplementation.should.be.equal(await proxy.getImplementation()) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + blockRewardNew.address.should.be.equal(await proxy.getImplementation()) + }) + it('should increment implementation version', async () => { + let blockRewardOldVersion = await proxy.getVersion() + let blockRewardNewVersion = blockRewardOldVersion.add(toBN(1)) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + blockRewardNewVersion.should.be.bignumber.equal(await proxy.getVersion()) + }) + it('should work after upgrade', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + blockRewardNew = await BlockReward.at(proxy.address) + false.should.be.equal(await blockRewardNew.isInitialized()) + await blockRewardNew.initialize(INITIAL_SUPPLY).should.be.fulfilled + true.should.be.equal(await blockRewardNew.isInitialized()) + }) + it('should use same proxyStorage after upgrade', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + blockRewardNew = await BlockReward.at(proxy.address) + proxyStorageStub.should.be.equal(await blockRewardNew.getProxyStorage()) + }) + it('should use same storage after upgrade', async () => { + await blockReward.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(blockRewardNew.address, {from: proxyStorageStub}) + blockRewardNew = await BlockReward.at(proxy.address) + RANDOM_ADDRESS.should.be.equal(await blockReward.getSystemAddress()) + }) + }) }) diff --git a/test/consensus.test.js b/test/consensus.test.js index 387e142..c4b98b9 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -6,16 +6,20 @@ const EternalStorageProxy = artifacts.require('EternalStorageProxyMock.sol') const BlockReward = artifacts.require('BlockRewardMock.sol') const Voting = artifacts.require('Voting.sol') const { ERROR_MSG, ZERO_AMOUNT, SYSTEM_ADDRESS, ZERO_ADDRESS, RANDOM_ADDRESS, advanceBlocks } = require('./helpers') +const { ZERO, ONE, TWO, THREE, FOUR } = require('./helpers') const { toBN, toWei, toChecksumAddress } = web3.utils const MAX_VALIDATORS = 100 const MIN_STAKE_AMOUNT = 10000 +const MAX_STAKE_AMOUNT = 50000 const MULTIPLY_AMOUNT = 3 const MIN_STAKE = toWei(toBN(MIN_STAKE_AMOUNT), 'ether') -const ONE_ETHER = toWei(toBN(1), 'ether') -const TWO_ETHER = toWei(toBN(2), 'ether') +const MAX_STAKE = toWei(toBN(MAX_STAKE_AMOUNT), 'ether') +const ONE_ETHER = toWei(ONE, 'ether') +const TWO_ETHER = toWei(TWO, 'ether') const LESS_THAN_MIN_STAKE = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') const MORE_THAN_MIN_STAKE = toWei(toBN(MIN_STAKE_AMOUNT + 1), 'ether') +const MORE_THAN_MAX_STAKE = toWei(toBN(MAX_STAKE_AMOUNT + 1), 'ether') const CYCLE_DURATION_BLOCKS = 120 const SNAPSHOTS_PER_CYCLE = 10 @@ -64,21 +68,24 @@ contract('Consensus', async (accounts) => { describe('initialize', async () => { it('default values', async () => { + ZERO.should.be.bignumber.equal(await consensus.currentValidatorsLength()) await consensus.initialize(initialValidator) await consensus.setProxyStorage(proxyStorage.address) owner.should.equal(await proxy.getOwner()) toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await consensus.getSystemAddress())) true.should.be.equal(await consensus.isFinalized()) MIN_STAKE.should.be.bignumber.equal(await consensus.getMinStake()) + MAX_STAKE.should.be.bignumber.equal(await consensus.getMaxStake()) toBN(MAX_VALIDATORS).should.be.bignumber.equal(await consensus.getMaxValidators()) toBN(CYCLE_DURATION_BLOCKS).should.be.bignumber.equal(await consensus.getCycleDurationBlocks()) toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) - toBN(0).should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) - toBN(0).should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) // toBN(CYCLE_DURATION_BLOCKS / SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getBlocksToSnapshot()) false.should.be.equal(await consensus.hasCycleEnded()) - toBN(0).should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) - toBN(0).should.be.bignumber.equal(await consensus.getNextSnapshotId()) + ZERO.should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) + ZERO.should.be.bignumber.equal(await consensus.getNextSnapshotId()) + ONE.should.be.bignumber.equal(await consensus.currentValidatorsLength()) let validators = await consensus.getValidators() validators.length.should.be.equal(1) validators[0].should.be.equal(initialValidator) @@ -120,101 +127,101 @@ contract('Consensus', async (accounts) => { }) }) - describe('setProxyStorage', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - }) - it('setProxyStorage should fail if no address', async () => { - await consensus.setProxyStorage(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG) - }) - it('setProxyStorage should fail if not called by owner', async () => { - await consensus.setProxyStorage(proxyStorage.address, {from: nonOwner}).should.be.rejectedWith(ERROR_MSG) - // success - await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) - // should not be able to set again if already set - await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) - }) - it('setProxyStorage successfully', async () => { - await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) - }) - it('setProxyStorage should not be able to set again if already set', async () => { - await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) - }) - }) + // describe('setProxyStorage', async () => { + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // }) + // it('setProxyStorage should fail if no address', async () => { + // await consensus.setProxyStorage(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG) + // }) + // it('setProxyStorage should fail if not called by owner', async () => { + // await consensus.setProxyStorage(proxyStorage.address, {from: nonOwner}).should.be.rejectedWith(ERROR_MSG) + // // success + // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + // proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) + // // should not be able to set again if already set + // await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) + // }) + // it('setProxyStorage successfully', async () => { + // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + // proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) + // }) + // it('setProxyStorage should not be able to set again if already set', async () => { + // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + // await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) + // }) + // }) - describe('emitInitiateChange', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - await consensus.setFinalizedMock(false) - }) - it('should fail if not called by validator', async () => { - await consensus.emitInitiateChange({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) - }) - it('should fail if newValidatorSet is empty', async () => { - await consensus.setShouldEmitInitiateChangeMock(true) - await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - }) - it('should fail if `shouldEmitInitiateChange` is false', async () => { - let mockSet = [firstCandidate, secondCandidate] - await consensus.setNewValidatorSetMock(mockSet) - await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - }) - it('should be successful and emit event', async () => { - await consensus.setShouldEmitInitiateChangeMock(true) - let mockSet = [firstCandidate, secondCandidate] - await consensus.setNewValidatorSetMock(mockSet) - let {logs} = await consensus.emitInitiateChange({from: initialValidator}).should.be.fulfilled - false.should.be.equal(await consensus.shouldEmitInitiateChange()) - logs.length.should.be.equal(1) - logs[0].event.should.be.equal('InitiateChange') - logs[0].args['newSet'].should.deep.equal(mockSet) - }) - }) + // describe('emitInitiateChange', async () => { + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // await consensus.setFinalizedMock(false) + // }) + // it('should fail if not called by validator', async () => { + // await consensus.emitInitiateChange({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should fail if newValidatorSet is empty', async () => { + // await consensus.setShouldEmitInitiateChangeMock(true) + // await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should fail if `shouldEmitInitiateChange` is false', async () => { + // let mockSet = [firstCandidate, secondCandidate] + // await consensus.setNewValidatorSetMock(mockSet) + // await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should be successful and emit event', async () => { + // await consensus.setShouldEmitInitiateChangeMock(true) + // let mockSet = [firstCandidate, secondCandidate] + // await consensus.setNewValidatorSetMock(mockSet) + // let {logs} = await consensus.emitInitiateChange({from: initialValidator}).should.be.fulfilled + // false.should.be.equal(await consensus.shouldEmitInitiateChange()) + // logs.length.should.be.equal(1) + // logs[0].event.should.be.equal('InitiateChange') + // logs[0].args['newSet'].should.deep.equal(mockSet) + // }) + // }) - describe('finalizeChange', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - await consensus.setFinalizedMock(false) - }) - it('should only be called by SYSTEM_ADDRESS', async () => { - await consensus.finalizeChange().should.be.rejectedWith(ERROR_MSG) - await consensus.setSystemAddressMock(accounts[0], {from: owner}) - await consensus.finalizeChange().should.be.fulfilled - }) - it('should set finalized to true', async () => { - false.should.be.equal(await consensus.isFinalized()) - await consensus.setSystemAddressMock(accounts[0]) - await consensus.finalizeChange().should.be.fulfilled - true.should.be.equal(await consensus.isFinalized()) - }) - it('should not update current validators set if new set is empty', async () => { - let initialValidators = await consensus.getValidators() - let mockSet = [] - await consensus.setNewValidatorSetMock(mockSet) - await consensus.setSystemAddressMock(accounts[0]) - let {logs} = await consensus.finalizeChange().should.be.fulfilled - let currentValidators = await consensus.getValidators() - currentValidators.length.should.be.equal(1) - currentValidators.should.deep.equal(initialValidators) - logs.length.should.be.equal(0) - }) - it('should update current validators set', async () => { - let mockSet = [firstCandidate, secondCandidate] - await consensus.setNewValidatorSetMock(mockSet) - await consensus.setSystemAddressMock(accounts[0]) - let {logs} = await consensus.finalizeChange().should.be.fulfilled - let currentValidators = await consensus.getValidators() - currentValidators.length.should.be.equal(2) - currentValidators.should.deep.equal(mockSet) - logs[0].event.should.be.equal('ChangeFinalized') - logs[0].args['newSet'].should.deep.equal(mockSet) - }) - }) + // describe('finalizeChange', async () => { + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // await consensus.setFinalizedMock(false) + // }) + // it('should only be called by SYSTEM_ADDRESS', async () => { + // await consensus.finalizeChange().should.be.rejectedWith(ERROR_MSG) + // await consensus.setSystemAddressMock(accounts[0], {from: owner}) + // await consensus.finalizeChange().should.be.fulfilled + // }) + // it('should set finalized to true', async () => { + // false.should.be.equal(await consensus.isFinalized()) + // await consensus.setSystemAddressMock(accounts[0]) + // await consensus.finalizeChange().should.be.fulfilled + // true.should.be.equal(await consensus.isFinalized()) + // }) + // it('should not update current validators set if new set is empty', async () => { + // let initialValidators = await consensus.getValidators() + // let mockSet = [] + // await consensus.setNewValidatorSetMock(mockSet) + // await consensus.setSystemAddressMock(accounts[0]) + // let {logs} = await consensus.finalizeChange().should.be.fulfilled + // let currentValidators = await consensus.getValidators() + // currentValidators.length.should.be.equal(1) + // currentValidators.should.deep.equal(initialValidators) + // logs.length.should.be.equal(0) + // }) + // it('should update current validators set', async () => { + // let mockSet = [firstCandidate, secondCandidate] + // await consensus.setNewValidatorSetMock(mockSet) + // await consensus.setSystemAddressMock(accounts[0]) + // let {logs} = await consensus.finalizeChange().should.be.fulfilled + // let currentValidators = await consensus.getValidators() + // currentValidators.length.should.be.equal(2) + // currentValidators.should.deep.equal(mockSet) + // logs[0].event.should.be.equal('ChangeFinalized') + // logs[0].args['newSet'].should.deep.equal(mockSet) + // }) + // }) describe('stake (fallback function)', async () => { beforeEach(async () => { @@ -231,16 +238,18 @@ contract('Consensus', async (accounts) => { LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) // sender stake amount should be updated LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) // pending validators should not be updated let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(0) // validator fee should not be set - toBN(0).should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) }) it('minimum stake amount', async () => { await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) @@ -252,6 +261,23 @@ contract('Consensus', async (accounts) => { await consensus.sendTransaction({from: firstCandidate, value: MORE_THAN_MIN_STAKE}).should.be.fulfilled MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + // default validator fee should be set + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + }) + + it('should allow the maximum stake', async () => { + ZERO.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + await consensus.sendTransaction({from: firstCandidate, value: MAX_STAKE}).should.be.fulfilled + MAX_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MAX_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) @@ -259,6 +285,10 @@ contract('Consensus', async (accounts) => { let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) }) + + it('should not allow more the maximum stake', async () => { + await consensus.sendTransaction({from: firstCandidate, value: MORE_THAN_MAX_STAKE}).should.be.rejectedWith(ERROR_MSG) + }) }) describe('advanced', async () => { it('minimum stake amount, in more than one transaction', async () => { @@ -266,6 +296,8 @@ contract('Consensus', async (accounts) => { await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(0) @@ -273,6 +305,7 @@ contract('Consensus', async (accounts) => { await consensus.sendTransaction({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) @@ -283,6 +316,7 @@ contract('Consensus', async (accounts) => { await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(0) @@ -290,6 +324,7 @@ contract('Consensus', async (accounts) => { await consensus.sendTransaction({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) @@ -314,6 +349,7 @@ contract('Consensus', async (accounts) => { pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) // add 2nd validator expectedValidators.push(secondCandidate) await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled @@ -321,20 +357,23 @@ contract('Consensus', async (accounts) => { pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) // doubling the stake for the 1st validator await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) - MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.mul(THREE).should.be.bignumber.equal(await consensus.totalStakeAmount()) // doubling the stake for the 2st validator await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) - MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + MIN_STAKE.mul(FOUR).should.be.bignumber.equal(await consensus.totalStakeAmount()) }) }) }) @@ -354,6 +393,7 @@ contract('Consensus', async (accounts) => { LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) // sender stake amount should be updated LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) // pending validators should not be updated let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(0) @@ -362,6 +402,7 @@ contract('Consensus', async (accounts) => { await consensus.stake({ from: firstCandidate, value: MIN_STAKE }).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) @@ -372,6 +413,7 @@ contract('Consensus', async (accounts) => { MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) @@ -379,6 +421,25 @@ contract('Consensus', async (accounts) => { let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) }) + + it('should allow the maximum stake', async () => { + ZERO.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + await consensus.stake({from: firstCandidate, value: MAX_STAKE}).should.be.fulfilled + MAX_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MAX_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + // default validator fee should be set + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + }) + + it('should not allow more the maximum stake', async () => { + await consensus.stake({from: firstCandidate, value: MORE_THAN_MAX_STAKE}).should.be.rejectedWith(ERROR_MSG) + }) }) describe('advanced', async () => { it('minimum stake amount, in more than one transaction', async () => { @@ -386,6 +447,7 @@ contract('Consensus', async (accounts) => { await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(0) @@ -393,6 +455,7 @@ contract('Consensus', async (accounts) => { await consensus.stake({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) @@ -403,6 +466,7 @@ contract('Consensus', async (accounts) => { await consensus.stake({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(0) @@ -410,6 +474,7 @@ contract('Consensus', async (accounts) => { await consensus.stake({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) @@ -418,10 +483,14 @@ contract('Consensus', async (accounts) => { it('more than one validator', async () => { // add 1st validator await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) // add 2nd validator await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(2) }) @@ -431,12 +500,16 @@ contract('Consensus', async (accounts) => { // add 1st validator expectedValidators.push(firstCandidate) await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) // add 2nd validator expectedValidators.push(secondCandidate) await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) @@ -446,14 +519,16 @@ contract('Consensus', async (accounts) => { pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) - MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.mul(THREE).should.be.bignumber.equal(await consensus.totalStakeAmount()) // doubling the stake for the 2st validator await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) - MIN_STAKE.mul(toBN(2)).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + MIN_STAKE.mul(FOUR).should.be.bignumber.equal(await consensus.totalStakeAmount()) }) }) }) @@ -478,6 +553,7 @@ contract('Consensus', async (accounts) => { LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) // delegated amount should be updated LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) // pending validators should not be updated let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(0) @@ -497,6 +573,7 @@ contract('Consensus', async (accounts) => { MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) // delegated amount should be updated MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) // pending validators should be updated let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) @@ -509,6 +586,33 @@ contract('Consensus', async (accounts) => { delegatorsLength.should.be.bignumber.equal(toBN(1)) firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) }) + + it('should allow the maximum stake', async () => { + ZERO.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MAX_STAKE}).should.be.fulfilled + + MAX_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // sender stake amount should be updated + MAX_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // delegated amount should be updated + MAX_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // pending validators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + // delegators list should be updated + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + }) + + it('should not allow more the maximum stake', async () => { + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MORE_THAN_MAX_STAKE}).should.be.rejectedWith(ERROR_MSG) + }) }) describe('advanced', async () => { it('minimum stake amount, in more than one transaction', async () => { @@ -517,6 +621,7 @@ contract('Consensus', async (accounts) => { LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(0) let delegators = await consensus.delegators(firstCandidate) @@ -531,6 +636,7 @@ contract('Consensus', async (accounts) => { MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) @@ -544,6 +650,8 @@ contract('Consensus', async (accounts) => { it('more than one validator', async () => { // add 1st validator await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) // delegators list should be updated @@ -555,6 +663,8 @@ contract('Consensus', async (accounts) => { firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) // add 2nd validator await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(2) // delegators list should be updated @@ -570,6 +680,8 @@ contract('Consensus', async (accounts) => { await consensus.delegate(firstCandidate, {from: firstDelegator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(0) @@ -585,6 +697,7 @@ contract('Consensus', async (accounts) => { await consensus.delegate(firstCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) @@ -597,6 +710,8 @@ contract('Consensus', async (accounts) => { firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) delegators = await consensus.delegators(firstCandidate) delegators.length.should.be.equal(1) delegators[0].should.be.equal(firstDelegator) @@ -607,605 +722,605 @@ contract('Consensus', async (accounts) => { }) }) - describe('cycles and snapshots', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - }) - it('hasCycleEnded', async () => { - false.should.be.equal(await consensus.hasCycleEnded()) + // describe('cycles and snapshots', async () => { + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // }) + // it('hasCycleEnded', async () => { + // false.should.be.equal(await consensus.hasCycleEnded()) - let currentBlockNumber = await web3.eth.getBlockNumber() - let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() - let blocksToAdvance = currentCycleEndBlock.toNumber() - currentBlockNumber + // let currentBlockNumber = await web3.eth.getBlockNumber() + // let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() + // let blocksToAdvance = currentCycleEndBlock.toNumber() - currentBlockNumber - await advanceBlocks(blocksToAdvance) - true.should.be.equal(await consensus.hasCycleEnded()) - }) + // await advanceBlocks(blocksToAdvance) + // true.should.be.equal(await consensus.hasCycleEnded()) + // }) - it('cycle', async () => { - false.should.be.equal(await consensus.hasCycleEnded()) + // it('cycle', async () => { + // false.should.be.equal(await consensus.hasCycleEnded()) - let currentBlockNumber = await web3.eth.getBlockNumber() - let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() - let blocksToAdvance = currentCycleEndBlock.toNumber() - currentBlockNumber - // console.log({ currentBlockNumber, currentCycleEndBlock: currentCycleEndBlock.toNumber(), blocksToAdvance }) - await advanceBlocks(blocksToAdvance) - true.should.be.equal(await consensus.hasCycleEnded()) + // let currentBlockNumber = await web3.eth.getBlockNumber() + // let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() + // let blocksToAdvance = currentCycleEndBlock.toNumber() - currentBlockNumber + // // console.log({ currentBlockNumber, currentCycleEndBlock: currentCycleEndBlock.toNumber(), blocksToAdvance }) + // await advanceBlocks(blocksToAdvance) + // true.should.be.equal(await consensus.hasCycleEnded()) - await consensus.sendTransaction({from: initialValidator, value: MIN_STAKE}).should.be.fulfilled + // await consensus.sendTransaction({from: initialValidator, value: MIN_STAKE}).should.be.fulfilled - await blockReward.cycleMock().should.be.fulfilled - false.should.be.equal(await consensus.hasCycleEnded()) - }) - // it('shouldTakeSnapshot', async () => { - // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // let lastSnapshotTakenAtBlock = await consensus.getLastSnapshotTakenAtBlock() - // let currentBlockNumber = toBN(await web3.eth.getBlockNumber()) - // let shouldTakeSnapshot = (currentBlockNumber.sub(lastSnapshotTakenAtBlock)).gte(blocksToSnapshot) - // shouldTakeSnapshot.should.be.equal(await consensus.shouldTakeSnapshot()) - // }) - // it('getRandom', async () => { - // let repeats = 25 - // let randoms = [] - // for (let i = 0; i < repeats; i++) { - // randoms.push((await consensus.getRandom(0, SNAPSHOTS_PER_CYCLE)).toNumber()) - // await advanceBlocks(1) - // } - // randoms.length.should.be.equal(repeats) - // let distincts = [...new Set(randoms)] - // distincts.length.should.be.greaterThan(1) - // distincts.length.should.be.most(SNAPSHOTS_PER_CYCLE) - // }) - it('cycle function should only be called by BlockReward', async () => { - await consensus.cycle().should.be.rejectedWith(ERROR_MSG) - await proxyStorage.setBlockRewardMock(owner) - await consensus.cycle().should.be.fulfilled - }) - // it('snapshot with less validators than MAX_VALIDATORS - entire set should be saved', async () => { - // let expectedValidators = [] - // for (let i = 1; i <= MAX_VALIDATORS - 1; i++) { - // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - // expectedValidators.push(accounts[i-1]) - // } - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // let snapshotId = await consensus.getNextSnapshotId() - // await advanceBlocks(blocksToSnapshot) - // await proxyStorage.setBlockRewardMock(owner) - // await consensus.cycle().should.be.fulfilled - // let snapshot = await consensus.getSnapshotAddresses(snapshotId) - // snapshot.length.should.be.equal(expectedValidators.length) - // snapshot.forEach(address => { - // expectedValidators.splice(expectedValidators.indexOf(address), 1) - // }) - // expectedValidators.length.should.be.equal(0) - // }) - // it('snapshot with exactly MAX_VALIDATORS validators - entire set should be saved', async () => { - // let expectedValidators = [] - // for (let i = 1; i <= MAX_VALIDATORS; i++) { - // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - // expectedValidators.push(accounts[i-1]) - // } - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // let snapshotId = await consensus.getNextSnapshotId() - // await advanceBlocks(blocksToSnapshot) - // await proxyStorage.setBlockRewardMock(owner) - // await consensus.cycle().should.be.fulfilled - // let snapshot = await consensus.getSnapshotAddresses(snapshotId) - // snapshot.length.should.be.equal(expectedValidators.length) - // snapshot.forEach(address => { - // expectedValidators.splice(expectedValidators.indexOf(address), 1) - // }) - // expectedValidators.length.should.be.equal(0) - // }) - // it('snapshot with more validators than MAX_VALIDATORS - random set should be saved', async () => { - // let expectedValidators = [] - // for (let i = 1; i <= MAX_VALIDATORS + 1; i++) { - // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - // expectedValidators.push(accounts[i-1]) - // } - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // let snapshotId = await consensus.getNextSnapshotId() - // await advanceBlocks(blocksToSnapshot) - // await proxyStorage.setBlockRewardMock(owner) - // await consensus.cycle().should.be.fulfilled - // let snapshot = await consensus.getSnapshotAddresses(snapshotId) - // snapshot.length.should.be.equal(MAX_VALIDATORS) - // snapshot.forEach(address => { - // expectedValidators.splice(expectedValidators.indexOf(address), 1) - // }) - // expectedValidators.length.should.be.equal(pendingValidators.length - MAX_VALIDATORS) - // }) - }) + // await blockReward.cycleMock().should.be.fulfilled + // false.should.be.equal(await consensus.hasCycleEnded()) + // }) + // // it('shouldTakeSnapshot', async () => { + // // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // // let lastSnapshotTakenAtBlock = await consensus.getLastSnapshotTakenAtBlock() + // // let currentBlockNumber = toBN(await web3.eth.getBlockNumber()) + // // let shouldTakeSnapshot = (currentBlockNumber.sub(lastSnapshotTakenAtBlock)).gte(blocksToSnapshot) + // // shouldTakeSnapshot.should.be.equal(await consensus.shouldTakeSnapshot()) + // // }) + // // it('getRandom', async () => { + // // let repeats = 25 + // // let randoms = [] + // // for (let i = 0; i < repeats; i++) { + // // randoms.push((await consensus.getRandom(0, SNAPSHOTS_PER_CYCLE)).toNumber()) + // // await advanceBlocks(1) + // // } + // // randoms.length.should.be.equal(repeats) + // // let distincts = [...new Set(randoms)] + // // distincts.length.should.be.greaterThan(1) + // // distincts.length.should.be.most(SNAPSHOTS_PER_CYCLE) + // // }) + // it('cycle function should only be called by BlockReward', async () => { + // await consensus.cycle().should.be.rejectedWith(ERROR_MSG) + // await proxyStorage.setBlockRewardMock(owner) + // await consensus.cycle().should.be.fulfilled + // }) + // // it('snapshot with less validators than MAX_VALIDATORS - entire set should be saved', async () => { + // // let expectedValidators = [] + // // for (let i = 1; i <= MAX_VALIDATORS - 1; i++) { + // // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled + // // expectedValidators.push(accounts[i-1]) + // // } + // // pendingValidators = await consensus.pendingValidators() + // // pendingValidators.length.should.be.equal(expectedValidators.length) + // // pendingValidators.should.deep.equal(expectedValidators) + // // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // // let snapshotId = await consensus.getNextSnapshotId() + // // await advanceBlocks(blocksToSnapshot) + // // await proxyStorage.setBlockRewardMock(owner) + // // await consensus.cycle().should.be.fulfilled + // // let snapshot = await consensus.getSnapshotAddresses(snapshotId) + // // snapshot.length.should.be.equal(expectedValidators.length) + // // snapshot.forEach(address => { + // // expectedValidators.splice(expectedValidators.indexOf(address), 1) + // // }) + // // expectedValidators.length.should.be.equal(0) + // // }) + // // it('snapshot with exactly MAX_VALIDATORS validators - entire set should be saved', async () => { + // // let expectedValidators = [] + // // for (let i = 1; i <= MAX_VALIDATORS; i++) { + // // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled + // // expectedValidators.push(accounts[i-1]) + // // } + // // pendingValidators = await consensus.pendingValidators() + // // pendingValidators.length.should.be.equal(expectedValidators.length) + // // pendingValidators.should.deep.equal(expectedValidators) + // // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // // let snapshotId = await consensus.getNextSnapshotId() + // // await advanceBlocks(blocksToSnapshot) + // // await proxyStorage.setBlockRewardMock(owner) + // // await consensus.cycle().should.be.fulfilled + // // let snapshot = await consensus.getSnapshotAddresses(snapshotId) + // // snapshot.length.should.be.equal(expectedValidators.length) + // // snapshot.forEach(address => { + // // expectedValidators.splice(expectedValidators.indexOf(address), 1) + // // }) + // // expectedValidators.length.should.be.equal(0) + // // }) + // // it('snapshot with more validators than MAX_VALIDATORS - random set should be saved', async () => { + // // let expectedValidators = [] + // // for (let i = 1; i <= MAX_VALIDATORS + 1; i++) { + // // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled + // // expectedValidators.push(accounts[i-1]) + // // } + // // pendingValidators = await consensus.pendingValidators() + // // pendingValidators.length.should.be.equal(expectedValidators.length) + // // pendingValidators.should.deep.equal(expectedValidators) + // // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // // let snapshotId = await consensus.getNextSnapshotId() + // // await advanceBlocks(blocksToSnapshot) + // // await proxyStorage.setBlockRewardMock(owner) + // // await consensus.cycle().should.be.fulfilled + // // let snapshot = await consensus.getSnapshotAddresses(snapshotId) + // // snapshot.length.should.be.equal(MAX_VALIDATORS) + // // snapshot.forEach(address => { + // // expectedValidators.splice(expectedValidators.indexOf(address), 1) + // // }) + // // expectedValidators.length.should.be.equal(pendingValidators.length - MAX_VALIDATORS) + // // }) + // }) - describe('withdraw', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - }) - describe('stakers', async () => { - it('cannot withdraw zero', async () => { - await consensus.methods['withdraw(uint256)'](ZERO_AMOUNT, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) - }) - it('cannot withdraw more than staked amount', async () => { - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - await consensus.methods['withdraw(uint256)'](MORE_THAN_MIN_STAKE).should.be.rejectedWith(ERROR_MSG) - }) - it('can withdraw all staked amount', async () => { - // stake - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // stake - await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}) - // withdraw - await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}) - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // pendingValidators should be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators.should.deep.equal([secondCandidate]) - }) - it('can withdraw less than staked amount', async () => { - // stake - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // withdraw - await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) - let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - let expectedValidators = [] - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // pendingValidators should be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - }) - it('can withdraw multiple times', async () => { - // stake - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // withdraw 1st time - await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) - let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - let expectedValidators = [] - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - // withdraw 2nd time - await consensus.withdraw(ONE_ETHER, {from: firstCandidate}) - expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - }) - }) - describe('delegators', async () => { - it('cannot withdraw zero', async () => { - await consensus.methods['withdraw(address,uint256)'](firstCandidate, ZERO_AMOUNT, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - }) - it('cannot withdraw if no staker address defined', async () => { - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - await consensus.methods['withdraw(address,uint256)'](ZERO_ADDRESS, MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - }) - it('cannot withdraw more than staked amount', async () => { - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - await consensus.methods['withdraw(address,uint256)'](firstCandidate, MORE_THAN_MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - }) - it('can withdraw all staked amount', async () => { - // stake - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // stake - await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}) - // withdraw - await consensus.methods['withdraw(address,uint256)'](firstCandidate, MIN_STAKE, {from: firstDelegator}) - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - ZERO_AMOUNT.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, secondCandidate)) - // pendingValidators should be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators.should.deep.equal([secondCandidate]) - // delegators list should be updated for firstCandidate - let delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(0) - let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(0)) - // delegators list should be updated for secondCandidate - delegators = await consensus.delegators(secondCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - delegatorsLength = await consensus.delegatorsLength(secondCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) - }) - it('can withdraw less than staked amount', async () => { - // stake - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // withdraw - await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - let expectedValidators = [] - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // pendingValidators should be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - // delegators list should be updated - let delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - }) - it('can withdraw multiple times', async () => { - // stake - await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // withdraw 1st time - await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - let expectedValidators = [firstCandidate] - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - // delegators list should be updated - let delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // withdraw 2nd time - await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') - expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - // delegators list should be updated - delegators = await consensus.delegators(firstCandidate) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - delegatorsLength = await consensus.delegatorsLength(firstCandidate) - delegatorsLength.should.be.bignumber.equal(toBN(1)) - firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - }) - }) - }) + // describe('withdraw', async () => { + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // }) + // describe('stakers', async () => { + // it('cannot withdraw zero', async () => { + // await consensus.methods['withdraw(uint256)'](ZERO_AMOUNT, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('cannot withdraw more than staked amount', async () => { + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // await consensus.methods['withdraw(uint256)'](MORE_THAN_MIN_STAKE).should.be.rejectedWith(ERROR_MSG) + // }) + // it('can withdraw all staked amount', async () => { + // // stake + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // // stake + // await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}) + // // withdraw + // await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}) + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // // pendingValidators should be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators.should.deep.equal([secondCandidate]) + // }) + // it('can withdraw less than staked amount', async () => { + // // stake + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // // withdraw + // await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) + // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + // let expectedValidators = [] + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // // pendingValidators should be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // }) + // it('can withdraw multiple times', async () => { + // // stake + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // // withdraw 1st time + // await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) + // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + // let expectedValidators = [] + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // withdraw 2nd time + // await consensus.withdraw(ONE_ETHER, {from: firstCandidate}) + // expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // }) + // }) + // describe('delegators', async () => { + // it('cannot withdraw zero', async () => { + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ZERO_AMOUNT, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('cannot withdraw if no staker address defined', async () => { + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + // await consensus.methods['withdraw(address,uint256)'](ZERO_ADDRESS, MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('cannot withdraw more than staked amount', async () => { + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MORE_THAN_MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('can withdraw all staked amount', async () => { + // // stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // stake + // await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // withdraw + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MIN_STAKE, {from: firstDelegator}) + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, secondCandidate)) + // // pendingValidators should be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators.should.deep.equal([secondCandidate]) + // // delegators list should be updated for firstCandidate + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(0) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(0)) + // // delegators list should be updated for secondCandidate + // delegators = await consensus.delegators(secondCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(secondCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) + // }) + // it('can withdraw less than staked amount', async () => { + // // stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // withdraw + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + // let expectedValidators = [] + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // // pendingValidators should be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // delegators list should be updated + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // }) + // it('can withdraw multiple times', async () => { + // // stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // withdraw 1st time + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + // let expectedValidators = [firstCandidate] + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // delegators list should be updated + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // // withdraw 2nd time + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + // expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // delegators list should be updated + // delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // }) + // }) + // }) - describe('setValidatorFee', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - }) - it('should only be called by validator', async () => { - decimals = await consensus.DECIMALS() - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - let newValidatorFee = defaultValidatorFee.sub(toBN(0.01 * decimals)) - await consensus.setValidatorFee(newValidatorFee, {from: initialValidator}).should.be.fulfilled - newValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(initialValidator)) - await consensus.setValidatorFee(newValidatorFee, {from: secondCandidate}).should.be.rejectedWith(ERROR_MSG) - }) - it('should only be able to set a valid fee', async () => { - decimals = await consensus.DECIMALS() - let i; - for (i = 0; i <= 100; i++) { - await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.fulfilled - } - await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - }) - }) + // describe('setValidatorFee', async () => { + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // }) + // it('should only be called by validator', async () => { + // decimals = await consensus.DECIMALS() + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + // let newValidatorFee = defaultValidatorFee.sub(toBN(0.01 * decimals)) + // await consensus.setValidatorFee(newValidatorFee, {from: initialValidator}).should.be.fulfilled + // newValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(initialValidator)) + // await consensus.setValidatorFee(newValidatorFee, {from: secondCandidate}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('should only be able to set a valid fee', async () => { + // decimals = await consensus.DECIMALS() + // let i; + // for (i = 0; i <= 100; i++) { + // await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.fulfilled + // } + // await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + // }) + // }) - describe('getDelegatorsForRewardDistribution', async () => { - beforeEach(async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - }) - it('validator without delegators', async () => { - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(0) - rewards.length.should.be.equal(0) - }) - describe('validator with one delegator', async () => { - it('total delegated more than total staked - no fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let fee = toBN(0 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - it('total delegated less than total staked - no fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let fee = toBN(0 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - it('total delegated more than total staked - 100% fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let fee = toBN(1 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - it('total delegated less than total staked - 100% fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let fee = toBN(1 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - it('total delegated more than total staked - other fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let fee = toBN(0.225 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - it('total delegated less than total staked - other fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - let fee = toBN(0.225 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(1) - delegators[0].should.be.equal(firstDelegator) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - rewards[0].should.be.bignumber.equal(expectedReward) - }) - }) - describe('validator with multiple delegators', async () => { - it('total delegated more than total staked - no fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let fee = toBN(0 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - it('total delegated less than total staked - no fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let fee = toBN(0 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - it('total delegated more than total staked - 100% fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let fee = toBN(1 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - it('total delegated less than total staked - 100% fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let fee = toBN(1 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - it('total delegated more than total staked - other fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let fee = toBN(0.15 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - it('total delegated less than total staked - other fee', async () => { - decimals = await consensus.DECIMALS() - let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - let fee = toBN(0.15 * decimals) - await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(2) - delegators[0].should.be.equal(firstDelegator) - delegators[1].should.be.equal(secondDelegator) - rewards.length.should.be.equal(delegators.length) - rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - }) - }) - it('validator with many delegators', async () => { - decimals = await consensus.DECIMALS() - let delegatorsCount = accounts.length - 2 - let delegateAmountValue = parseInt(MIN_STAKE_AMOUNT * 0.99 / delegatorsCount) - let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') - let stakeAmountValue = MIN_STAKE_AMOUNT - delegateAmountValue * delegatorsCount - let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') - let fee = toBN(0.05 * decimals) - let validator = accounts[1] - await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled - for (let i = 2; i < accounts.length; i++) { - await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled - } - await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - let validatorFee = await consensus.validatorFee(firstCandidate) - let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - delegators.length.should.be.equal(delegatorsCount) - rewards.length.should.be.equal(delegators.length) - let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - for (let i = 0; i < delegatorsCount; i++) { - delegators[i].should.be.equal(accounts[i + 2]) - rewards[i].should.be.bignumber.equal(expectedReward) - } - }) - }) + // describe('getDelegatorsForRewardDistribution', async () => { + // beforeEach(async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // }) + // it('validator without delegators', async () => { + // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(0) + // rewards.length.should.be.equal(0) + // }) + // describe('validator with one delegator', async () => { + // it('total delegated more than total staked - no fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let fee = toBN(0 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // it('total delegated less than total staked - no fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let fee = toBN(0 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // it('total delegated more than total staked - 100% fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let fee = toBN(1 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // it('total delegated less than total staked - 100% fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let fee = toBN(1 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // it('total delegated more than total staked - other fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let fee = toBN(0.225 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // it('total delegated less than total staked - other fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + // let fee = toBN(0.225 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // rewards[0].should.be.bignumber.equal(expectedReward) + // }) + // }) + // describe('validator with multiple delegators', async () => { + // it('total delegated more than total staked - no fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let fee = toBN(0 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // it('total delegated less than total staked - no fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let fee = toBN(0 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // it('total delegated more than total staked - 100% fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let fee = toBN(1 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // it('total delegated less than total staked - 100% fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let fee = toBN(1 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // it('total delegated more than total staked - other fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let fee = toBN(0.15 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // it('total delegated less than total staked - other fee', async () => { + // decimals = await consensus.DECIMALS() + // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + // let fee = toBN(0.15 * decimals) + // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(2) + // delegators[0].should.be.equal(firstDelegator) + // delegators[1].should.be.equal(secondDelegator) + // rewards.length.should.be.equal(delegators.length) + // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + // }) + // }) + // it('validator with many delegators', async () => { + // decimals = await consensus.DECIMALS() + // let delegatorsCount = accounts.length - 2 + // let delegateAmountValue = parseInt(MIN_STAKE_AMOUNT * 0.99 / delegatorsCount) + // let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') + // let stakeAmountValue = MIN_STAKE_AMOUNT - delegateAmountValue * delegatorsCount + // let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') + // let fee = toBN(0.05 * decimals) + // let validator = accounts[1] + // await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled + // for (let i = 2; i < accounts.length; i++) { + // await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled + // } + // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + // let validatorFee = await consensus.validatorFee(firstCandidate) + // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + // delegators.length.should.be.equal(delegatorsCount) + // rewards.length.should.be.equal(delegators.length) + // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + // for (let i = 0; i < delegatorsCount; i++) { + // delegators[i].should.be.equal(accounts[i + 2]) + // rewards[i].should.be.bignumber.equal(expectedReward) + // } + // }) + // }) - describe('upgradeTo', async () => { - let consensusOldImplementation, consensusNew - let proxyStorageStub = accounts[3] - beforeEach(async () => { - consensus = await Consensus.new() - consensusOldImplementation = consensus.address - proxy = await EternalStorageProxy.new(proxyStorage.address, consensus.address) - consensus = await Consensus.at(proxy.address) - consensusNew = await Consensus.new() - }) - it('should only be called by ProxyStorage', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) - let {logs} = await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - logs[0].event.should.be.equal('Upgraded') - await proxy.setProxyStorageMock(proxyStorage.address) - }) - it('should change implementation address', async () => { - consensusOldImplementation.should.be.equal(await proxy.getImplementation()) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - consensusNew.address.should.be.equal(await proxy.getImplementation()) - }) - it('should increment implementation version', async () => { - let consensusOldVersion = await proxy.getVersion() - let consensusNewVersion = consensusOldVersion.add(toBN(1)) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - consensusNewVersion.should.be.bignumber.equal(await proxy.getVersion()) - }) - it('should work after upgrade', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - consensusNew = await Consensus.at(proxy.address) - false.should.be.equal(await consensusNew.isInitialized()) - await consensusNew.initialize(initialValidator).should.be.fulfilled - true.should.be.equal(await consensusNew.isInitialized()) - }) - it('should use same proxyStorage after upgrade', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - consensusNew = await Consensus.at(proxy.address) - proxyStorageStub.should.be.equal(await consensusNew.getProxyStorage()) - }) - it('should use same storage after upgrade', async () => { - await consensus.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - consensusNew = await Consensus.at(proxy.address) - RANDOM_ADDRESS.should.be.equal(await consensus.getSystemAddress()) - }) - }) + // describe('upgradeTo', async () => { + // let consensusOldImplementation, consensusNew + // let proxyStorageStub = accounts[3] + // beforeEach(async () => { + // consensus = await Consensus.new() + // consensusOldImplementation = consensus.address + // proxy = await EternalStorageProxy.new(proxyStorage.address, consensus.address) + // consensus = await Consensus.at(proxy.address) + // consensusNew = await Consensus.new() + // }) + // it('should only be called by ProxyStorage', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) + // let {logs} = await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // logs[0].event.should.be.equal('Upgraded') + // await proxy.setProxyStorageMock(proxyStorage.address) + // }) + // it('should change implementation address', async () => { + // consensusOldImplementation.should.be.equal(await proxy.getImplementation()) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // consensusNew.address.should.be.equal(await proxy.getImplementation()) + // }) + // it('should increment implementation version', async () => { + // let consensusOldVersion = await proxy.getVersion() + // let consensusNewVersion = consensusOldVersion.add(toBN(1)) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // consensusNewVersion.should.be.bignumber.equal(await proxy.getVersion()) + // }) + // it('should work after upgrade', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // consensusNew = await Consensus.at(proxy.address) + // false.should.be.equal(await consensusNew.isInitialized()) + // await consensusNew.initialize(initialValidator).should.be.fulfilled + // true.should.be.equal(await consensusNew.isInitialized()) + // }) + // it('should use same proxyStorage after upgrade', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // consensusNew = await Consensus.at(proxy.address) + // proxyStorageStub.should.be.equal(await consensusNew.getProxyStorage()) + // }) + // it('should use same storage after upgrade', async () => { + // await consensus.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + // consensusNew = await Consensus.at(proxy.address) + // RANDOM_ADDRESS.should.be.equal(await consensus.getSystemAddress()) + // }) + // }) }) diff --git a/test/helpers.js b/test/helpers.js index 4f91b71..c23d92e 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -13,6 +13,12 @@ exports.ERROR_MSG_OPCODE = 'VM Exception while processing transaction: invalid o exports.INVALID_ARGUMENTS = 'Invalid number of arguments to Solidity function' exports.RANDOM_ADDRESS = '0xc0ffee254729296a45a3885639AC7E10F9d54979' +exports.ZERO = toBN(0) +exports.ONE = toBN(1) +exports.TWO = toBN(2) +exports.THREE = toBN(3) +exports.FOUR = toBN(4) + exports.advanceTime = (seconds) => { return new Promise((resolve, reject) => { web3.currentProvider.send({ diff --git a/test/voting.test.js b/test/voting.test.js index 47a2cf3..713691a 100644 --- a/test/voting.test.js +++ b/test/voting.test.js @@ -326,7 +326,7 @@ contract('Voting', async (accounts) => { let currentBlock = toBN(await web3.eth.getBlockNumber()) let voteStartBlock = await voting.getStartBlock(firstBallotId) let blocksToAdvance = voteStartBlock.sub(currentBlock) - await advanceBlocks(blocksToAdvance.toNumber()) + await advanceBlocks(blocksToAdvance.toNumber() + 1) true.should.be.equal(await voting.isActiveBallot(firstBallotId)) true.should.be.equal(await voting.isActiveBallot(secondBallotId)) false.should.be.equal(await voting.isActiveBallot(thirdBallotId)) @@ -417,7 +417,7 @@ contract('Voting', async (accounts) => { // advance until 3rd ballot is open currentBlock = toBN(await web3.eth.getBlockNumber()) voteStartBlock = await voting.getStartBlock(thirdBallotId) - await advanceBlocks(voteStartBlock.sub(currentBlock).toNumber()) + await advanceBlocks(voteStartBlock.sub(currentBlock).toNumber() + 1) true.should.be.equal(await voting.isActiveBallot(firstBallotId)) true.should.be.equal(await voting.isActiveBallot(secondBallotId)) true.should.be.equal(await voting.isActiveBallot(thirdBallotId)) @@ -559,137 +559,137 @@ contract('Voting', async (accounts) => { }) }) - describe('finalize', async () => { - let currentValidators - beforeEach(async () => { - await voting.initialize().should.be.fulfilled - voteStartAfterNumberOfCycles = 1 - voteCyclesDuration = 10 - currentValidators = await consensus.getValidators() - }) - it('should change to proposed value successfully if quorum is reached', async () => { - let id = await voting.getNextBallotId() - let proposedValue = RANDOM_ADDRESS - let contractType = CONTRACT_TYPES.BLOCK_REWARD - await voting.newBallot(voteStartAfterNumberOfCycles, voteCyclesDuration, contractType, proposedValue, 'description', {from: validators[0]}).should.be.fulfilled - let currentBlock = toBN(await web3.eth.getBlockNumber()) - let voteStartBlock = await voting.getStartBlock(id) - let blocksToAdvance = voteStartBlock.sub(currentBlock) - await advanceBlocks(blocksToAdvance.toNumber()) - await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[0]}).should.be.fulfilled - await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[1]}).should.be.fulfilled - await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[2]}).should.be.fulfilled - let voteEndBlock = await voting.getEndBlock(id) - blocksToAdvance = voteEndBlock.sub(currentBlock).add(toBN(1)) - await advanceBlocks(blocksToAdvance.toNumber()) - await proxyStorage.setConsensusMock(owner) - let {logs} = await voting.onCycleEnd(currentValidators).should.be.fulfilled - logs.length.should.be.equal(1) - logs[0].event.should.be.equal('BallotFinalized') - logs[0].args['id'].should.be.bignumber.equal(id) - let ballotInfo = await voting.getBallotInfo(id, validators[0]) - ballotInfo.startBlock.should.be.bignumber.equal(voteStartBlock) - ballotInfo.endBlock.should.be.bignumber.equal(voteEndBlock) - ballotInfo.isFinalized.should.be.equal(true) - ballotInfo.proposedValue.should.be.equal(proposedValue) - ballotInfo.contractType.should.be.bignumber.equal(toBN(contractType)) - ballotInfo.creator.should.be.equal(validators[0]) - ballotInfo.description.should.be.equal('description') - ballotInfo.canBeFinalizedNow.should.be.equal(false) - ballotInfo.alreadyVoted.should.be.equal(true) - toBN(QUORUM_STATES.ACCEPTED).should.be.bignumber.equal(await voting.getQuorumState(id)) - proposedValue.should.be.equal(await (await EternalStorageProxy.at(await proxyStorage.getBlockReward())).getImplementation()) - }) - it('should not change to proposed value if quorum is not reached', async () => { - let id = await voting.getNextBallotId() - let proposedValue = RANDOM_ADDRESS - let contractType = CONTRACT_TYPES.BLOCK_REWARD - await voting.newBallot(voteStartAfterNumberOfCycles, voteCyclesDuration, contractType, proposedValue, 'description', {from: validators[0]}).should.be.fulfilled - let currentBlock = toBN(await web3.eth.getBlockNumber()) - let voteStartBlock = await voting.getStartBlock(id) - let blocksToAdvance = voteStartBlock.sub(currentBlock) - await advanceBlocks(blocksToAdvance.toNumber()) - await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[0]}).should.be.fulfilled - await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[1]}).should.be.fulfilled - await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[2]}).should.be.fulfilled - let voteEndBlock = await voting.getEndBlock(id) - blocksToAdvance = voteEndBlock.sub(currentBlock).add(toBN(1)) - await advanceBlocks(blocksToAdvance.toNumber()) - await proxyStorage.setConsensusMock(owner) - let {logs} = await voting.onCycleEnd(currentValidators).should.be.fulfilled - logs.length.should.be.equal(1) - logs[0].event.should.be.equal('BallotFinalized') - logs[0].args['id'].should.be.bignumber.equal(id) - let ballotInfo = await voting.getBallotInfo(id, validators[0]) - ballotInfo.startBlock.should.be.bignumber.equal(voteStartBlock) - ballotInfo.endBlock.should.be.bignumber.equal(voteEndBlock) - ballotInfo.isFinalized.should.be.equal(true) - ballotInfo.proposedValue.should.be.equal(proposedValue) - ballotInfo.contractType.should.be.bignumber.equal(toBN(contractType)) - ballotInfo.creator.should.be.equal(validators[0]) - ballotInfo.description.should.be.equal('description') - ballotInfo.canBeFinalizedNow.should.be.equal(false) - ballotInfo.alreadyVoted.should.be.equal(true) - toBN(QUORUM_STATES.REJECTED).should.be.bignumber.equal(await voting.getQuorumState(id)) - proposedValue.should.not.be.equal(await (await EternalStorageProxy.at(await proxyStorage.getBlockReward())).getImplementation()) - }) - }) - - describe('upgradeTo', async () => { - let votingOldImplementation, votingNew - let proxyStorageStub = accounts[13] - beforeEach(async () => { - voting = await Voting.new() - votingOldImplementation = voting.address - proxy = await EternalStorageProxy.new(proxyStorage.address, voting.address) - voting = await Voting.at(proxy.address) - votingNew = await Voting.new() - }) - it('should only be called by ProxyStorage', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(votingNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) - let {logs} = await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - logs[0].event.should.be.equal('Upgraded') - await proxy.setProxyStorageMock(proxyStorage.address) - }) - it('should change implementation address', async () => { - votingOldImplementation.should.be.equal(await proxy.getImplementation()) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - votingNew.address.should.be.equal(await proxy.getImplementation()) - }) - it('should increment implementation version', async () => { - let votingOldVersion = await proxy.getVersion() - let votingNewVersion = votingOldVersion.add(toBN(1)) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - votingNewVersion.should.be.bignumber.equal(await proxy.getVersion()) - }) - it('should work after upgrade', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - await proxy.setProxyStorageMock(proxyStorage.address) - votingNew = await Voting.at(proxy.address) - false.should.be.equal(await votingNew.isInitialized()) - await votingNew.initialize().should.be.fulfilled - true.should.be.equal(await votingNew.isInitialized()) - }) - it('should use same proxyStorage after upgrade', async () => { - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - votingNew = await Voting.at(proxy.address) - proxyStorageStub.should.be.equal(await votingNew.getProxyStorage()) - }) - it('should use same storage after upgrade', async () => { - let nextBallotId = await voting.getNextBallotId() - let newValue = nextBallotId.toNumber() + 1 - await voting.setNextBallotIdMock(newValue) - await proxy.setProxyStorageMock(proxyStorageStub) - await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - votingNew = await Voting.at(proxy.address) - toBN(newValue).should.be.bignumber.equal(await votingNew.getNextBallotId()) - }) - }) + // describe('finalize', async () => { + // let currentValidators + // beforeEach(async () => { + // await voting.initialize().should.be.fulfilled + // voteStartAfterNumberOfCycles = 1 + // voteCyclesDuration = 10 + // currentValidators = await consensus.getValidators() + // }) + // it('should change to proposed value successfully if quorum is reached', async () => { + // let id = await voting.getNextBallotId() + // let proposedValue = RANDOM_ADDRESS + // let contractType = CONTRACT_TYPES.BLOCK_REWARD + // await voting.newBallot(voteStartAfterNumberOfCycles, voteCyclesDuration, contractType, proposedValue, 'description', {from: validators[0]}).should.be.fulfilled + // let currentBlock = toBN(await web3.eth.getBlockNumber()) + // let voteStartBlock = await voting.getStartBlock(id) + // let blocksToAdvance = voteStartBlock.sub(currentBlock) + // await advanceBlocks(blocksToAdvance.toNumber()) + // await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[0]}).should.be.fulfilled + // await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[1]}).should.be.fulfilled + // await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[2]}).should.be.fulfilled + // let voteEndBlock = await voting.getEndBlock(id) + // blocksToAdvance = voteEndBlock.sub(currentBlock).add(toBN(1)) + // await advanceBlocks(blocksToAdvance.toNumber()) + // await proxyStorage.setConsensusMock(owner) + // let {logs} = await voting.onCycleEnd(currentValidators).should.be.fulfilled + // logs.length.should.be.equal(1) + // logs[0].event.should.be.equal('BallotFinalized') + // logs[0].args['id'].should.be.bignumber.equal(id) + // let ballotInfo = await voting.getBallotInfo(id, validators[0]) + // ballotInfo.startBlock.should.be.bignumber.equal(voteStartBlock) + // ballotInfo.endBlock.should.be.bignumber.equal(voteEndBlock) + // ballotInfo.isFinalized.should.be.equal(true) + // ballotInfo.proposedValue.should.be.equal(proposedValue) + // ballotInfo.contractType.should.be.bignumber.equal(toBN(contractType)) + // ballotInfo.creator.should.be.equal(validators[0]) + // ballotInfo.description.should.be.equal('description') + // ballotInfo.canBeFinalizedNow.should.be.equal(false) + // ballotInfo.alreadyVoted.should.be.equal(true) + // toBN(QUORUM_STATES.ACCEPTED).should.be.bignumber.equal(await voting.getQuorumState(id)) + // proposedValue.should.be.equal(await (await EternalStorageProxy.at(await proxyStorage.getBlockReward())).getImplementation()) + // }) + // it('should not change to proposed value if quorum is not reached', async () => { + // let id = await voting.getNextBallotId() + // let proposedValue = RANDOM_ADDRESS + // let contractType = CONTRACT_TYPES.BLOCK_REWARD + // await voting.newBallot(voteStartAfterNumberOfCycles, voteCyclesDuration, contractType, proposedValue, 'description', {from: validators[0]}).should.be.fulfilled + // let currentBlock = toBN(await web3.eth.getBlockNumber()) + // let voteStartBlock = await voting.getStartBlock(id) + // let blocksToAdvance = voteStartBlock.sub(currentBlock) + // await advanceBlocks(blocksToAdvance.toNumber()) + // await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[0]}).should.be.fulfilled + // await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[1]}).should.be.fulfilled + // await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[2]}).should.be.fulfilled + // let voteEndBlock = await voting.getEndBlock(id) + // blocksToAdvance = voteEndBlock.sub(currentBlock).add(toBN(1)) + // await advanceBlocks(blocksToAdvance.toNumber()) + // await proxyStorage.setConsensusMock(owner) + // let {logs} = await voting.onCycleEnd(currentValidators).should.be.fulfilled + // logs.length.should.be.equal(1) + // logs[0].event.should.be.equal('BallotFinalized') + // logs[0].args['id'].should.be.bignumber.equal(id) + // let ballotInfo = await voting.getBallotInfo(id, validators[0]) + // ballotInfo.startBlock.should.be.bignumber.equal(voteStartBlock) + // ballotInfo.endBlock.should.be.bignumber.equal(voteEndBlock) + // ballotInfo.isFinalized.should.be.equal(true) + // ballotInfo.proposedValue.should.be.equal(proposedValue) + // ballotInfo.contractType.should.be.bignumber.equal(toBN(contractType)) + // ballotInfo.creator.should.be.equal(validators[0]) + // ballotInfo.description.should.be.equal('description') + // ballotInfo.canBeFinalizedNow.should.be.equal(false) + // ballotInfo.alreadyVoted.should.be.equal(true) + // toBN(QUORUM_STATES.REJECTED).should.be.bignumber.equal(await voting.getQuorumState(id)) + // proposedValue.should.not.be.equal(await (await EternalStorageProxy.at(await proxyStorage.getBlockReward())).getImplementation()) + // }) + // }) + + // describe('upgradeTo', async () => { + // let votingOldImplementation, votingNew + // let proxyStorageStub = accounts[13] + // beforeEach(async () => { + // voting = await Voting.new() + // votingOldImplementation = voting.address + // proxy = await EternalStorageProxy.new(proxyStorage.address, voting.address) + // voting = await Voting.at(proxy.address) + // votingNew = await Voting.new() + // }) + // it('should only be called by ProxyStorage', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(votingNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) + // let {logs} = await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + // logs[0].event.should.be.equal('Upgraded') + // await proxy.setProxyStorageMock(proxyStorage.address) + // }) + // it('should change implementation address', async () => { + // votingOldImplementation.should.be.equal(await proxy.getImplementation()) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // votingNew.address.should.be.equal(await proxy.getImplementation()) + // }) + // it('should increment implementation version', async () => { + // let votingOldVersion = await proxy.getVersion() + // let votingNewVersion = votingOldVersion.add(toBN(1)) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // votingNewVersion.should.be.bignumber.equal(await proxy.getVersion()) + // }) + // it('should work after upgrade', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + // await proxy.setProxyStorageMock(proxyStorage.address) + // votingNew = await Voting.at(proxy.address) + // false.should.be.equal(await votingNew.isInitialized()) + // await votingNew.initialize().should.be.fulfilled + // true.should.be.equal(await votingNew.isInitialized()) + // }) + // it('should use same proxyStorage after upgrade', async () => { + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + // votingNew = await Voting.at(proxy.address) + // proxyStorageStub.should.be.equal(await votingNew.getProxyStorage()) + // }) + // it('should use same storage after upgrade', async () => { + // let nextBallotId = await voting.getNextBallotId() + // let newValue = nextBallotId.toNumber() + 1 + // await voting.setNextBallotIdMock(newValue) + // await proxy.setProxyStorageMock(proxyStorageStub) + // await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + // votingNew = await Voting.at(proxy.address) + // toBN(newValue).should.be.bignumber.equal(await votingNew.getNextBallotId()) + // }) + // }) }) From 8b5a5b1fde8126b1206fcc4ad68394419d8e80e3 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Sun, 30 Aug 2020 14:19:51 +0300 Subject: [PATCH 10/19] handle second total stake for second withdaw func --- contracts/Consensus.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/contracts/Consensus.sol b/contracts/Consensus.sol index 7cf7497..f531c64 100644 --- a/contracts/Consensus.sol +++ b/contracts/Consensus.sol @@ -105,10 +105,22 @@ contract Consensus is ConsensusUtils { _delegatedAmountSub(msg.sender, _validator, _amount); _stakeAmountSub(_validator, _amount); + if (stakeAmount(_validator) < getMinStake()) { _pendingValidatorsRemove(_validator); } + if (stakeAmount(_validator) < getMinStake()) { + if (isPendingValidator(_validator)) { + _pendingValidatorsRemove(_validator); + _totalStakeAmountSub(stakeAmount(_validator)); + } + } else { + if (isPendingValidator(_validator)) { + _totalStakeAmountSub(_amount); + } + } + msg.sender.transfer(_amount); } From 7d6442e6b42d87f38f1983b6fe8d3a4923e4041c Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Mon, 31 Aug 2020 12:51:04 +0300 Subject: [PATCH 11/19] handling change of total stake for pending validators --- contracts/Consensus.sol | 45 +- contracts/ConsensusUtils.sol | 53 +- migrations/2_deploy_contract.js | 2 + test/blockReward.test.js | 59 +- test/consensus.test.js | 1642 ++++++++++++++++++------------- test/helpers.js | 2 +- 6 files changed, 1012 insertions(+), 791 deletions(-) diff --git a/contracts/Consensus.sol b/contracts/Consensus.sol index f531c64..4f63dd1 100644 --- a/contracts/Consensus.sol +++ b/contracts/Consensus.sol @@ -71,25 +71,7 @@ contract Consensus is ConsensusUtils { * @param _amount the amount msg.sender wishes to withdraw from the contract */ function withdraw(uint256 _amount) external { - require(_amount > 0); - require(_amount <= stakeAmount(msg.sender)); - require(_amount <= delegatedAmount(msg.sender, msg.sender)); - - _delegatedAmountSub(msg.sender, msg.sender, _amount); - _stakeAmountSub(msg.sender, _amount); - - if (stakeAmount(msg.sender) < getMinStake()) { - if (isPendingValidator(msg.sender)) { - _pendingValidatorsRemove(msg.sender); - _totalStakeAmountSub(stakeAmount(msg.sender)); - } - } else { - if (isPendingValidator(msg.sender)) { - _totalStakeAmountSub(_amount); - } - } - - msg.sender.transfer(_amount); + _withdraw(msg.sender, _amount, msg.sender); } /** @@ -98,30 +80,7 @@ contract Consensus is ConsensusUtils { * @param _amount the amount msg.sender wishes to withdraw from the contract */ function withdraw(address _validator, uint256 _amount) external { - require(_validator != address(0)); - require(_amount > 0); - require(_amount <= stakeAmount(_validator)); - require(_amount <= delegatedAmount(msg.sender, _validator)); - - _delegatedAmountSub(msg.sender, _validator, _amount); - _stakeAmountSub(_validator, _amount); - - if (stakeAmount(_validator) < getMinStake()) { - _pendingValidatorsRemove(_validator); - } - - if (stakeAmount(_validator) < getMinStake()) { - if (isPendingValidator(_validator)) { - _pendingValidatorsRemove(_validator); - _totalStakeAmountSub(stakeAmount(_validator)); - } - } else { - if (isPendingValidator(_validator)) { - _totalStakeAmountSub(_amount); - } - } - - msg.sender.transfer(_amount); + _withdraw(msg.sender, _amount, _validator); } /** diff --git a/contracts/ConsensusUtils.sol b/contracts/ConsensusUtils.sol index b540ee6..9f643ac 100644 --- a/contracts/ConsensusUtils.sol +++ b/contracts/ConsensusUtils.sol @@ -98,17 +98,52 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { _delegatedAmountAdd(_staker, _validator, _amount); _stakeAmountAdd(_validator, _amount); - + + // stake amount of the validator isn't greater than the max stake require(stakeAmount(_validator) <= getMaxStake()); - if (stakeAmount(_validator) >= getMinStake()) { - if (!isPendingValidator(_validator)) { - _totalStakeAmountAdd(stakeAmount(_validator)); - _pendingValidatorsAdd(_validator); - } else { - _totalStakeAmountAdd(_amount); - } + // the validator must stake himselft the minimum stake + if (stakeAmount(_validator) >= getMinStake() && !isPendingValidator(_validator)) { + _pendingValidatorsAdd(_validator); + } + + // if _validator is one of the current validators + if (isValidator(_validator)) { + // the total stake needs to be adjusted for the block reward formula + _totalStakeAmountAdd(_amount); + } + } + + function _withdraw(address _staker, uint256 _amount, address _validator) internal { + require(_validator != address(0)); + require(_amount > 0); + require(_amount <= stakeAmount(_validator)); + require(_amount <= delegatedAmount(_staker, _validator)); + + bool _isValidator = isValidator(_validator); + + // if new stake amount is lesser than minStake and the validator is one of the current validators + if (stakeAmount(_validator).sub(_amount) < getMinStake() && _isValidator) { + // do not withdaw the amount until the validator is in current set + _pendingValidatorsRemove(_validator); + return; + } + + + _delegatedAmountSub(_staker, _validator, _amount); + _stakeAmountSub(_validator, _amount); + + // if _validator is one of the current validators + if (_isValidator) { + // the total stake needs to be adjusted for the block reward formula + _totalStakeAmountSub(_amount); + } + + // if validator is needed to be removed from pending, but not current + if (stakeAmount(_validator) < getMinStake()) { + _pendingValidatorsRemove(_validator); } + _staker.transfer(_amount); } function _setSystemAddress(address _newAddress) internal { @@ -258,6 +293,7 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { uint256 stakedAmount = stakeAmount(_currentValidators[i]); totalStake = totalStake + stakedAmount; } + _setTotalStakeAmount(totalStake); addressArrayStorage[CURRENT_VALIDATORS] = _currentValidators; } @@ -308,6 +344,7 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { } delete addressArrayStorage[PENDING_VALIDATORS][lastIndex]; addressArrayStorage[PENDING_VALIDATORS].length--; + // if the validator in on of the current validators } } diff --git a/migrations/2_deploy_contract.js b/migrations/2_deploy_contract.js index 7842e40..33761bf 100644 --- a/migrations/2_deploy_contract.js +++ b/migrations/2_deploy_contract.js @@ -78,6 +78,8 @@ module.exports = function(deployer, network, accounts) { await proxyStorage.initializeAddresses(blockReward.address, voting.address) debug(`proxyStorage.initializeAddresses: ${blockReward.address}, ${voting.address}`) + // TODO: + // stake to consensus on behalf of the initial validator if (!!SAVE_TO_FILE === true) { const contracts = { "BlockReward": blockReward.address, diff --git a/test/blockReward.test.js b/test/blockReward.test.js index 42e9a41..e38f060 100644 --- a/test/blockReward.test.js +++ b/test/blockReward.test.js @@ -52,24 +52,24 @@ contract('BlockReward', async (accounts) => { ) }) - // describe('initialize', async () => { - // it('default values', async () => { - // await blockReward.initialize(INITIAL_SUPPLY) - // owner.should.equal(await proxy.getOwner()) - // toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await blockReward.getSystemAddress())) - // let decimals = await blockReward.DECIMALS() - // let initialSupply = await blockReward.getTotalSupply() - // let blocksPerYear = await blockReward.getBlocksPerYear() - // let inflation = await blockReward.getInflation() - - // INITIAL_SUPPLY.should.be.bignumber.equal(initialSupply) - // toBN(BLOCKS_PER_YEAR).should.be.bignumber.equal(blocksPerYear) - // toBN(YEARLY_INFLATION_PERCENTAGE).should.be.bignumber.equal(inflation) - - // let blockRewardAmount = (initialSupply.mul(decimals).mul(inflation).div(toBN(100))).div(blocksPerYear).div(decimals) - // blockRewardAmount.should.be.bignumber.equal(await blockReward.getBlockRewardAmount()) - // }) - // }) + describe('initialize', async () => { + it('default values', async () => { + await blockReward.initialize(INITIAL_SUPPLY) + owner.should.equal(await proxy.getOwner()) + toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await blockReward.getSystemAddress())) + let decimals = await blockReward.DECIMALS() + let initialSupply = await blockReward.getTotalSupply() + let blocksPerYear = await blockReward.getBlocksPerYear() + let inflation = await blockReward.getInflation() + + INITIAL_SUPPLY.should.be.bignumber.equal(initialSupply) + toBN(BLOCKS_PER_YEAR).should.be.bignumber.equal(blocksPerYear) + toBN(YEARLY_INFLATION_PERCENTAGE).should.be.bignumber.equal(inflation) + + let blockRewardAmount = (initialSupply.mul(decimals).mul(inflation).div(toBN(100))).div(blocksPerYear).div(decimals) + blockRewardAmount.should.be.bignumber.equal(await blockReward.getBlockRewardAmount()) + }) + }) describe('reward', async () => { let minStakeAmount @@ -166,7 +166,7 @@ contract('BlockReward', async (accounts) => { it('block reward does not changed if the propotion stays the same', async () => { const minStakeAmount = await consensus.getMinStake() - const validator = accounts[1] + const validator = accounts[0] await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) await consensus.setCurrentValidatorsLengthMock(toBN(2)) @@ -182,7 +182,6 @@ contract('BlockReward', async (accounts) => { // total stake is 10 * minStakeAmount now await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) - // expected reward calculation const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) @@ -233,7 +232,7 @@ contract('BlockReward', async (accounts) => { let stakeAmountValue = minStakeAmount.div(decimals).toNumber() - delegateAmountValue * delegatorsCount let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') let fee = 5 - let validator = accounts[1] + let validator = accounts[0] await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled for (let i = 2; i < accounts.length; i++) { await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled @@ -262,13 +261,14 @@ contract('BlockReward', async (accounts) => { rewards[0].should.be.bignumber.equal(expectedRewardForValidator) }) it('reward amount should update after BLOCKS_PER_YEAR and total yearly inflation should be calculated correctly', async () => { + const validator = accounts[0] await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) await consensus.setTotalStakeAmountMock(0) - await consensus.sendTransaction({ from: accounts[3], value: minStakeAmount }).should.be.fulfilled + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled console.log(await consensus.currentValidatorsLength()) - console.log((await consensus.stakeAmount(accounts[3])).toString(10)) + console.log((await consensus.stakeAmount(validator)).toString(10)) console.log((await consensus.totalStakeAmount()).toString(10)) - console.log((await blockReward.getBlockRewardAmountPerValidator(accounts[3])).toString(10)) + console.log((await blockReward.getBlockRewardAmountPerValidator(validator)).toString(10)) let decimals = await blockReward.DECIMALS() let initialSupply = await blockReward.getTotalSupply() let blocksPerYear = await blockReward.getBlocksPerYear() @@ -282,7 +282,7 @@ contract('BlockReward', async (accounts) => { let blockNumber = await web3.eth.getBlockNumber() while (blockNumber % BLOCKS_PER_YEAR !== 0) { // console.log('block #', blockNumber) - await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled + await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled blockNumber = await web3.eth.getBlockNumber() i++ } @@ -330,16 +330,17 @@ contract('BlockReward', async (accounts) => { let blockRewardAmount = await blockReward.getBlockRewardAmount() let expectedAmount = blockRewardAmount.mul(toBN(BLOCKS_TO_REWARD)) let minStakeAmount = await consensus.getMinStake() - await consensus.sendTransaction({from: accounts[3], value: minStakeAmount}).should.be.fulfilled + const validator = accounts[0] + await consensus.sendTransaction({from: validator, value: minStakeAmount}).should.be.fulfilled console.log(await consensus.currentValidatorsLength()) - console.log((await consensus.stakeAmount(accounts[3])).toString(10)) + console.log((await consensus.stakeAmount(validator)).toString(10)) console.log((await consensus.totalStakeAmount()).toString(10)) - // console.log((await blockReward.getBlockRewardAmountPerValidator(accounts[3])).toString(10)) + // console.log((await blockReward.getBlockRewardAmountPerValidator(validator)).toString(10)) await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) for (let i = 0; i < BLOCKS_TO_REWARD; i++) { - await blockReward.reward([accounts[3]], [0], {from: mockSystemAddress}).should.be.fulfilled + await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled } await blockReward.setShouldEmitRewardedOnCycleMock(true) diff --git a/test/consensus.test.js b/test/consensus.test.js index c4b98b9..302f50e 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -17,6 +17,7 @@ const MIN_STAKE = toWei(toBN(MIN_STAKE_AMOUNT), 'ether') const MAX_STAKE = toWei(toBN(MAX_STAKE_AMOUNT), 'ether') const ONE_ETHER = toWei(ONE, 'ether') const TWO_ETHER = toWei(TWO, 'ether') +const ONE_WEI = ONE const LESS_THAN_MIN_STAKE = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') const MORE_THAN_MIN_STAKE = toWei(toBN(MIN_STAKE_AMOUNT + 1), 'ether') const MORE_THAN_MAX_STAKE = toWei(toBN(MAX_STAKE_AMOUNT + 1), 'ether') @@ -66,66 +67,73 @@ contract('Consensus', async (accounts) => { ) }) - describe('initialize', async () => { - it('default values', async () => { - ZERO.should.be.bignumber.equal(await consensus.currentValidatorsLength()) - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - owner.should.equal(await proxy.getOwner()) - toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await consensus.getSystemAddress())) - true.should.be.equal(await consensus.isFinalized()) - MIN_STAKE.should.be.bignumber.equal(await consensus.getMinStake()) - MAX_STAKE.should.be.bignumber.equal(await consensus.getMaxStake()) - toBN(MAX_VALIDATORS).should.be.bignumber.equal(await consensus.getMaxValidators()) - toBN(CYCLE_DURATION_BLOCKS).should.be.bignumber.equal(await consensus.getCycleDurationBlocks()) - toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) - ZERO.should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) - ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - // toBN(CYCLE_DURATION_BLOCKS / SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getBlocksToSnapshot()) - false.should.be.equal(await consensus.hasCycleEnded()) - ZERO.should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) - ZERO.should.be.bignumber.equal(await consensus.getNextSnapshotId()) - ONE.should.be.bignumber.equal(await consensus.currentValidatorsLength()) - let validators = await consensus.getValidators() - validators.length.should.be.equal(1) - validators[0].should.be.equal(initialValidator) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - }) - it('initial validator address not defined - owner should be initial validator', async () => { - await consensus.initialize(ZERO_ADDRESS) - await consensus.setProxyStorage(proxyStorage.address) - let validators = await consensus.getValidators() - validators.length.should.be.equal(1) - validators[0].should.be.equal(owner) - }) - it('initial validator address defined', async () => { - await consensus.initialize(initialValidator) - let validators = await consensus.getValidators() - validators.length.should.be.equal(1) - validators[0].should.be.equal(initialValidator) - }) + const mockEoF = async () => { + await consensus.setNewValidatorSetMock(await consensus.pendingValidators()) + await consensus.setFinalizedMock(false, {from: owner}) + await consensus.setSystemAddressMock(owner, {from: owner}) + await consensus.finalizeChange().should.be.fulfilled + } - it('initial validator is added to pending after sending fuse', async () => { - await consensus.initialize(initialValidator) - await consensus.setProxyStorage(proxyStorage.address) - true.should.be.equal(await consensus.isFinalized()) - let validators = await consensus.getValidators() - validators.length.should.be.equal(1) - validators[0].should.be.equal(initialValidator) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) + // describe('initialize', async () => { + // it('default values', async () => { + // ZERO.should.be.bignumber.equal(await consensus.currentValidatorsLength()) + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // owner.should.equal(await proxy.getOwner()) + // toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await consensus.getSystemAddress())) + // true.should.be.equal(await consensus.isFinalized()) + // MIN_STAKE.should.be.bignumber.equal(await consensus.getMinStake()) + // MAX_STAKE.should.be.bignumber.equal(await consensus.getMaxStake()) + // toBN(MAX_VALIDATORS).should.be.bignumber.equal(await consensus.getMaxValidators()) + // toBN(CYCLE_DURATION_BLOCKS).should.be.bignumber.equal(await consensus.getCycleDurationBlocks()) + // toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) + // ZERO.should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) + // ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // // toBN(CYCLE_DURATION_BLOCKS / SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getBlocksToSnapshot()) + // false.should.be.equal(await consensus.hasCycleEnded()) + // ZERO.should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) + // ZERO.should.be.bignumber.equal(await consensus.getNextSnapshotId()) + // ONE.should.be.bignumber.equal(await consensus.currentValidatorsLength()) + // let validators = await consensus.getValidators() + // validators.length.should.be.equal(1) + // validators[0].should.be.equal(initialValidator) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // }) + // it('initial validator address not defined - owner should be initial validator', async () => { + // await consensus.initialize(ZERO_ADDRESS) + // await consensus.setProxyStorage(proxyStorage.address) + // let validators = await consensus.getValidators() + // validators.length.should.be.equal(1) + // validators[0].should.be.equal(owner) + // }) + // it('initial validator address defined', async () => { + // await consensus.initialize(initialValidator) + // let validators = await consensus.getValidators() + // validators.length.should.be.equal(1) + // validators[0].should.be.equal(initialValidator) + // }) - await consensus.sendTransaction({from: initialValidator, value: MIN_STAKE}).should.be.fulfilled + // it('initial validator is added to pending after sending fuse', async () => { + // await consensus.initialize(initialValidator) + // await consensus.setProxyStorage(proxyStorage.address) + // true.should.be.equal(await consensus.isFinalized()) + // let validators = await consensus.getValidators() + // validators.length.should.be.equal(1) + // validators[0].should.be.equal(initialValidator) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(initialValidator) + // await consensus.sendTransaction({from: initialValidator, value: MIN_STAKE}).should.be.fulfilled - toBN(MIN_STAKE).should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) - toBN(MIN_STAKE).should.be.bignumber.equal(await consensus.totalStakeAmount()) - }) - }) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(initialValidator) + + // toBN(MIN_STAKE).should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) + // toBN(MIN_STAKE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + // }) + // }) // describe('setProxyStorage', async () => { // beforeEach(async () => { @@ -232,63 +240,137 @@ contract('Consensus', async (accounts) => { it('should not allow zero stake', async () => { await consensus.send(0, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) }) - it('less than minimum stake - should not be added to pending validators', async () => { - await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // contract balance should be updated - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // sender stake amount should be updated - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - // pending validators should not be updated - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) - // validator fee should not be set - ZERO.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - }) - it('minimum stake amount', async () => { - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) - // default validator fee should be set - let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - }) - it('should allow more than minimum stake', async () => { - await consensus.sendTransaction({from: firstCandidate, value: MORE_THAN_MIN_STAKE}).should.be.fulfilled - MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) - // default validator fee should be set - let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - }) + describe('with first candidate', () => { + const validator = initialValidator + it('less than minimum stake, should update the total stake', async () => { + await consensus.sendTransaction({from: validator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // contract balance should be updated + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // sender stake amount should be updated + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + // total stake is updated because the validator in the current validator + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // pending validators should not be updated + // (the validator is not added to pending validators fot next cycle) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // validator fee should not be set + ZERO.should.be.bignumber.equal(await consensus.validatorFee(validator)) + }) + it('minimum stake amount', async () => { + await consensus.sendTransaction({from: validator, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) - it('should allow the maximum stake', async () => { - ZERO.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - await consensus.sendTransaction({from: firstCandidate, value: MAX_STAKE}).should.be.fulfilled - MAX_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MAX_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(validator) + // default validator fee should be set + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) + }) + it('should allow more than minimum stake', async () => { + await consensus.sendTransaction({from: validator, value: MORE_THAN_MIN_STAKE}).should.be.fulfilled + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) - // default validator fee should be set - let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - }) + // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(validator) + // default validator fee should be set + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) + }) + it('should allow the maximum stake', async () => { + ZERO.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + await consensus.sendTransaction({from: validator, value: MAX_STAKE}).should.be.fulfilled + MAX_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MAX_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) - it('should not allow more the maximum stake', async () => { - await consensus.sendTransaction({from: firstCandidate, value: MORE_THAN_MAX_STAKE}).should.be.rejectedWith(ERROR_MSG) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(validator) + // default validator fee should be set + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) + }) + + it('should not allow more the maximum stake', async () => { + await consensus.sendTransaction({from: validator, value: MORE_THAN_MAX_STAKE}).should.be.rejectedWith(ERROR_MSG) + }) }) + + // describe('with first candidate', () => { + // const validator = firstCandidate + // it('less than minimum stake - should not be added to pending validators', async () => { + // await consensus.sendTransaction({from: validator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // // contract balance should be updated + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // // sender stake amount should be updated + // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + // ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // // pending validators should not be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // validator fee should not be set + // ZERO.should.be.bignumber.equal(await consensus.validatorFee(validator)) + // }) + // it('minimum stake amount', async () => { + // await consensus.sendTransaction({from: validator, value: MIN_STAKE}).should.be.fulfilled + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + // ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // // MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(validator) + // // default validator fee should be set + // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) + // }) + // it('should allow more than minimum stake', async () => { + // await consensus.sendTransaction({from: validator, value: MORE_THAN_MIN_STAKE}).should.be.fulfilled + // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + // ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(validator) + // // default validator fee should be set + // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) + // }) + // it('should allow the maximum stake', async () => { + // ZERO.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + // await consensus.sendTransaction({from: validator, value: MAX_STAKE}).should.be.fulfilled + // MAX_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // MAX_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + // ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // // MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators[0].should.be.equal(validator) + // // default validator fee should be set + // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) + // }) + + // it('should not allow more the maximum stake', async () => { + // await consensus.sendTransaction({from: validator, value: MORE_THAN_MAX_STAKE}).should.be.rejectedWith(ERROR_MSG) + // }) + // }) }) describe('advanced', async () => { it('minimum stake amount, in more than one transaction', async () => { @@ -305,10 +387,14 @@ contract('Consensus', async (accounts) => { await consensus.sendTransaction({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) + + // total stake is updated on the EoF + await mockEoF() + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) it('more than minimum stake amount, in more than one transaction', async () => { @@ -324,21 +410,31 @@ contract('Consensus', async (accounts) => { await consensus.sendTransaction({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) + + // total stake is updated on start of the cycle + await mockEoF() + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) it('more than one validator', async () => { // add 1st validator await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) // add 2nd validator await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(2) + + // total stake is updated on the EoF + await mockEoF() + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) }) it('multiple validators, multiple times', async () => { const expectedValidators = [] @@ -349,7 +445,7 @@ contract('Consensus', async (accounts) => { pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) // add 2nd validator expectedValidators.push(secondCandidate) await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled @@ -357,6 +453,10 @@ contract('Consensus', async (accounts) => { pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + ZERO.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // total stake is updated on the EoF + await mockEoF() MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) // doubling the stake for the 1st validator @@ -374,11 +474,15 @@ contract('Consensus', async (accounts) => { pendingValidators.should.deep.equal(expectedValidators) MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) MIN_STAKE.mul(FOUR).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // total stake does not change of the EoF + await mockEoF() + MIN_STAKE.mul(FOUR).should.be.bignumber.equal(await consensus.totalStakeAmount()) }) }) }) - describe('stake', async () => { + describe.skip('stake', async () => { beforeEach(async () => { await consensus.initialize(initialValidator) await consensus.setProxyStorage(proxyStorage.address) @@ -573,7 +677,9 @@ contract('Consensus', async (accounts) => { MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) // delegated amount should be updated MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // total stake isn't updated until the validator is in the current set + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // pending validators should be updated let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) @@ -585,6 +691,9 @@ contract('Consensus', async (accounts) => { let delegatorsLength = await consensus.delegatorsLength(firstCandidate) delegatorsLength.should.be.bignumber.equal(toBN(1)) firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + + await mockEoF() + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) it('should allow the maximum stake', async () => { @@ -594,7 +703,7 @@ contract('Consensus', async (accounts) => { MAX_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) // sender stake amount should be updated MAX_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) // delegated amount should be updated MAX_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) // pending validators should be updated @@ -608,6 +717,9 @@ contract('Consensus', async (accounts) => { let delegatorsLength = await consensus.delegatorsLength(firstCandidate) delegatorsLength.should.be.bignumber.equal(toBN(1)) firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + + await mockEoF() + MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) it('should not allow more the maximum stake', async () => { @@ -636,7 +748,7 @@ contract('Consensus', async (accounts) => { MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) @@ -646,12 +758,16 @@ contract('Consensus', async (accounts) => { delegatorsLength = await consensus.delegatorsLength(firstCandidate) delegatorsLength.should.be.bignumber.equal(toBN(1)) firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + + await mockEoF() + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) it('more than one validator', async () => { // add 1st validator await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) // delegators list should be updated @@ -664,7 +780,7 @@ contract('Consensus', async (accounts) => { // add 2nd validator await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) - MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + // MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(2) // delegators list should be updated @@ -674,6 +790,9 @@ contract('Consensus', async (accounts) => { delegatorsLength = await consensus.delegatorsLength(secondCandidate) delegatorsLength.should.be.bignumber.equal(toBN(1)) firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) + + await mockEoF() + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) }) it('multiple times according to staked amount, in more than one transaction', async () => { // 1st stake @@ -697,7 +816,7 @@ contract('Consensus', async (accounts) => { await consensus.delegate(firstCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) @@ -711,7 +830,7 @@ contract('Consensus', async (accounts) => { await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + // MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) delegators = await consensus.delegators(firstCandidate) delegators.length.should.be.equal(1) delegators[0].should.be.equal(firstDelegator) @@ -722,605 +841,708 @@ contract('Consensus', async (accounts) => { }) }) - // describe('cycles and snapshots', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // }) - // it('hasCycleEnded', async () => { - // false.should.be.equal(await consensus.hasCycleEnded()) + describe('cycles and snapshots', async () => { + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + }) + it('hasCycleEnded', async () => { + false.should.be.equal(await consensus.hasCycleEnded()) - // let currentBlockNumber = await web3.eth.getBlockNumber() - // let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() - // let blocksToAdvance = currentCycleEndBlock.toNumber() - currentBlockNumber + let currentBlockNumber = await web3.eth.getBlockNumber() + let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() + let blocksToAdvance = currentCycleEndBlock.toNumber() - currentBlockNumber - // await advanceBlocks(blocksToAdvance) - // true.should.be.equal(await consensus.hasCycleEnded()) - // }) + await advanceBlocks(blocksToAdvance) + true.should.be.equal(await consensus.hasCycleEnded()) + }) - // it('cycle', async () => { - // false.should.be.equal(await consensus.hasCycleEnded()) + it('cycle', async () => { + false.should.be.equal(await consensus.hasCycleEnded()) - // let currentBlockNumber = await web3.eth.getBlockNumber() - // let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() - // let blocksToAdvance = currentCycleEndBlock.toNumber() - currentBlockNumber - // // console.log({ currentBlockNumber, currentCycleEndBlock: currentCycleEndBlock.toNumber(), blocksToAdvance }) - // await advanceBlocks(blocksToAdvance) - // true.should.be.equal(await consensus.hasCycleEnded()) + let currentBlockNumber = await web3.eth.getBlockNumber() + let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() + let blocksToAdvance = currentCycleEndBlock.toNumber() - currentBlockNumber + // console.log({ currentBlockNumber, currentCycleEndBlock: currentCycleEndBlock.toNumber(), blocksToAdvance }) + await advanceBlocks(blocksToAdvance) + true.should.be.equal(await consensus.hasCycleEnded()) - // await consensus.sendTransaction({from: initialValidator, value: MIN_STAKE}).should.be.fulfilled + await consensus.sendTransaction({from: initialValidator, value: MIN_STAKE}).should.be.fulfilled - // await blockReward.cycleMock().should.be.fulfilled - // false.should.be.equal(await consensus.hasCycleEnded()) - // }) - // // it('shouldTakeSnapshot', async () => { - // // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // // let lastSnapshotTakenAtBlock = await consensus.getLastSnapshotTakenAtBlock() - // // let currentBlockNumber = toBN(await web3.eth.getBlockNumber()) - // // let shouldTakeSnapshot = (currentBlockNumber.sub(lastSnapshotTakenAtBlock)).gte(blocksToSnapshot) - // // shouldTakeSnapshot.should.be.equal(await consensus.shouldTakeSnapshot()) - // // }) - // // it('getRandom', async () => { - // // let repeats = 25 - // // let randoms = [] - // // for (let i = 0; i < repeats; i++) { - // // randoms.push((await consensus.getRandom(0, SNAPSHOTS_PER_CYCLE)).toNumber()) - // // await advanceBlocks(1) - // // } - // // randoms.length.should.be.equal(repeats) - // // let distincts = [...new Set(randoms)] - // // distincts.length.should.be.greaterThan(1) - // // distincts.length.should.be.most(SNAPSHOTS_PER_CYCLE) - // // }) - // it('cycle function should only be called by BlockReward', async () => { - // await consensus.cycle().should.be.rejectedWith(ERROR_MSG) - // await proxyStorage.setBlockRewardMock(owner) - // await consensus.cycle().should.be.fulfilled - // }) - // // it('snapshot with less validators than MAX_VALIDATORS - entire set should be saved', async () => { - // // let expectedValidators = [] - // // for (let i = 1; i <= MAX_VALIDATORS - 1; i++) { - // // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - // // expectedValidators.push(accounts[i-1]) - // // } - // // pendingValidators = await consensus.pendingValidators() - // // pendingValidators.length.should.be.equal(expectedValidators.length) - // // pendingValidators.should.deep.equal(expectedValidators) - // // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // // let snapshotId = await consensus.getNextSnapshotId() - // // await advanceBlocks(blocksToSnapshot) - // // await proxyStorage.setBlockRewardMock(owner) - // // await consensus.cycle().should.be.fulfilled - // // let snapshot = await consensus.getSnapshotAddresses(snapshotId) - // // snapshot.length.should.be.equal(expectedValidators.length) - // // snapshot.forEach(address => { - // // expectedValidators.splice(expectedValidators.indexOf(address), 1) - // // }) - // // expectedValidators.length.should.be.equal(0) - // // }) - // // it('snapshot with exactly MAX_VALIDATORS validators - entire set should be saved', async () => { - // // let expectedValidators = [] - // // for (let i = 1; i <= MAX_VALIDATORS; i++) { - // // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - // // expectedValidators.push(accounts[i-1]) - // // } - // // pendingValidators = await consensus.pendingValidators() - // // pendingValidators.length.should.be.equal(expectedValidators.length) - // // pendingValidators.should.deep.equal(expectedValidators) - // // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // // let snapshotId = await consensus.getNextSnapshotId() - // // await advanceBlocks(blocksToSnapshot) - // // await proxyStorage.setBlockRewardMock(owner) - // // await consensus.cycle().should.be.fulfilled - // // let snapshot = await consensus.getSnapshotAddresses(snapshotId) - // // snapshot.length.should.be.equal(expectedValidators.length) - // // snapshot.forEach(address => { - // // expectedValidators.splice(expectedValidators.indexOf(address), 1) - // // }) - // // expectedValidators.length.should.be.equal(0) - // // }) - // // it('snapshot with more validators than MAX_VALIDATORS - random set should be saved', async () => { - // // let expectedValidators = [] - // // for (let i = 1; i <= MAX_VALIDATORS + 1; i++) { - // // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - // // expectedValidators.push(accounts[i-1]) - // // } - // // pendingValidators = await consensus.pendingValidators() - // // pendingValidators.length.should.be.equal(expectedValidators.length) - // // pendingValidators.should.deep.equal(expectedValidators) - // // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // // let snapshotId = await consensus.getNextSnapshotId() - // // await advanceBlocks(blocksToSnapshot) - // // await proxyStorage.setBlockRewardMock(owner) - // // await consensus.cycle().should.be.fulfilled - // // let snapshot = await consensus.getSnapshotAddresses(snapshotId) - // // snapshot.length.should.be.equal(MAX_VALIDATORS) - // // snapshot.forEach(address => { - // // expectedValidators.splice(expectedValidators.indexOf(address), 1) - // // }) - // // expectedValidators.length.should.be.equal(pendingValidators.length - MAX_VALIDATORS) - // // }) - // }) + await blockReward.cycleMock().should.be.fulfilled + false.should.be.equal(await consensus.hasCycleEnded()) + }) + // it('shouldTakeSnapshot', async () => { + // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // let lastSnapshotTakenAtBlock = await consensus.getLastSnapshotTakenAtBlock() + // let currentBlockNumber = toBN(await web3.eth.getBlockNumber()) + // let shouldTakeSnapshot = (currentBlockNumber.sub(lastSnapshotTakenAtBlock)).gte(blocksToSnapshot) + // shouldTakeSnapshot.should.be.equal(await consensus.shouldTakeSnapshot()) + // }) + // it('getRandom', async () => { + // let repeats = 25 + // let randoms = [] + // for (let i = 0; i < repeats; i++) { + // randoms.push((await consensus.getRandom(0, SNAPSHOTS_PER_CYCLE)).toNumber()) + // await advanceBlocks(1) + // } + // randoms.length.should.be.equal(repeats) + // let distincts = [...new Set(randoms)] + // distincts.length.should.be.greaterThan(1) + // distincts.length.should.be.most(SNAPSHOTS_PER_CYCLE) + // }) + it('cycle function should only be called by BlockReward', async () => { + await consensus.cycle().should.be.rejectedWith(ERROR_MSG) + await proxyStorage.setBlockRewardMock(owner) + await consensus.cycle().should.be.fulfilled + }) + // it('snapshot with less validators than MAX_VALIDATORS - entire set should be saved', async () => { + // let expectedValidators = [] + // for (let i = 1; i <= MAX_VALIDATORS - 1; i++) { + // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled + // expectedValidators.push(accounts[i-1]) + // } + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // let snapshotId = await consensus.getNextSnapshotId() + // await advanceBlocks(blocksToSnapshot) + // await proxyStorage.setBlockRewardMock(owner) + // await consensus.cycle().should.be.fulfilled + // let snapshot = await consensus.getSnapshotAddresses(snapshotId) + // snapshot.length.should.be.equal(expectedValidators.length) + // snapshot.forEach(address => { + // expectedValidators.splice(expectedValidators.indexOf(address), 1) + // }) + // expectedValidators.length.should.be.equal(0) + // }) + // it('snapshot with exactly MAX_VALIDATORS validators - entire set should be saved', async () => { + // let expectedValidators = [] + // for (let i = 1; i <= MAX_VALIDATORS; i++) { + // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled + // expectedValidators.push(accounts[i-1]) + // } + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // let snapshotId = await consensus.getNextSnapshotId() + // await advanceBlocks(blocksToSnapshot) + // await proxyStorage.setBlockRewardMock(owner) + // await consensus.cycle().should.be.fulfilled + // let snapshot = await consensus.getSnapshotAddresses(snapshotId) + // snapshot.length.should.be.equal(expectedValidators.length) + // snapshot.forEach(address => { + // expectedValidators.splice(expectedValidators.indexOf(address), 1) + // }) + // expectedValidators.length.should.be.equal(0) + // }) + // it('snapshot with more validators than MAX_VALIDATORS - random set should be saved', async () => { + // let expectedValidators = [] + // for (let i = 1; i <= MAX_VALIDATORS + 1; i++) { + // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled + // expectedValidators.push(accounts[i-1]) + // } + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(expectedValidators.length) + // pendingValidators.should.deep.equal(expectedValidators) + // let blocksToSnapshot = await consensus.getBlocksToSnapshot() + // let snapshotId = await consensus.getNextSnapshotId() + // await advanceBlocks(blocksToSnapshot) + // await proxyStorage.setBlockRewardMock(owner) + // await consensus.cycle().should.be.fulfilled + // let snapshot = await consensus.getSnapshotAddresses(snapshotId) + // snapshot.length.should.be.equal(MAX_VALIDATORS) + // snapshot.forEach(address => { + // expectedValidators.splice(expectedValidators.indexOf(address), 1) + // }) + // expectedValidators.length.should.be.equal(pendingValidators.length - MAX_VALIDATORS) + // }) + }) - // describe('withdraw', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // }) - // describe('stakers', async () => { - // it('cannot withdraw zero', async () => { - // await consensus.methods['withdraw(uint256)'](ZERO_AMOUNT, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('cannot withdraw more than staked amount', async () => { - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // await consensus.methods['withdraw(uint256)'](MORE_THAN_MIN_STAKE).should.be.rejectedWith(ERROR_MSG) - // }) - // it('can withdraw all staked amount', async () => { - // // stake - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // // stake - // await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}) - // // withdraw - // await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}) - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // // pendingValidators should be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators.should.deep.equal([secondCandidate]) - // }) - // it('can withdraw less than staked amount', async () => { - // // stake - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // // withdraw - // await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) - // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - // let expectedValidators = [] - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // // pendingValidators should be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // }) - // it('can withdraw multiple times', async () => { - // // stake - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) - // // withdraw 1st time - // await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) - // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - // let expectedValidators = [] - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // withdraw 2nd time - // await consensus.withdraw(ONE_ETHER, {from: firstCandidate}) - // expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // }) - // }) - // describe('delegators', async () => { - // it('cannot withdraw zero', async () => { - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ZERO_AMOUNT, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('cannot withdraw if no staker address defined', async () => { - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - // await consensus.methods['withdraw(address,uint256)'](ZERO_ADDRESS, MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('cannot withdraw more than staked amount', async () => { - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MORE_THAN_MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('can withdraw all staked amount', async () => { - // // stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // stake - // await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // withdraw - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MIN_STAKE, {from: firstDelegator}) - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, secondCandidate)) - // // pendingValidators should be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators.should.deep.equal([secondCandidate]) - // // delegators list should be updated for firstCandidate - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(0) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(0)) - // // delegators list should be updated for secondCandidate - // delegators = await consensus.delegators(secondCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(secondCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) - // }) - // it('can withdraw less than staked amount', async () => { - // // stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // withdraw - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - // let expectedValidators = [] - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // // pendingValidators should be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // delegators list should be updated - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // }) - // it('can withdraw multiple times', async () => { - // // stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // withdraw 1st time - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - // let expectedValidators = [firstCandidate] - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // delegators list should be updated - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // // withdraw 2nd time - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - // expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // delegators list should be updated - // delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // }) - // }) - // }) + describe('withdraw', async () => { + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + }) + describe('stakers', async () => { - // describe('setValidatorFee', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // }) - // it('should only be called by validator', async () => { - // decimals = await consensus.DECIMALS() - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - // let newValidatorFee = defaultValidatorFee.sub(toBN(0.01 * decimals)) - // await consensus.setValidatorFee(newValidatorFee, {from: initialValidator}).should.be.fulfilled - // newValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(initialValidator)) - // await consensus.setValidatorFee(newValidatorFee, {from: secondCandidate}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should only be able to set a valid fee', async () => { - // decimals = await consensus.DECIMALS() - // let i; - // for (i = 0; i <= 100; i++) { - // await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.fulfilled - // } - // await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - // }) - // }) + it('cannot withdraw zero', async () => { + await consensus.methods['withdraw(uint256)'](ZERO_AMOUNT, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) + }) + it('cannot withdraw more than staked amount', async () => { + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + await consensus.methods['withdraw(uint256)'](MORE_THAN_MIN_STAKE).should.be.rejectedWith(ERROR_MSG) + }) - // describe('getDelegatorsForRewardDistribution', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // }) - // it('validator without delegators', async () => { - // await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(0) - // rewards.length.should.be.equal(0) - // }) - // describe('validator with one delegator', async () => { - // it('total delegated more than total staked - no fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let fee = toBN(0 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // it('total delegated less than total staked - no fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let fee = toBN(0 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // it('total delegated more than total staked - 100% fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let fee = toBN(1 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // it('total delegated less than total staked - 100% fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let fee = toBN(1 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // it('total delegated more than total staked - other fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let fee = toBN(0.225 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // it('total delegated less than total staked - other fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') - // let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') - // let fee = toBN(0.225 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // rewards[0].should.be.bignumber.equal(expectedReward) - // }) - // }) - // describe('validator with multiple delegators', async () => { - // it('total delegated more than total staked - no fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let fee = toBN(0 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // it('total delegated less than total staked - no fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let fee = toBN(0 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // it('total delegated more than total staked - 100% fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let fee = toBN(1 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // it('total delegated less than total staked - 100% fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let fee = toBN(1 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // it('total delegated more than total staked - other fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let fee = toBN(0.15 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // it('total delegated less than total staked - other fee', async () => { - // decimals = await consensus.DECIMALS() - // let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') - // let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') - // let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') - // let fee = toBN(0.15 * decimals) - // await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled - // await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(2) - // delegators[0].should.be.equal(firstDelegator) - // delegators[1].should.be.equal(secondDelegator) - // rewards.length.should.be.equal(delegators.length) - // rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) - // }) - // }) - // it('validator with many delegators', async () => { - // decimals = await consensus.DECIMALS() - // let delegatorsCount = accounts.length - 2 - // let delegateAmountValue = parseInt(MIN_STAKE_AMOUNT * 0.99 / delegatorsCount) - // let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') - // let stakeAmountValue = MIN_STAKE_AMOUNT - delegateAmountValue * delegatorsCount - // let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') - // let fee = toBN(0.05 * decimals) - // let validator = accounts[1] - // await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled - // for (let i = 2; i < accounts.length; i++) { - // await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled - // } - // await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled - // let validatorFee = await consensus.validatorFee(firstCandidate) - // let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) - // delegators.length.should.be.equal(delegatorsCount) - // rewards.length.should.be.equal(delegators.length) - // let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) - // for (let i = 0; i < delegatorsCount; i++) { - // delegators[i].should.be.equal(accounts[i + 2]) - // rewards[i].should.be.bignumber.equal(expectedReward) - // } - // }) - // }) + describe('stakers are not curent validators', () => { + it('can withdraw all staked amount', async () => { + // stake + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // stake + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}) - // describe('upgradeTo', async () => { - // let consensusOldImplementation, consensusNew - // let proxyStorageStub = accounts[3] - // beforeEach(async () => { - // consensus = await Consensus.new() - // consensusOldImplementation = consensus.address - // proxy = await EternalStorageProxy.new(proxyStorage.address, consensus.address) - // consensus = await Consensus.at(proxy.address) - // consensusNew = await Consensus.new() - // }) - // it('should only be called by ProxyStorage', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) - // let {logs} = await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // logs[0].event.should.be.equal('Upgraded') - // await proxy.setProxyStorageMock(proxyStorage.address) - // }) - // it('should change implementation address', async () => { - // consensusOldImplementation.should.be.equal(await proxy.getImplementation()) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // consensusNew.address.should.be.equal(await proxy.getImplementation()) - // }) - // it('should increment implementation version', async () => { - // let consensusOldVersion = await proxy.getVersion() - // let consensusNewVersion = consensusOldVersion.add(toBN(1)) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // consensusNewVersion.should.be.bignumber.equal(await proxy.getVersion()) - // }) - // it('should work after upgrade', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // consensusNew = await Consensus.at(proxy.address) - // false.should.be.equal(await consensusNew.isInitialized()) - // await consensusNew.initialize(initialValidator).should.be.fulfilled - // true.should.be.equal(await consensusNew.isInitialized()) - // }) - // it('should use same proxyStorage after upgrade', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // consensusNew = await Consensus.at(proxy.address) - // proxyStorageStub.should.be.equal(await consensusNew.getProxyStorage()) - // }) - // it('should use same storage after upgrade', async () => { - // await consensus.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) - // consensusNew = await Consensus.at(proxy.address) - // RANDOM_ADDRESS.should.be.equal(await consensus.getSystemAddress()) - // }) - // }) + // await mockEoF() + // withdraw + await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}) + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // pendingValidators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators.should.deep.equal([secondCandidate]) + }) + it('can withdraw less than staked amount', async () => { + // stake + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + // withdraw + await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + let expectedValidators = [] + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // pendingValidators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + }) + it('can withdraw multiple times', async () => { + // stake + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // withdraw 1st time + await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) + let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + expectedAmount.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // withdraw 2nd time + await consensus.withdraw(ONE_ETHER, {from: firstCandidate}) + expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + }) + + describe('stakers are curent validators', () => { + it('cannot withdraw the min stake for active validator', async () => { + // stake + // console.log(await web3.eth.getBalance(firstCandidate)) + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + + await mockEoF() + // withdraw + const firstCandidateBalance = toBN(await web3.eth.getBalance(firstCandidate)) + await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}).should.be.fulfilled + // firstCandidate doesn't get the stake back + firstCandidateBalance.should.be.bignumber.above(toBN(await web3.eth.getBalance(firstCandidate))) + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + + // pendingValidators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + }) + + it('cannot withdraw one wei from the min stake for active validator', async () => { + // stake + // console.log(await web3.eth.getBalance(firstCandidate)) + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + + await mockEoF() + // withdraw + // console.log(await web3.eth.getBalance(firstCandidate)) + const firstCandidateBalance = toBN(await web3.eth.getBalance(firstCandidate)) + await consensus.methods['withdraw(uint256)'](ONE_WEI, {from: firstCandidate}).should.be.fulfilled + // firstCandidate doesn't get the stake back + firstCandidateBalance.should.be.bignumber.above(toBN(await web3.eth.getBalance(firstCandidate))) + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + + // pendingValidators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + }) + + it('can withdraw until the min stake for active validator', async () => { + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE.mul(TWO)}) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + + await mockEoF() + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // withdraw + // console.log(await web3.eth.getBalance(firstCandidate)) + await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}).should.be.fulfilled + // console.log(await web3.eth.getBalance(firstCandidate)) + + MIN_STAKE.should.be.bignumber.not.equal(toBN(await web3.eth.getBalance(firstCandidate))) + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // pendingValidators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + }) + + it('can withdraw multiple times', async () => { + // stake + const stake = MIN_STAKE.mul(TWO) + await consensus.sendTransaction({from: firstCandidate, value: stake}) + stake.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + + await mockEoF() + stake.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // withdraw 1st time + await consensus.methods['withdraw(uint256)'](ONE_ETHER, {from: firstCandidate}) + let expectedAmount = stake.sub(ONE_ETHER) + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + expectedAmount.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + // withdraw 2nd time + await consensus.withdraw(ONE_ETHER, {from: firstCandidate}) + // expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') + expectedAmount = stake.sub(TWO_ETHER) + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + expectedAmount.should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + }) + }) + // describe('delegators', async () => { + // it('cannot withdraw zero', async () => { + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ZERO_AMOUNT, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('cannot withdraw if no staker address defined', async () => { + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + // await consensus.methods['withdraw(address,uint256)'](ZERO_ADDRESS, MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('cannot withdraw more than staked amount', async () => { + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MORE_THAN_MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + // }) + // it('can withdraw all staked amount', async () => { + // // stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // stake + // await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // withdraw + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MIN_STAKE, {from: firstDelegator}) + // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, secondCandidate)) + // // pendingValidators should be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(1) + // pendingValidators.should.deep.equal([secondCandidate]) + // // delegators list should be updated for firstCandidate + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(0) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(0)) + // // delegators list should be updated for secondCandidate + // delegators = await consensus.delegators(secondCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(secondCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) + // }) + // it('can withdraw less than staked amount', async () => { + // // stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // withdraw + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + // let expectedValidators = [] + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // // pendingValidators should be updated + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // delegators list should be updated + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // }) + // it('can withdraw multiple times', async () => { + // // stake + // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // // withdraw 1st time + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + // let expectedValidators = [firstCandidate] + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // let pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // delegators list should be updated + // let delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // // withdraw 2nd time + // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + // expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') + // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // pendingValidators = await consensus.pendingValidators() + // pendingValidators.length.should.be.equal(0) + // // delegators list should be updated + // delegators = await consensus.delegators(firstCandidate) + // delegators.length.should.be.equal(1) + // delegators[0].should.be.equal(firstDelegator) + // delegatorsLength = await consensus.delegatorsLength(firstCandidate) + // delegatorsLength.should.be.bignumber.equal(toBN(1)) + // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // }) + // }) + }) + + describe('setValidatorFee', async () => { + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + }) + it('should only be called by validator', async () => { + decimals = await consensus.DECIMALS() + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + let newValidatorFee = defaultValidatorFee.sub(toBN(0.01 * decimals)) + await consensus.setValidatorFee(newValidatorFee, {from: initialValidator}).should.be.fulfilled + newValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(initialValidator)) + await consensus.setValidatorFee(newValidatorFee, {from: secondCandidate}).should.be.rejectedWith(ERROR_MSG) + }) + it('should only be able to set a valid fee', async () => { + decimals = await consensus.DECIMALS() + let i; + for (i = 0; i <= 100; i++) { + await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.fulfilled + } + await consensus.setValidatorFee(toBN(i/100 * decimals), {from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + }) + }) + + describe('getDelegatorsForRewardDistribution', async () => { + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + }) + it('validator without delegators', async () => { + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(0) + rewards.length.should.be.equal(0) + }) + describe('validator with one delegator', async () => { + it('total delegated more than total staked - no fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let fee = toBN(0 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + it('total delegated less than total staked - no fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let fee = toBN(0 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + it('total delegated more than total staked - 100% fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let fee = toBN(1 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + it('total delegated less than total staked - 100% fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let fee = toBN(1 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + it('total delegated more than total staked - other fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let fee = toBN(0.225 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + it('total delegated less than total staked - other fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.75), 'ether') + let delegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.25), 'ether') + let fee = toBN(0.225 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: delegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + rewards[0].should.be.bignumber.equal(expectedReward) + }) + }) + describe('validator with multiple delegators', async () => { + it('total delegated more than total staked - no fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let fee = toBN(0 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + it('total delegated less than total staked - no fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let fee = toBN(0 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + it('total delegated more than total staked - 100% fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let fee = toBN(1 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + it('total delegated less than total staked - 100% fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let fee = toBN(1 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + it('total delegated more than total staked - other fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let fee = toBN(0.15 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + it('total delegated less than total staked - other fee', async () => { + decimals = await consensus.DECIMALS() + let stakeAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.7), 'ether') + let firstDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.2), 'ether') + let secondDelegateAmount = toWei(toBN(MIN_STAKE_AMOUNT * 0.1), 'ether') + let fee = toBN(0.15 * decimals) + await consensus.sendTransaction({from: firstCandidate, value: stakeAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: firstDelegateAmount}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: secondDelegator, value: secondDelegateAmount}).should.be.fulfilled + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(2) + delegators[0].should.be.equal(firstDelegator) + delegators[1].should.be.equal(secondDelegator) + rewards.length.should.be.equal(delegators.length) + rewards[0].should.be.bignumber.equal(blockRewardAmount.mul(firstDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + rewards[1].should.be.bignumber.equal(blockRewardAmount.mul(secondDelegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals)) + }) + }) + it('validator with many delegators', async () => { + decimals = await consensus.DECIMALS() + let delegatorsCount = accounts.length - 2 + let delegateAmountValue = parseInt(MIN_STAKE_AMOUNT * 0.99 / delegatorsCount) + let delegateAmount = toWei(toBN(delegateAmountValue), 'ether') + let stakeAmountValue = MIN_STAKE_AMOUNT - delegateAmountValue * delegatorsCount + let stakeAmount = toWei(toBN(stakeAmountValue), 'ether') + let fee = toBN(0.05 * decimals) + let validator = accounts[1] + await consensus.sendTransaction({from: validator, value: stakeAmount}).should.be.fulfilled + for (let i = 2; i < accounts.length; i++) { + await consensus.delegate(validator, {from: accounts[i], value: delegateAmount}).should.be.fulfilled + } + await consensus.setValidatorFeeMock(fee, {from: firstCandidate}).should.be.fulfilled + let validatorFee = await consensus.validatorFee(firstCandidate) + let { 0: delegators, 1: rewards } = await consensus.getDelegatorsForRewardDistribution(firstCandidate, blockRewardAmount) + delegators.length.should.be.equal(delegatorsCount) + rewards.length.should.be.equal(delegators.length) + let expectedReward = blockRewardAmount.mul(delegateAmount).div(MIN_STAKE).mul(decimals.sub(validatorFee)).div(decimals) + for (let i = 0; i < delegatorsCount; i++) { + delegators[i].should.be.equal(accounts[i + 2]) + rewards[i].should.be.bignumber.equal(expectedReward) + } + }) + }) + + describe('upgradeTo', async () => { + let consensusOldImplementation, consensusNew + let proxyStorageStub = accounts[3] + beforeEach(async () => { + consensus = await Consensus.new() + consensusOldImplementation = consensus.address + proxy = await EternalStorageProxy.new(proxyStorage.address, consensus.address) + consensus = await Consensus.at(proxy.address) + consensusNew = await Consensus.new() + }) + it('should only be called by ProxyStorage', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) + let {logs} = await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + logs[0].event.should.be.equal('Upgraded') + await proxy.setProxyStorageMock(proxyStorage.address) + }) + it('should change implementation address', async () => { + consensusOldImplementation.should.be.equal(await proxy.getImplementation()) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + consensusNew.address.should.be.equal(await proxy.getImplementation()) + }) + it('should increment implementation version', async () => { + let consensusOldVersion = await proxy.getVersion() + let consensusNewVersion = consensusOldVersion.add(toBN(1)) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + consensusNewVersion.should.be.bignumber.equal(await proxy.getVersion()) + }) + it('should work after upgrade', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + consensusNew = await Consensus.at(proxy.address) + false.should.be.equal(await consensusNew.isInitialized()) + await consensusNew.initialize(initialValidator).should.be.fulfilled + true.should.be.equal(await consensusNew.isInitialized()) + }) + it('should use same proxyStorage after upgrade', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + consensusNew = await Consensus.at(proxy.address) + proxyStorageStub.should.be.equal(await consensusNew.getProxyStorage()) + }) + it('should use same storage after upgrade', async () => { + await consensus.setSystemAddressMock(RANDOM_ADDRESS, {from: owner}) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(consensusNew.address, {from: proxyStorageStub}) + consensusNew = await Consensus.at(proxy.address) + RANDOM_ADDRESS.should.be.equal(await consensus.getSystemAddress()) + }) + }) }) diff --git a/test/helpers.js b/test/helpers.js index c23d92e..b2b9e3d 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -59,4 +59,4 @@ exports.advanceBlocks = (n) => { resolve(results[results.length - 1]) }) }) -} \ No newline at end of file +} From 662d4195dd55fbf991ab3d45dde4d5ab0841225b Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Mon, 31 Aug 2020 19:03:54 +0300 Subject: [PATCH 12/19] working on tests --- test/consensus.test.js | 352 +++++++++++++++++++++++------------------ 1 file changed, 196 insertions(+), 156 deletions(-) diff --git a/test/consensus.test.js b/test/consensus.test.js index 302f50e..369444e 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -74,162 +74,202 @@ contract('Consensus', async (accounts) => { await consensus.finalizeChange().should.be.fulfilled } - // describe('initialize', async () => { - // it('default values', async () => { - // ZERO.should.be.bignumber.equal(await consensus.currentValidatorsLength()) - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // owner.should.equal(await proxy.getOwner()) - // toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await consensus.getSystemAddress())) - // true.should.be.equal(await consensus.isFinalized()) - // MIN_STAKE.should.be.bignumber.equal(await consensus.getMinStake()) - // MAX_STAKE.should.be.bignumber.equal(await consensus.getMaxStake()) - // toBN(MAX_VALIDATORS).should.be.bignumber.equal(await consensus.getMaxValidators()) - // toBN(CYCLE_DURATION_BLOCKS).should.be.bignumber.equal(await consensus.getCycleDurationBlocks()) - // toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) - // ZERO.should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) - // ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - // // toBN(CYCLE_DURATION_BLOCKS / SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getBlocksToSnapshot()) - // false.should.be.equal(await consensus.hasCycleEnded()) - // ZERO.should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) - // ZERO.should.be.bignumber.equal(await consensus.getNextSnapshotId()) - // ONE.should.be.bignumber.equal(await consensus.currentValidatorsLength()) - // let validators = await consensus.getValidators() - // validators.length.should.be.equal(1) - // validators[0].should.be.equal(initialValidator) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // }) - // it('initial validator address not defined - owner should be initial validator', async () => { - // await consensus.initialize(ZERO_ADDRESS) - // await consensus.setProxyStorage(proxyStorage.address) - // let validators = await consensus.getValidators() - // validators.length.should.be.equal(1) - // validators[0].should.be.equal(owner) - // }) - // it('initial validator address defined', async () => { - // await consensus.initialize(initialValidator) - // let validators = await consensus.getValidators() - // validators.length.should.be.equal(1) - // validators[0].should.be.equal(initialValidator) - // }) - - // it('initial validator is added to pending after sending fuse', async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // true.should.be.equal(await consensus.isFinalized()) - // let validators = await consensus.getValidators() - // validators.length.should.be.equal(1) - // validators[0].should.be.equal(initialValidator) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - - // await consensus.sendTransaction({from: initialValidator, value: MIN_STAKE}).should.be.fulfilled - - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(initialValidator) - - // toBN(MIN_STAKE).should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) - // toBN(MIN_STAKE).should.be.bignumber.equal(await consensus.totalStakeAmount()) - // }) - // }) - - // describe('setProxyStorage', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // }) - // it('setProxyStorage should fail if no address', async () => { - // await consensus.setProxyStorage(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG) - // }) - // it('setProxyStorage should fail if not called by owner', async () => { - // await consensus.setProxyStorage(proxyStorage.address, {from: nonOwner}).should.be.rejectedWith(ERROR_MSG) - // // success - // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - // proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) - // // should not be able to set again if already set - // await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) - // }) - // it('setProxyStorage successfully', async () => { - // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - // proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) - // }) - // it('setProxyStorage should not be able to set again if already set', async () => { - // await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled - // await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) - // }) - // }) - - // describe('emitInitiateChange', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // await consensus.setFinalizedMock(false) - // }) - // it('should fail if not called by validator', async () => { - // await consensus.emitInitiateChange({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should fail if newValidatorSet is empty', async () => { - // await consensus.setShouldEmitInitiateChangeMock(true) - // await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should fail if `shouldEmitInitiateChange` is false', async () => { - // let mockSet = [firstCandidate, secondCandidate] - // await consensus.setNewValidatorSetMock(mockSet) - // await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('should be successful and emit event', async () => { - // await consensus.setShouldEmitInitiateChangeMock(true) - // let mockSet = [firstCandidate, secondCandidate] - // await consensus.setNewValidatorSetMock(mockSet) - // let {logs} = await consensus.emitInitiateChange({from: initialValidator}).should.be.fulfilled - // false.should.be.equal(await consensus.shouldEmitInitiateChange()) - // logs.length.should.be.equal(1) - // logs[0].event.should.be.equal('InitiateChange') - // logs[0].args['newSet'].should.deep.equal(mockSet) - // }) - // }) - - // describe('finalizeChange', async () => { - // beforeEach(async () => { - // await consensus.initialize(initialValidator) - // await consensus.setProxyStorage(proxyStorage.address) - // await consensus.setFinalizedMock(false) - // }) - // it('should only be called by SYSTEM_ADDRESS', async () => { - // await consensus.finalizeChange().should.be.rejectedWith(ERROR_MSG) - // await consensus.setSystemAddressMock(accounts[0], {from: owner}) - // await consensus.finalizeChange().should.be.fulfilled - // }) - // it('should set finalized to true', async () => { - // false.should.be.equal(await consensus.isFinalized()) - // await consensus.setSystemAddressMock(accounts[0]) - // await consensus.finalizeChange().should.be.fulfilled - // true.should.be.equal(await consensus.isFinalized()) - // }) - // it('should not update current validators set if new set is empty', async () => { - // let initialValidators = await consensus.getValidators() - // let mockSet = [] - // await consensus.setNewValidatorSetMock(mockSet) - // await consensus.setSystemAddressMock(accounts[0]) - // let {logs} = await consensus.finalizeChange().should.be.fulfilled - // let currentValidators = await consensus.getValidators() - // currentValidators.length.should.be.equal(1) - // currentValidators.should.deep.equal(initialValidators) - // logs.length.should.be.equal(0) - // }) - // it('should update current validators set', async () => { - // let mockSet = [firstCandidate, secondCandidate] - // await consensus.setNewValidatorSetMock(mockSet) - // await consensus.setSystemAddressMock(accounts[0]) - // let {logs} = await consensus.finalizeChange().should.be.fulfilled - // let currentValidators = await consensus.getValidators() - // currentValidators.length.should.be.equal(2) - // currentValidators.should.deep.equal(mockSet) - // logs[0].event.should.be.equal('ChangeFinalized') - // logs[0].args['newSet'].should.deep.equal(mockSet) - // }) - // }) + describe('initialize', async () => { + it('default values', async () => { + ZERO.should.be.bignumber.equal(await consensus.currentValidatorsLength()) + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + owner.should.equal(await proxy.getOwner()) + toChecksumAddress(SYSTEM_ADDRESS).should.be.equal(toChecksumAddress(await consensus.getSystemAddress())) + true.should.be.equal(await consensus.isFinalized()) + MIN_STAKE.should.be.bignumber.equal(await consensus.getMinStake()) + MAX_STAKE.should.be.bignumber.equal(await consensus.getMaxStake()) + toBN(MAX_VALIDATORS).should.be.bignumber.equal(await consensus.getMaxValidators()) + toBN(CYCLE_DURATION_BLOCKS).should.be.bignumber.equal(await consensus.getCycleDurationBlocks()) + toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) + ZERO.should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // toBN(CYCLE_DURATION_BLOCKS / SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getBlocksToSnapshot()) + false.should.be.equal(await consensus.hasCycleEnded()) + ZERO.should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) + ZERO.should.be.bignumber.equal(await consensus.getNextSnapshotId()) + ONE.should.be.bignumber.equal(await consensus.currentValidatorsLength()) + let validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(initialValidator) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + }) + it('initial validator address not defined - owner should be initial validator', async () => { + await consensus.initialize(ZERO_ADDRESS) + await consensus.setProxyStorage(proxyStorage.address) + let validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(owner) + }) + it('initial validator address defined', async () => { + await consensus.initialize(initialValidator) + let validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(initialValidator) + }) + + it('initial validator is added to pending after sending fuse', async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + true.should.be.equal(await consensus.isFinalized()) + let validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(initialValidator) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + + await consensus.sendTransaction({from: initialValidator, value: MIN_STAKE}).should.be.fulfilled + + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(initialValidator) + + toBN(MIN_STAKE).should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) + toBN(MIN_STAKE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + }) + + describe('setProxyStorage', async () => { + beforeEach(async () => { + await consensus.initialize(initialValidator) + }) + it('setProxyStorage should fail if no address', async () => { + await consensus.setProxyStorage(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG) + }) + it('setProxyStorage should fail if not called by owner', async () => { + await consensus.setProxyStorage(proxyStorage.address, {from: nonOwner}).should.be.rejectedWith(ERROR_MSG) + // success + await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) + // should not be able to set again if already set + await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) + }) + it('setProxyStorage successfully', async () => { + await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + proxyStorage.address.should.be.equal(await consensus.getProxyStorage()) + }) + it('setProxyStorage should not be able to set again if already set', async () => { + await consensus.setProxyStorage(proxyStorage.address).should.be.fulfilled + await consensus.setProxyStorage(RANDOM_ADDRESS).should.be.rejectedWith(ERROR_MSG) + }) + }) + + describe('emitInitiateChange', async () => { + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + await consensus.setFinalizedMock(false) + }) + it('should fail if not called by validator', async () => { + await consensus.emitInitiateChange({from: nonOwner}).should.be.rejectedWith(ERROR_MSG) + }) + it('should fail if newValidatorSet is empty', async () => { + await consensus.setShouldEmitInitiateChangeMock(true) + await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + }) + it('should fail if `shouldEmitInitiateChange` is false', async () => { + let mockSet = [firstCandidate, secondCandidate] + await consensus.setNewValidatorSetMock(mockSet) + await consensus.emitInitiateChange({from: initialValidator}).should.be.rejectedWith(ERROR_MSG) + }) + it('should be successful and emit event', async () => { + await consensus.setShouldEmitInitiateChangeMock(true) + let mockSet = [firstCandidate, secondCandidate] + await consensus.setNewValidatorSetMock(mockSet) + let {logs} = await consensus.emitInitiateChange({from: initialValidator}).should.be.fulfilled + false.should.be.equal(await consensus.shouldEmitInitiateChange()) + logs.length.should.be.equal(1) + logs[0].event.should.be.equal('InitiateChange') + logs[0].args['newSet'].should.deep.equal(mockSet) + }) + }) + + describe('finalizeChange', async () => { + beforeEach(async () => { + await consensus.initialize(initialValidator) + await consensus.setProxyStorage(proxyStorage.address) + await consensus.setFinalizedMock(false) + }) + it('should only be called by SYSTEM_ADDRESS', async () => { + await consensus.finalizeChange().should.be.rejectedWith(ERROR_MSG) + await consensus.setSystemAddressMock(accounts[0], {from: owner}) + await consensus.finalizeChange().should.be.fulfilled + }) + it('should set finalized to true', async () => { + false.should.be.equal(await consensus.isFinalized()) + await consensus.setSystemAddressMock(accounts[0]) + await consensus.finalizeChange().should.be.fulfilled + true.should.be.equal(await consensus.isFinalized()) + }) + it('should not update current validators set if new set is empty', async () => { + let initialValidators = await consensus.getValidators() + let mockSet = [] + await consensus.setNewValidatorSetMock(mockSet) + await consensus.setSystemAddressMock(accounts[0]) + let {logs} = await consensus.finalizeChange().should.be.fulfilled + let currentValidators = await consensus.getValidators() + currentValidators.length.should.be.equal(1) + currentValidators.should.deep.equal(initialValidators) + logs.length.should.be.equal(0) + }) + it.only('should update current validators set', async () => { + let mockSet = [firstCandidate, secondCandidate] + await consensus.setNewValidatorSetMock(mockSet) + await consensus.setSystemAddressMock(accounts[0]) + let {logs} = await consensus.finalizeChange().should.be.fulfilled + let currentValidators = await consensus.getValidators() + currentValidators.length.should.be.equal(2) + currentValidators.should.deep.equal(mockSet) + logs[0].event.should.be.equal('ChangeFinalized') + logs[0].args['newSet'].should.deep.equal(mockSet) + + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + + context.only('with staking', () => { + it('adding validators should update the total stake', async () => { + let mockSet = [firstCandidate, secondCandidate] + + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + await consensus.setNewValidatorSetMock(mockSet) + await consensus.setSystemAddressMock(accounts[0]) + + let {logs} = await consensus.finalizeChange().should.be.fulfilled + let currentValidators = await consensus.getValidators() + currentValidators.length.should.be.equal(2) + currentValidators.should.deep.equal(mockSet) + logs[0].event.should.be.equal('ChangeFinalized') + logs[0].args['newSet'].should.deep.equal(mockSet) + + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + + it('removing validators should update the total stake', async () => { + let mockSet = [firstCandidate, secondCandidate] + + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + await consensus.setNewValidatorSetMock(mockSet) + await consensus.setSystemAddressMock(accounts[0]) + + let {logs} = await consensus.finalizeChange().should.be.fulfilled + let currentValidators = await consensus.getValidators() + currentValidators.length.should.be.equal(2) + currentValidators.should.deep.equal(mockSet) + logs[0].event.should.be.equal('ChangeFinalized') + logs[0].args['newSet'].should.deep.equal(mockSet) + + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + }) + }) describe('stake (fallback function)', async () => { beforeEach(async () => { From f34810e89065ac1ca544cb7dcfcfc64c68a0d509 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Mon, 7 Sep 2020 22:21:01 +0300 Subject: [PATCH 13/19] Improving tests --- test/blockReward.test.js | 101 ++++++++++----------- test/consensus.test.js | 183 +++++++++++++++++++-------------------- test/helpers.js | 2 + 3 files changed, 144 insertions(+), 142 deletions(-) diff --git a/test/blockReward.test.js b/test/blockReward.test.js index e38f060..830e084 100644 --- a/test/blockReward.test.js +++ b/test/blockReward.test.js @@ -6,7 +6,7 @@ const EternalStorageProxy = artifacts.require('EternalStorageProxyMock.sol') const BlockReward = artifacts.require('BlockRewardMock.sol') const Voting = artifacts.require('Voting.sol') const { ERROR_MSG, ZERO_ADDRESS, RANDOM_ADDRESS } = require('./helpers') -const { ZERO, ONE, TWO, THREE, FOUR } = require('./helpers') +const { ZERO, ONE, TWO, THREE, FOUR, TEN } = require('./helpers') const {toBN, toWei, toChecksumAddress} = web3.utils const INITIAL_SUPPLY = toWei(toBN(300000000000000000 || 0), 'gwei') @@ -72,11 +72,11 @@ contract('BlockReward', async (accounts) => { }) describe('reward', async () => { - let minStakeAmount + let minStakeAmount, doubleMinStakeAmount beforeEach(async () => { await blockReward.initialize(INITIAL_SUPPLY) minStakeAmount = await consensus.getMinStake() - // await consensus.setTotalStakeAmountMock(ZERO) + doubleMinStakeAmount = minStakeAmount.mul(TWO) }) describe('#getBlockRewardAmountPerValidator', () => { @@ -87,15 +87,14 @@ contract('BlockReward', async (accounts) => { validator = accounts[1] secondValidator = accounts[2] }) + it('block reward with one validator', async () => { - const minStakeAmount = await consensus.getMinStake() ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - // await consensus.sendTransaction({ from: validator, value: minStakeAmount.mul(toBN(4)) }).should.be.fulfilled - // mocking total supply - await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(TEN)) + const l = await consensus.currentValidatorsLength() console.log(l.toString(10)) console.log(blockRewardAmount.toString(10)) @@ -103,22 +102,14 @@ contract('BlockReward', async (accounts) => { const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - const expectedReward = blockRewardAmount.div(toBN(10)) + const expectedReward = blockRewardAmount.div(TEN) expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) }) it('block reward of one validator staking 100% of the total stake', async () => { - const minStakeAmount = await consensus.getMinStake() - - const validator = accounts[1] await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled await consensus.setTotalStakeAmountMock(minStakeAmount) - const l = await consensus.currentValidatorsLength() - console.log(l.toString(10)) - console.log(blockRewardAmount.toString(10)) - '1'.should.be.equal(l.toString(10)) - const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) const expectedReward = blockRewardAmount @@ -126,31 +117,23 @@ contract('BlockReward', async (accounts) => { }) it('block reward of 1 validator of 2, staking 10% of the total stake', async () => { - const minStakeAmount = await consensus.getMinStake() - const validator = accounts[1] await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) - await consensus.setCurrentValidatorsLengthMock(toBN(2)) - - const l = await consensus.currentValidatorsLength() - '2'.should.be.equal(l.toString(10)) + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(TEN)) + await consensus.setCurrentValidatorsLengthMock(TWO) const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) // expected reward calculation - const expectedReward = blockRewardAmount.div(toBN(10)).mul(toBN(2)) + const expectedReward = blockRewardAmount.div(TEN).mul(TWO) expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) }) it('block reward of 1 validator of 2, staking 50% of the total stake', async () => { - const minStakeAmount = await consensus.getMinStake() - - const validator = accounts[1] await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) - await consensus.setCurrentValidatorsLengthMock(toBN(2)) + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(TEN)) + await consensus.setCurrentValidatorsLengthMock(TWO) const l = await consensus.currentValidatorsLength() '2'.should.be.equal(l.toString(10)) @@ -159,20 +142,15 @@ contract('BlockReward', async (accounts) => { console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) // expected reward calculation - const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) + const expectedReward = blockRewardAmount.div(TEN).mul(TWO) expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) }) - it('block reward does not changed if the propotion stays the same', async () => { - const minStakeAmount = await consensus.getMinStake() - + it('block reward does not change if the propotion stays the same', async () => { const validator = accounts[0] await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(2))) - await consensus.setCurrentValidatorsLengthMock(toBN(2)) - - const l = await consensus.currentValidatorsLength() - '2'.should.be.equal(l.toString(10)) + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(TEN)) + await consensus.setCurrentValidatorsLengthMock(TWO) const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) @@ -180,10 +158,26 @@ contract('BlockReward', async (accounts) => { // validator stake is 5 * minStakeAmount now await consensus.sendTransaction({ from: validator, value: minStakeAmount.mul(toBN(4)) }).should.be.fulfilled // total stake is 10 * minStakeAmount now - await consensus.setTotalStakeAmountMock(minStakeAmount.mul(toBN(10))) + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(TEN)) // expected reward calculation - const expectedReward = blockRewardAmount.div(toBN(2)).mul(toBN(2)) + const expectedReward = blockRewardAmount.div(TEN).mul(TWO) + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) + + it('block reward for two validators', async () => { + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + await consensus.sendTransaction({ from: secondValidator, value: minStakeAmount.mul(THREE) }).should.be.fulfilled + + await consensus.setTotalStakeAmountMock(minStakeAmount.mul(FOUR)) + await consensus.setCurrentValidatorsLengthMock(TWO) + + let blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + let expectedReward = blockRewardAmount.div(FOUR).mul(TWO) + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + + blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(secondValidator) + expectedReward = blockRewardAmount.mul(THREE).div(FOUR).mul(TWO) expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) }) }) @@ -265,10 +259,7 @@ contract('BlockReward', async (accounts) => { await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) await consensus.setTotalStakeAmountMock(0) await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - console.log(await consensus.currentValidatorsLength()) - console.log((await consensus.stakeAmount(validator)).toString(10)) - console.log((await consensus.totalStakeAmount()).toString(10)) - console.log((await blockReward.getBlockRewardAmountPerValidator(validator)).toString(10)) + let decimals = await blockReward.DECIMALS() let initialSupply = await blockReward.getTotalSupply() let blocksPerYear = await blockReward.getBlocksPerYear() @@ -299,9 +290,24 @@ contract('BlockReward', async (accounts) => { totalSupply.should.be.bignumber.equal(expectedSupply) newBlockRewardAmount.should.be.bignumber.equal((totalSupply.mul(decimals).mul(inflation).div(toBN(100))).div(blocksPerYear).div(decimals)) }) + + it.only('call reward with 0 blockReward', async () => { + const validator = accounts[4] + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + await consensus.setTotalStakeAmountMock(minStakeAmount) + let {logs} = await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled + + ZERO.should.be.bignumber.equal(await blockReward.getBlockRewardAmountPerValidator(validator)) + + // await consensus.sendTransaction({from: validator, value: minStakeAmount}).should.be.fulfilled + + // let initialSupply = await blockReward.getTotalSupply() + // let blockRewardAmount = await blockReward.getBlockRewardAmountPerValidator(validator) + // let {logs} = await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled + }) }) - describe('emitRewardedOnCycle', function() { + describe('emitRewardedOnCycle', function () { beforeEach(async () => { await blockReward.initialize(INITIAL_SUPPLY) }) @@ -333,11 +339,6 @@ contract('BlockReward', async (accounts) => { const validator = accounts[0] await consensus.sendTransaction({from: validator, value: minStakeAmount}).should.be.fulfilled - console.log(await consensus.currentValidatorsLength()) - console.log((await consensus.stakeAmount(validator)).toString(10)) - console.log((await consensus.totalStakeAmount()).toString(10)) - // console.log((await blockReward.getBlockRewardAmountPerValidator(validator)).toString(10)) - await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) for (let i = 0; i < BLOCKS_TO_REWARD; i++) { await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled diff --git a/test/consensus.test.js b/test/consensus.test.js index 369444e..d92d432 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -89,7 +89,6 @@ contract('Consensus', async (accounts) => { toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) ZERO.should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - // toBN(CYCLE_DURATION_BLOCKS / SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getBlocksToSnapshot()) false.should.be.equal(await consensus.hasCycleEnded()) ZERO.should.be.bignumber.equal(await consensus.getLastSnapshotTakenAtBlock()) ZERO.should.be.bignumber.equal(await consensus.getNextSnapshotId()) @@ -1161,97 +1160,97 @@ contract('Consensus', async (accounts) => { }) }) }) - // describe('delegators', async () => { - // it('cannot withdraw zero', async () => { - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ZERO_AMOUNT, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('cannot withdraw if no staker address defined', async () => { - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled - // await consensus.methods['withdraw(address,uint256)'](ZERO_ADDRESS, MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('cannot withdraw more than staked amount', async () => { - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MORE_THAN_MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) - // }) - // it('can withdraw all staked amount', async () => { - // // stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // stake - // await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // withdraw - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, MIN_STAKE, {from: firstDelegator}) - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - // ZERO_AMOUNT.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, secondCandidate)) - // // pendingValidators should be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators.should.deep.equal([secondCandidate]) - // // delegators list should be updated for firstCandidate - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(0) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(0)) - // // delegators list should be updated for secondCandidate - // delegators = await consensus.delegators(secondCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(secondCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) - // }) - // it('can withdraw less than staked amount', async () => { - // // stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // withdraw - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - // let expectedValidators = [] - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // // pendingValidators should be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // delegators list should be updated - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // }) - // it('can withdraw multiple times', async () => { - // // stake - // await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) - // // withdraw 1st time - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - // let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') - // let expectedValidators = [firstCandidate] - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // delegators list should be updated - // let delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // let delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // // withdraw 2nd time - // await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) - // expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') - // expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // delegators list should be updated - // delegators = await consensus.delegators(firstCandidate) - // delegators.length.should.be.equal(1) - // delegators[0].should.be.equal(firstDelegator) - // delegatorsLength = await consensus.delegatorsLength(firstCandidate) - // delegatorsLength.should.be.bignumber.equal(toBN(1)) - // firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - // }) - // }) + describe.only('delegators', async () => { + it('cannot withdraw zero', async () => { + await consensus.methods['withdraw(address,uint256)'](firstCandidate, ZERO_AMOUNT, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + }) + it('cannot withdraw if no staker address defined', async () => { + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + await consensus.methods['withdraw(address,uint256)'](ZERO_ADDRESS, MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + }) + it('cannot withdraw more than staked amount', async () => { + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + await consensus.methods['withdraw(address,uint256)'](firstCandidate, MORE_THAN_MIN_STAKE, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) + }) + it('can withdraw all staked amount', async () => { + // stake + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // stake + await consensus.delegate(secondCandidate, {from: firstDelegator, value: MIN_STAKE}) + // withdraw + await consensus.methods['withdraw(address,uint256)'](firstCandidate, MIN_STAKE, {from: firstDelegator}) + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + ZERO_AMOUNT.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO_AMOUNT.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, firstCandidate)) + MIN_STAKE.should.be.bignumber.equal(await consensus.delegatedAmount(firstDelegator, secondCandidate)) + // pendingValidators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators.should.deep.equal([secondCandidate]) + // delegators list should be updated for firstCandidate + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(0) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(0)) + // delegators list should be updated for secondCandidate + delegators = await consensus.delegators(secondCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + delegatorsLength = await consensus.delegatorsLength(secondCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) + }) + it('can withdraw less than staked amount', async () => { + // stake + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // withdraw + await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + let expectedValidators = [] + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // pendingValidators should be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // delegators list should be updated + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + }) + it('can withdraw multiple times', async () => { + // stake + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}) + // withdraw 1st time + await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + let expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 1), 'ether') + let expectedValidators = [firstCandidate] + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // delegators list should be updated + let delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + let delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + // withdraw 2nd time + await consensus.methods['withdraw(address,uint256)'](firstCandidate, ONE_ETHER, {from: firstDelegator}) + expectedAmount = toWei(toBN(MIN_STAKE_AMOUNT - 2), 'ether') + expectedAmount.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // delegators list should be updated + delegators = await consensus.delegators(firstCandidate) + delegators.length.should.be.equal(1) + delegators[0].should.be.equal(firstDelegator) + delegatorsLength = await consensus.delegatorsLength(firstCandidate) + delegatorsLength.should.be.bignumber.equal(toBN(1)) + firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) + }) + }) }) describe('setValidatorFee', async () => { diff --git a/test/helpers.js b/test/helpers.js index b2b9e3d..494a2c9 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -18,6 +18,8 @@ exports.ONE = toBN(1) exports.TWO = toBN(2) exports.THREE = toBN(3) exports.FOUR = toBN(4) +exports.FIVE = toBN(5) +exports.TEN = toBN(10) exports.advanceTime = (seconds) => { return new Promise((resolve, reject) => { From a1e7bb773e76bee311a88579c9f39f249db02dce Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Wed, 9 Sep 2020 10:48:54 +0300 Subject: [PATCH 14/19] working on tests --- test/blockReward.test.js | 2 +- test/consensus.test.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/blockReward.test.js b/test/blockReward.test.js index 830e084..08c750d 100644 --- a/test/blockReward.test.js +++ b/test/blockReward.test.js @@ -291,7 +291,7 @@ contract('BlockReward', async (accounts) => { newBlockRewardAmount.should.be.bignumber.equal((totalSupply.mul(decimals).mul(inflation).div(toBN(100))).div(blocksPerYear).div(decimals)) }) - it.only('call reward with 0 blockReward', async () => { + it('call reward with 0 blockReward', async () => { const validator = accounts[4] await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) await consensus.setTotalStakeAmountMock(minStakeAmount) diff --git a/test/consensus.test.js b/test/consensus.test.js index d92d432..d54bd01 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -217,7 +217,7 @@ contract('Consensus', async (accounts) => { currentValidators.should.deep.equal(initialValidators) logs.length.should.be.equal(0) }) - it.only('should update current validators set', async () => { + it('should update current validators set', async () => { let mockSet = [firstCandidate, secondCandidate] await consensus.setNewValidatorSetMock(mockSet) await consensus.setSystemAddressMock(accounts[0]) @@ -231,7 +231,7 @@ contract('Consensus', async (accounts) => { ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) - context.only('with staking', () => { + context('with staking', () => { it('adding validators should update the total stake', async () => { let mockSet = [firstCandidate, secondCandidate] @@ -1160,7 +1160,7 @@ contract('Consensus', async (accounts) => { }) }) }) - describe.only('delegators', async () => { + describe('delegators', async () => { it('cannot withdraw zero', async () => { await consensus.methods['withdraw(address,uint256)'](firstCandidate, ZERO_AMOUNT, {from: firstDelegator}).should.be.rejectedWith(ERROR_MSG) }) From 3c143212f91a3c7faa5334e34be70e4e91957bea Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Wed, 9 Sep 2020 15:43:03 +0300 Subject: [PATCH 15/19] fixing staking tests --- test/consensus.test.js | 70 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/test/consensus.test.js b/test/consensus.test.js index d54bd01..de29f5d 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -521,7 +521,7 @@ contract('Consensus', async (accounts) => { }) }) - describe.skip('stake', async () => { + describe('stake', async () => { beforeEach(async () => { await consensus.initialize(initialValidator) await consensus.setProxyStorage(proxyStorage.address) @@ -542,27 +542,53 @@ contract('Consensus', async (accounts) => { pendingValidators.length.should.be.equal(0) }) it('minimum stake amount', async () => { + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + ONE.should.be.bignumber.equal(await consensus.currentValidatorsLength()) + let validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(initialValidator) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + await consensus.stake({ from: firstCandidate, value: MIN_STAKE }).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) - let pendingValidators = await consensus.pendingValidators() + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) + + await mockEoF() + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // initial validator did not stake so he is not in the pending validators list + ONE.should.be.bignumber.equal(await consensus.currentValidatorsLength()) + validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(firstCandidate) }) it('should allow more than minimum stake', async () => { + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) await consensus.stake({ from: firstCandidate, value: MORE_THAN_MIN_STAKE }).should.be.fulfilled MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) // default validator fee should be set let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + + await mockEoF() + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // initial validator did not stake so he is not in the pending validators list + ONE.should.be.bignumber.equal(await consensus.currentValidatorsLength()) + let validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(firstCandidate) }) it('should allow the maximum stake', async () => { @@ -570,7 +596,7 @@ contract('Consensus', async (accounts) => { await consensus.stake({from: firstCandidate, value: MAX_STAKE}).should.be.fulfilled MAX_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MAX_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) @@ -578,6 +604,14 @@ contract('Consensus', async (accounts) => { // default validator fee should be set let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) + + await mockEoF() + MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // initial validator did not stake so he is not in the pending validators list + ONE.should.be.bignumber.equal(await consensus.currentValidatorsLength()) + let validators = await consensus.getValidators() + validators.length.should.be.equal(1) + validators[0].should.be.equal(firstCandidate) }) it('should not allow more the maximum stake', async () => { @@ -598,10 +632,13 @@ contract('Consensus', async (accounts) => { await consensus.stake({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) + + await mockEoF() + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) it('more than minimum stake amount, in more than one transaction', async () => { @@ -617,25 +654,31 @@ contract('Consensus', async (accounts) => { await consensus.stake({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) + + await mockEoF() + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) it('more than one validator', async () => { // add 1st validator await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(1) // add 2nd validator await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) - MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(2) + + await mockEoF() + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) }) it('multiple validators, multiple times', async () => { @@ -644,7 +687,7 @@ contract('Consensus', async (accounts) => { expectedValidators.push(firstCandidate) await consensus.stake({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) let pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) @@ -652,7 +695,7 @@ contract('Consensus', async (accounts) => { expectedValidators.push(secondCandidate) await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) - MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) @@ -663,7 +706,7 @@ contract('Consensus', async (accounts) => { pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.mul(THREE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) // doubling the stake for the 2st validator await consensus.stake({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled @@ -671,6 +714,9 @@ contract('Consensus', async (accounts) => { pendingValidators.length.should.be.equal(expectedValidators.length) pendingValidators.should.deep.equal(expectedValidators) MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + await mockEoF() MIN_STAKE.mul(FOUR).should.be.bignumber.equal(await consensus.totalStakeAmount()) }) }) From 88f6c93913b661603ac31fdf907223d3914abde5 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Wed, 9 Sep 2020 16:00:52 +0300 Subject: [PATCH 16/19] Delete comments --- contracts/Consensus.sol | 13 ------------- contracts/ConsensusUtils.sol | 20 -------------------- 2 files changed, 33 deletions(-) diff --git a/contracts/Consensus.sol b/contracts/Consensus.sol index 4f63dd1..0addc5c 100644 --- a/contracts/Consensus.sol +++ b/contracts/Consensus.sol @@ -87,21 +87,9 @@ contract Consensus is ConsensusUtils { * @dev Function to be called by the block reward contract each block to handle cycles and snapshots logic */ function cycle() external onlyBlockReward { - // if (_shouldTakeSnapshot()) { - // uint256 snapshotId = getNextSnapshotId(); - // if (snapshotId == getSnapshotsPerCycle().sub(1)) { - // _setNextSnapshotId(0); - // } else { - // _setNextSnapshotId(snapshotId.add(1)); - // } - // _setSnapshot(snapshotId, pendingValidators()); - // _setLastSnapshotTakenAtBlock(block.number); - // delete snapshotId; - // } if (_hasCycleEnded()) { IVoting(ProxyStorage(getProxyStorage()).getVoting()).onCycleEnd(currentValidators()); _setCurrentCycle(); - // uint256 randomSnapshotId = _getRandom(0, getSnapshotsPerCycle() - 1); address[] memory newSet = pendingValidators(); if (newSet.length > 0) { _setNewValidatorSet(newSet); @@ -111,7 +99,6 @@ contract Consensus is ConsensusUtils { _setShouldEmitInitiateChange(true); emit ShouldEmitInitiateChange(); } - // delete randomSnapshotId; IBlockReward(ProxyStorage(getProxyStorage()).getBlockReward()).onCycleEnd(); } } diff --git a/contracts/ConsensusUtils.sol b/contracts/ConsensusUtils.sol index 9f643ac..79f292b 100644 --- a/contracts/ConsensusUtils.sol +++ b/contracts/ConsensusUtils.sol @@ -92,10 +92,6 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { require(_amount != 0); require(_validator != address(0)); - // overstaking should not be possible - // require (stakeAmount(_validator) < getMinStake()); - // require (stakeAmount(_validator).add(_amount) <= getMinStake()); - _delegatedAmountAdd(_staker, _validator, _amount); _stakeAmountAdd(_validator, _amount); @@ -283,7 +279,6 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { } function _currentValidatorsAdd(address _address) internal { - // _totalStakeAmountAddValidator(_address); addressArrayStorage[CURRENT_VALIDATORS].push(_address); } @@ -460,13 +455,6 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { uintStorage[TOTAL_STAKE_AMOUNT] = _totalStake; } - // function _totalStakeAmountAddValidator(address _address) internal { - // uint256 stakedAmount = stakeAmount(_address); - // uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))].add(stakedAmount); - - // // uintStorage[keccak256(abi.encodePacked("totalStakeAmount"))] = _totalStake; - // } - function _totalStakeAmountAdd(uint256 _stakeAmount) internal { uintStorage[TOTAL_STAKE_AMOUNT] = uintStorage[TOTAL_STAKE_AMOUNT].add(_stakeAmount); } @@ -483,14 +471,6 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { boolStorage[SHOULD_EMIT_INITIATE_CHANGE] = _status; } - // function _getBlocksToSnapshot() internal pure returns(uint256) { - // return getCycleDurationBlocks().div(getSnapshotsPerCycle()); - // } - - // function _shouldTakeSnapshot() internal view returns(bool) { - // return (block.number - getLastSnapshotTakenAtBlock() >= _getBlocksToSnapshot()); - // } - function _hasCycleEnded() internal view returns(bool) { return (block.number >= getCurrentCycleEndBlock()); } From 7306b304dbce48cf1cfc0ba214a0d5f70aa2905d Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Wed, 23 Sep 2020 12:10:54 +0300 Subject: [PATCH 17/19] working on tests --- test/consensus.test.js | 537 +++++++++++++++++++++++++++-------------- 1 file changed, 362 insertions(+), 175 deletions(-) diff --git a/test/consensus.test.js b/test/consensus.test.js index de29f5d..a774cbd 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -5,7 +5,7 @@ const ProxyStorage = artifacts.require('ProxyStorageMock.sol') const EternalStorageProxy = artifacts.require('EternalStorageProxyMock.sol') const BlockReward = artifacts.require('BlockRewardMock.sol') const Voting = artifacts.require('Voting.sol') -const { ERROR_MSG, ZERO_AMOUNT, SYSTEM_ADDRESS, ZERO_ADDRESS, RANDOM_ADDRESS, advanceBlocks } = require('./helpers') +const { ERROR_MSG, ZERO_AMOUNT, SYSTEM_ADDRESS, ZERO_ADDRESS, RANDOM_ADDRESS, advanceBlocks, FIVE } = require('./helpers') const { ZERO, ONE, TWO, THREE, FOUR } = require('./helpers') const { toBN, toWei, toChecksumAddress } = web3.utils @@ -67,7 +67,7 @@ contract('Consensus', async (accounts) => { ) }) - const mockEoF = async () => { + const mockEoC = async () => { await consensus.setNewValidatorSetMock(await consensus.pendingValidators()) await consensus.setFinalizedMock(false, {from: owner}) await consensus.setSystemAddressMock(owner, {from: owner}) @@ -280,7 +280,7 @@ contract('Consensus', async (accounts) => { await consensus.send(0, {from: firstCandidate}).should.be.rejectedWith(ERROR_MSG) }) - describe('with first candidate', () => { + context('with the initial validator', () => { const validator = initialValidator it('less than minimum stake, should update the total stake', async () => { await consensus.sendTransaction({from: validator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled @@ -345,178 +345,365 @@ contract('Consensus', async (accounts) => { }) }) - // describe('with first candidate', () => { - // const validator = firstCandidate - // it('less than minimum stake - should not be added to pending validators', async () => { - // await consensus.sendTransaction({from: validator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - // // contract balance should be updated - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // // sender stake amount should be updated - // LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) - // ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - // // pending validators should not be updated - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(0) - // // validator fee should not be set - // ZERO.should.be.bignumber.equal(await consensus.validatorFee(validator)) - // }) - // it('minimum stake amount', async () => { - // await consensus.sendTransaction({from: validator, value: MIN_STAKE}).should.be.fulfilled - // MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) - // ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - - // // MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(validator) - // // default validator fee should be set - // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) - // }) - // it('should allow more than minimum stake', async () => { - // await consensus.sendTransaction({from: validator, value: MORE_THAN_MIN_STAKE}).should.be.fulfilled - // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) - // ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - - // // MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) - - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(validator) - // // default validator fee should be set - // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) - // }) - // it('should allow the maximum stake', async () => { - // ZERO.should.be.bignumber.equal(await consensus.stakeAmount(validator)) - // await consensus.sendTransaction({from: validator, value: MAX_STAKE}).should.be.fulfilled - // MAX_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - // MAX_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) - // ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - - // // MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) - - // let pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(1) - // pendingValidators[0].should.be.equal(validator) - // // default validator fee should be set - // let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() - // defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) - // }) - - // it('should not allow more the maximum stake', async () => { - // await consensus.sendTransaction({from: validator, value: MORE_THAN_MAX_STAKE}).should.be.rejectedWith(ERROR_MSG) - // }) - // }) + context('with first candidate', () => { + const validator = firstCandidate + it('less than minimum stake - should not be added to pending validators', async () => { + await consensus.sendTransaction({from: validator, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + // contract balance should be updated + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + // sender stake amount should be updated + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // pending validators should not be updated + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) + // validator fee should not be set + ZERO.should.be.bignumber.equal(await consensus.validatorFee(validator)) + + await mockEoC() + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + it('minimum stake amount', async () => { + let validatorsLength = await consensus.currentValidatorsLength() + validatorsLength.should.be.bignumber.equal(ONE) + true.should.be.equal(await consensus.isValidator(initialValidator)) + + await consensus.sendTransaction({from: validator, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(validator) + // default validator fee should be set + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) + + // total stake is updated on the EoC + await mockEoC() + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + validatorsLength.should.be.bignumber.equal(ONE) + true.should.be.equal(await consensus.isValidator(validator)) + }) + it('should allow more than minimum stake', async () => { + await consensus.sendTransaction({from: validator, value: MORE_THAN_MIN_STAKE}).should.be.fulfilled + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(validator) + // default validator fee should be set + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) + + // total stake is updated on the EoC + await mockEoC() + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + it('should allow the maximum stake', async () => { + ZERO.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + await consensus.sendTransaction({from: validator, value: MAX_STAKE}).should.be.fulfilled + MAX_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MAX_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(validator)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(validator) + // default validator fee should be set + let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() + defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(validator)) + + // total stake is updated on the EoC + await mockEoC() + MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + + it('should not allow more the maximum stake', async () => { + await consensus.sendTransaction({from: validator, value: MORE_THAN_MAX_STAKE}).should.be.rejectedWith(ERROR_MSG) + }) + }) }) describe('advanced', async () => { - it('minimum stake amount, in more than one transaction', async () => { - // 1st stake - await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + context('with first candidate', () => { + it('minimum stake amount, in more than one transaction', async () => { + // 1st stake + await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) - // 2nd stake - await consensus.sendTransaction({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled - MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) + // 2nd stake + await consensus.sendTransaction({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled + MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) - // total stake is updated on the EoF - await mockEoF() - MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) - }) + // total stake is updated on the EoC + await mockEoC() + MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) - it('more than minimum stake amount, in more than one transaction', async () => { - // 1st stake - await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(0) + it('more than minimum stake amount, in more than one transaction', async () => { + // 1st stake + await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + LESS_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(0) - // 2nd stake - await consensus.sendTransaction({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled - MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - pendingValidators[0].should.be.equal(firstCandidate) + // 2nd stake + await consensus.sendTransaction({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) - // total stake is updated on start of the cycle - await mockEoF() - MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // total stake is updated on start of the cycle + await mockEoC() + MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + + it('more than one validator', async () => { + // add 1st validator + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + // add 2nd validator + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(2) + + // total stake is updated on the EoC + await mockEoC() + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + it('multiple validators, multiple times', async () => { + const expectedValidators = [] + // add 1st validator + expectedValidators.push(firstCandidate) + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + // add 2nd validator + expectedValidators.push(secondCandidate) + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + ZERO.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // total stake is updated on the EoC + await mockEoC() + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // doubling the stake for the 1st validator + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.mul(THREE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // doubling the stake for the 2st validator + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + MIN_STAKE.mul(FOUR).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // total stake does not change of the EoC + await mockEoC() + MIN_STAKE.mul(FOUR).should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) }) - it('more than one validator', async () => { - // add 1st validator - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(1) - // add 2nd validator - await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(2) + context('with existing stake', () => { + beforeEach(async () => { + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + await mockEoC() + }) - // total stake is updated on the EoF - await mockEoF() - MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + it('minimum stake amount, in more than one transaction', async () => { + // 1st stake + await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + MIN_STAKE.add(LESS_THAN_MIN_STAKE).should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.add(LESS_THAN_MIN_STAKE).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.add(LESS_THAN_MIN_STAKE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + + // 2nd stake + await consensus.sendTransaction({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + + // total stake is updated on the EoC + await mockEoC() + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + + it('more than minimum stake amount, in more than one transaction', async () => { + // 1st stake + await consensus.sendTransaction({from: firstCandidate, value: LESS_THAN_MIN_STAKE}).should.be.fulfilled + MIN_STAKE.add(LESS_THAN_MIN_STAKE).should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.add(LESS_THAN_MIN_STAKE).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.add(LESS_THAN_MIN_STAKE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + + // 2nd stake + await consensus.sendTransaction({from: firstCandidate, value: TWO_ETHER}).should.be.fulfilled + MIN_STAKE.add(MORE_THAN_MIN_STAKE).should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) + MIN_STAKE.add(MORE_THAN_MIN_STAKE).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.add(MORE_THAN_MIN_STAKE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + pendingValidators[0].should.be.equal(firstCandidate) + + // total stake is updated on start of the cycle + await mockEoC() + MIN_STAKE.add(MORE_THAN_MIN_STAKE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + + it('more than one validator', async () => { + // add 1st validator + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(1) + // add 2nd validator + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(2) + + // total stake is updated on the EoC + await mockEoC() + MIN_STAKE.mul(THREE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + + it('multiple validators, multiple times', async () => { + const expectedValidators = [] + // add 1st validator + expectedValidators.push(firstCandidate) + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + let pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + // add 2nd validator + expectedValidators.push(secondCandidate) + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // total stake is updated on the EoC + await mockEoC() + MIN_STAKE.mul(THREE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // doubling the stake for the 1st validator + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.mul(THREE).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + MIN_STAKE.mul(FOUR).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // doubling the stake for the 2st validator + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled + pendingValidators = await consensus.pendingValidators() + pendingValidators.length.should.be.equal(expectedValidators.length) + pendingValidators.should.deep.equal(expectedValidators) + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + MIN_STAKE.mul(FIVE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + // total stake does not change of the EoC + await mockEoC() + MIN_STAKE.mul(FIVE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) }) - it('multiple validators, multiple times', async () => { - const expectedValidators = [] - // add 1st validator - expectedValidators.push(firstCandidate) - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - let pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(expectedValidators.length) - pendingValidators.should.deep.equal(expectedValidators) - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - // add 2nd validator - expectedValidators.push(secondCandidate) - await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(expectedValidators.length) - pendingValidators.should.deep.equal(expectedValidators) - MIN_STAKE.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) - ZERO.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) - // total stake is updated on the EoF - await mockEoF() - MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + context('total stake', () => { + it('two validators', async () => { + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE.mul(FOUR)}).should.be.fulfilled - // doubling the stake for the 1st validator - await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(expectedValidators.length) - pendingValidators.should.deep.equal(expectedValidators) - MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) - MIN_STAKE.mul(THREE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - // doubling the stake for the 2st validator - await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}).should.be.fulfilled - pendingValidators = await consensus.pendingValidators() - pendingValidators.length.should.be.equal(expectedValidators.length) - pendingValidators.should.deep.equal(expectedValidators) - MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) - MIN_STAKE.mul(FOUR).should.be.bignumber.equal(await consensus.totalStakeAmount()) + await mockEoC() - // total stake does not change of the EoF - await mockEoF() - MIN_STAKE.mul(FOUR).should.be.bignumber.equal(await consensus.totalStakeAmount()) + MIN_STAKE.mul(FIVE).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + await consensus.sendTransaction({from: firstCandidate, value: ONE_ETHER}).should.be.fulfilled + + MIN_STAKE.mul(FIVE).add(ONE_ETHER).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + await consensus.sendTransaction({from: thirdCandidate, value: ONE_ETHER}).should.be.fulfilled + ONE_ETHER.should.be.bignumber.equal(await consensus.stakeAmount(thirdCandidate)) + + MIN_STAKE.mul(FIVE).add(ONE_ETHER).should.be.bignumber.equal(await consensus.totalStakeAmount()) + await mockEoC() + + MIN_STAKE.mul(FIVE).add(ONE_ETHER).should.be.bignumber.equal(await consensus.totalStakeAmount()) + }) + + it('validator with delegators', async () => { + await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}).should.be.fulfilled + await consensus.delegate(firstCandidate, {from: firstDelegator, value: MIN_STAKE}).should.be.fulfilled + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) + + await mockEoC() + + MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) + + await consensus.delegate(firstCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled + await consensus.delegate(secondCandidate, {from: firstDelegator, value: ONE_ETHER}).should.be.fulfilled + + MIN_STAKE.mul(TWO).add(ONE_ETHER).should.be.bignumber.equal(await consensus.totalStakeAmount()) + MIN_STAKE.mul(TWO).add(ONE_ETHER).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ONE_ETHER.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + + await mockEoC() + + MIN_STAKE.mul(TWO).add(ONE_ETHER).should.be.bignumber.equal(await consensus.totalStakeAmount()) + MIN_STAKE.mul(TWO).add(ONE_ETHER).should.be.bignumber.equal(await consensus.stakeAmount(firstCandidate)) + ONE_ETHER.should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) + }) }) }) }) @@ -558,7 +745,7 @@ contract('Consensus', async (accounts) => { pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) - await mockEoF() + await mockEoC() MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) // initial validator did not stake so he is not in the pending validators list @@ -582,7 +769,7 @@ contract('Consensus', async (accounts) => { let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - await mockEoF() + await mockEoC() MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) // initial validator did not stake so he is not in the pending validators list ONE.should.be.bignumber.equal(await consensus.currentValidatorsLength()) @@ -605,7 +792,7 @@ contract('Consensus', async (accounts) => { let defaultValidatorFee = await consensus.DEFAULT_VALIDATOR_FEE() defaultValidatorFee.should.be.bignumber.equal(await consensus.validatorFee(firstCandidate)) - await mockEoF() + await mockEoC() MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) // initial validator did not stake so he is not in the pending validators list ONE.should.be.bignumber.equal(await consensus.currentValidatorsLength()) @@ -637,7 +824,7 @@ contract('Consensus', async (accounts) => { pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) - await mockEoF() + await mockEoC() MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) @@ -659,7 +846,7 @@ contract('Consensus', async (accounts) => { pendingValidators.length.should.be.equal(1) pendingValidators[0].should.be.equal(firstCandidate) - await mockEoF() + await mockEoC() MORE_THAN_MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) @@ -677,7 +864,7 @@ contract('Consensus', async (accounts) => { pendingValidators = await consensus.pendingValidators() pendingValidators.length.should.be.equal(2) - await mockEoF() + await mockEoC() MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) }) @@ -716,7 +903,7 @@ contract('Consensus', async (accounts) => { MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.stakeAmount(secondCandidate)) ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) - await mockEoF() + await mockEoC() MIN_STAKE.mul(FOUR).should.be.bignumber.equal(await consensus.totalStakeAmount()) }) }) @@ -777,7 +964,7 @@ contract('Consensus', async (accounts) => { delegatorsLength.should.be.bignumber.equal(toBN(1)) firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - await mockEoF() + await mockEoC() MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) @@ -803,7 +990,7 @@ contract('Consensus', async (accounts) => { delegatorsLength.should.be.bignumber.equal(toBN(1)) firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - await mockEoF() + await mockEoC() MAX_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) @@ -844,7 +1031,7 @@ contract('Consensus', async (accounts) => { delegatorsLength.should.be.bignumber.equal(toBN(1)) firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(firstCandidate, 0)) - await mockEoF() + await mockEoC() MIN_STAKE.should.be.bignumber.equal(await consensus.totalStakeAmount()) }) @@ -876,7 +1063,7 @@ contract('Consensus', async (accounts) => { delegatorsLength.should.be.bignumber.equal(toBN(1)) firstDelegator.should.be.equal(await consensus.delegatorsAtPosition(secondCandidate, 0)) - await mockEoF() + await mockEoC() MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) }) it('multiple times according to staked amount, in more than one transaction', async () => { @@ -1068,7 +1255,7 @@ contract('Consensus', async (accounts) => { // stake await consensus.sendTransaction({from: secondCandidate, value: MIN_STAKE}) - // await mockEoF() + // await mockEoC() // withdraw await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}) MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) @@ -1122,7 +1309,7 @@ contract('Consensus', async (accounts) => { await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - await mockEoF() + await mockEoC() // withdraw const firstCandidateBalance = toBN(await web3.eth.getBalance(firstCandidate)) await consensus.methods['withdraw(uint256)'](MIN_STAKE, {from: firstCandidate}).should.be.fulfilled @@ -1142,7 +1329,7 @@ contract('Consensus', async (accounts) => { await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE}) MIN_STAKE.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - await mockEoF() + await mockEoC() // withdraw // console.log(await web3.eth.getBalance(firstCandidate)) const firstCandidateBalance = toBN(await web3.eth.getBalance(firstCandidate)) @@ -1161,7 +1348,7 @@ contract('Consensus', async (accounts) => { await consensus.sendTransaction({from: firstCandidate, value: MIN_STAKE.mul(TWO)}) MIN_STAKE.mul(TWO).should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - await mockEoF() + await mockEoC() MIN_STAKE.mul(TWO).should.be.bignumber.equal(await consensus.totalStakeAmount()) // withdraw @@ -1185,7 +1372,7 @@ contract('Consensus', async (accounts) => { await consensus.sendTransaction({from: firstCandidate, value: stake}) stake.should.be.bignumber.equal(await web3.eth.getBalance(consensus.address)) - await mockEoF() + await mockEoC() stake.should.be.bignumber.equal(await consensus.totalStakeAmount()) // withdraw 1st time From 1d8590e41161eaeee45b367c2fcbd2aa0b65fa14 Mon Sep 17 00:00:00 2001 From: Leon Prouger Date: Wed, 7 Oct 2020 17:15:45 +0300 Subject: [PATCH 18/19] taking care of block reward without total stake --- contracts/BlockReward.sol | 4 +- test/blockReward.test.js | 35 +++++++++-------- test/consensus.test.js | 83 +-------------------------------------- 3 files changed, 23 insertions(+), 99 deletions(-) diff --git a/contracts/BlockReward.sol b/contracts/BlockReward.sol index 043790b..05c22ed 100644 --- a/contracts/BlockReward.sol +++ b/contracts/BlockReward.sol @@ -188,7 +188,9 @@ contract BlockReward is EternalStorage, BlockRewardBase { uint256 stakeAmount = consensus.stakeAmount(_validator); uint256 totalStakeAmount = consensus.totalStakeAmount(); uint256 currentValidatorsLength = consensus.currentValidatorsLength(); - if (currentValidatorsLength == 0) { + // this may arise in peculiar cases when the consensus totalStakeAmount wasn't calculated yet + // for example at the first blocks after the contract was deployed + if (totalStakeAmount == 0) { return getBlockRewardAmount(); } return getBlockRewardAmount().mul(stakeAmount).mul(currentValidatorsLength).div(totalStakeAmount); diff --git a/test/blockReward.test.js b/test/blockReward.test.js index 08c750d..c41b744 100644 --- a/test/blockReward.test.js +++ b/test/blockReward.test.js @@ -96,12 +96,9 @@ contract('BlockReward', async (accounts) => { await consensus.setTotalStakeAmountMock(minStakeAmount.mul(TEN)) const l = await consensus.currentValidatorsLength() - console.log(l.toString(10)) - console.log(blockRewardAmount.toString(10)) '1'.should.be.equal(l.toString(10)) const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) const expectedReward = blockRewardAmount.div(TEN) expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) }) @@ -110,8 +107,10 @@ contract('BlockReward', async (accounts) => { await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled await consensus.setTotalStakeAmountMock(minStakeAmount) + const l = await consensus.currentValidatorsLength() + '1'.should.be.equal(l.toString(10)) + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) const expectedReward = blockRewardAmount expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) }) @@ -123,7 +122,6 @@ contract('BlockReward', async (accounts) => { await consensus.setCurrentValidatorsLengthMock(TWO) const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) // expected reward calculation const expectedReward = blockRewardAmount.div(TEN).mul(TWO) @@ -139,8 +137,6 @@ contract('BlockReward', async (accounts) => { '2'.should.be.equal(l.toString(10)) const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) - // expected reward calculation const expectedReward = blockRewardAmount.div(TEN).mul(TWO) expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) @@ -153,7 +149,6 @@ contract('BlockReward', async (accounts) => { await consensus.setCurrentValidatorsLengthMock(TWO) const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) - console.log(`blockReward: ${blockRewardAmount.toString(10)}, blockRewardAmountOfValidator ${blockRewardAmountOfV.toString(10)}`) // validator stake is 5 * minStakeAmount now await consensus.sendTransaction({ from: validator, value: minStakeAmount.mul(toBN(4)) }).should.be.fulfilled @@ -180,6 +175,22 @@ contract('BlockReward', async (accounts) => { expectedReward = blockRewardAmount.mul(THREE).div(FOUR).mul(TWO) expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) }) + + it('block reward without the total stake', async () => { + const minStakeAmount = await consensus.getMinStake() + + const validator = accounts[1] + await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled + // await consensus.setTotalStakeAmountMock(minStakeAmount) + + const l = await consensus.currentValidatorsLength() + '1'.should.be.equal(l.toString(10)) + + const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) + const expectedReward = blockRewardAmount + expectedReward.should.be.bignumber.equal(blockRewardAmountOfV) + }) + }) it('can only be called by system address', async () => { @@ -214,7 +225,6 @@ contract('BlockReward', async (accounts) => { logs[0].args['receivers'].should.deep.equal([validator]) logs[0].args['rewards'][0].should.be.bignumber.equal(blockRewardAmount) let expectedSupply = initialSupply.add(blockRewardAmount) - console.log({ blockRewardAmount }) expectedSupply.should.be.bignumber.equal(await blockReward.getTotalSupply()) }) it('should give rewards to validator and its delegators', async () => { @@ -236,7 +246,6 @@ contract('BlockReward', async (accounts) => { await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) let initialSupply = await blockReward.getTotalSupply() let blockRewardAmount = await blockReward.getBlockRewardAmountPerValidator(validator) - console.log({ blockRewardAmount }) let {logs} = await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled logs.length.should.be.equal(1) logs[0].event.should.be.equal('Rewarded') @@ -259,14 +268,11 @@ contract('BlockReward', async (accounts) => { await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) await consensus.setTotalStakeAmountMock(0) await consensus.sendTransaction({ from: validator, value: minStakeAmount }).should.be.fulfilled - let decimals = await blockReward.DECIMALS() let initialSupply = await blockReward.getTotalSupply() let blocksPerYear = await blockReward.getBlocksPerYear() let inflation = await blockReward.getInflation() let blockRewardAmount = await blockReward.getBlockRewardAmount() - console.log(blockRewardAmount.toString(10)) - // console.log(`initialSupply: ${initialSupply.div(decimals).toNumber()}, blockRewardAmount: ${blockRewardAmount.div(decimals).toNumber()}`) // each of the following calls advances a block let i = 0 @@ -277,16 +283,13 @@ contract('BlockReward', async (accounts) => { blockNumber = await web3.eth.getBlockNumber() i++ } - // console.log('i', i) let totalSupply = await blockReward.getTotalSupply() let newBlockRewardAmount = await blockReward.getBlockRewardAmount() - // console.log(`totalSupply: ${totalSupply.div(decimals).toNumber()}, newBlockRewardAmount: ${newBlockRewardAmount.div(decimals).toNumber()}`) let expectedSupply = initialSupply for (let j = 0; j < i; j++) { expectedSupply = expectedSupply.add(blockRewardAmount) } - // console.log(`expectedSupply: ${expectedSupply.div(decimals).toNumber()}`) totalSupply.should.be.bignumber.equal(expectedSupply) newBlockRewardAmount.should.be.bignumber.equal((totalSupply.mul(decimals).mul(inflation).div(toBN(100))).div(blocksPerYear).div(decimals)) }) diff --git a/test/consensus.test.js b/test/consensus.test.js index a774cbd..037f4af 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -1144,93 +1144,12 @@ contract('Consensus', async (accounts) => { await blockReward.cycleMock().should.be.fulfilled false.should.be.equal(await consensus.hasCycleEnded()) }) - // it('shouldTakeSnapshot', async () => { - // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // let lastSnapshotTakenAtBlock = await consensus.getLastSnapshotTakenAtBlock() - // let currentBlockNumber = toBN(await web3.eth.getBlockNumber()) - // let shouldTakeSnapshot = (currentBlockNumber.sub(lastSnapshotTakenAtBlock)).gte(blocksToSnapshot) - // shouldTakeSnapshot.should.be.equal(await consensus.shouldTakeSnapshot()) - // }) - // it('getRandom', async () => { - // let repeats = 25 - // let randoms = [] - // for (let i = 0; i < repeats; i++) { - // randoms.push((await consensus.getRandom(0, SNAPSHOTS_PER_CYCLE)).toNumber()) - // await advanceBlocks(1) - // } - // randoms.length.should.be.equal(repeats) - // let distincts = [...new Set(randoms)] - // distincts.length.should.be.greaterThan(1) - // distincts.length.should.be.most(SNAPSHOTS_PER_CYCLE) - // }) + it('cycle function should only be called by BlockReward', async () => { await consensus.cycle().should.be.rejectedWith(ERROR_MSG) await proxyStorage.setBlockRewardMock(owner) await consensus.cycle().should.be.fulfilled }) - // it('snapshot with less validators than MAX_VALIDATORS - entire set should be saved', async () => { - // let expectedValidators = [] - // for (let i = 1; i <= MAX_VALIDATORS - 1; i++) { - // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - // expectedValidators.push(accounts[i-1]) - // } - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // let snapshotId = await consensus.getNextSnapshotId() - // await advanceBlocks(blocksToSnapshot) - // await proxyStorage.setBlockRewardMock(owner) - // await consensus.cycle().should.be.fulfilled - // let snapshot = await consensus.getSnapshotAddresses(snapshotId) - // snapshot.length.should.be.equal(expectedValidators.length) - // snapshot.forEach(address => { - // expectedValidators.splice(expectedValidators.indexOf(address), 1) - // }) - // expectedValidators.length.should.be.equal(0) - // }) - // it('snapshot with exactly MAX_VALIDATORS validators - entire set should be saved', async () => { - // let expectedValidators = [] - // for (let i = 1; i <= MAX_VALIDATORS; i++) { - // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - // expectedValidators.push(accounts[i-1]) - // } - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // let snapshotId = await consensus.getNextSnapshotId() - // await advanceBlocks(blocksToSnapshot) - // await proxyStorage.setBlockRewardMock(owner) - // await consensus.cycle().should.be.fulfilled - // let snapshot = await consensus.getSnapshotAddresses(snapshotId) - // snapshot.length.should.be.equal(expectedValidators.length) - // snapshot.forEach(address => { - // expectedValidators.splice(expectedValidators.indexOf(address), 1) - // }) - // expectedValidators.length.should.be.equal(0) - // }) - // it('snapshot with more validators than MAX_VALIDATORS - random set should be saved', async () => { - // let expectedValidators = [] - // for (let i = 1; i <= MAX_VALIDATORS + 1; i++) { - // await consensus.sendTransaction({from: accounts[i-1], value: MIN_STAKE}).should.be.fulfilled - // expectedValidators.push(accounts[i-1]) - // } - // pendingValidators = await consensus.pendingValidators() - // pendingValidators.length.should.be.equal(expectedValidators.length) - // pendingValidators.should.deep.equal(expectedValidators) - // let blocksToSnapshot = await consensus.getBlocksToSnapshot() - // let snapshotId = await consensus.getNextSnapshotId() - // await advanceBlocks(blocksToSnapshot) - // await proxyStorage.setBlockRewardMock(owner) - // await consensus.cycle().should.be.fulfilled - // let snapshot = await consensus.getSnapshotAddresses(snapshotId) - // snapshot.length.should.be.equal(MAX_VALIDATORS) - // snapshot.forEach(address => { - // expectedValidators.splice(expectedValidators.indexOf(address), 1) - // }) - // expectedValidators.length.should.be.equal(pendingValidators.length - MAX_VALIDATORS) - // }) }) describe('withdraw', async () => { From 80c08e147b0834af9ba3c694d02ec6dda795fc37 Mon Sep 17 00:00:00 2001 From: roman Date: Mon, 2 Nov 2020 13:12:40 +0200 Subject: [PATCH 19/19] added new tests --- .solcover.js | 22 ++ .solhint.json | 22 ++ .soliumrc.json | 44 +++ contracts/ConsensusUtils.sol | 2 +- contracts/test/ConsensusMock.sol | 13 +- contracts/test/VotingMock.sol | 11 + package.json | 11 +- test/blockReward.test.js | 229 ++++++++++++++- test/consensus.test.js | 1 - test/proxyStorage.test.js | 35 +++ test/utils.js | 478 +++++++++++++++++++++++++++++++ test/voting.test.js | 282 +++++++++--------- truffle-config.js | 2 + 13 files changed, 1009 insertions(+), 143 deletions(-) create mode 100644 .solcover.js create mode 100644 .solhint.json create mode 100644 .soliumrc.json create mode 100644 test/utils.js diff --git a/.solcover.js b/.solcover.js new file mode 100644 index 0000000..03db1f6 --- /dev/null +++ b/.solcover.js @@ -0,0 +1,22 @@ +module.exports = { + skipFiles: [ + 'Migrations.sol', + 'test/BlockRewardMock.sol', + 'test/ConsensusMock.sol', + 'test/EternalStorageProxyMock.sol', + 'test/ProxyStorageMock.sol', + 'test/VotingMock.sol', + ], + // need for dependencies + copyNodeModules: true, + copyPackages: [ + 'openzeppelin-solidity' + ], + dir: '.', + providerOptions: { + total_accounts: 110, + default_balance_ether: 100000000, + gasPrice: '0x1' + }, + norpc: false +}; diff --git a/.solhint.json b/.solhint.json new file mode 100644 index 0000000..217db7a --- /dev/null +++ b/.solhint.json @@ -0,0 +1,22 @@ +{ + "extends": "solhint:default", + "rules": { + "avoid-throw": "off", + "avoid-suicide": "error", + "avoid-sha3": "warn", + "indent": ["warn", 4], + "compiler-fixed": "off", + "not-rely-on-time": "off", + "quotes": ["error", "double"], + "no-empty-blocks": "off", + "no-complex-fallback": "off", + "two-lines-top-level-separator": "off", + "code-complexity": 8, + "avoid-call-value": "off", + "no-simple-event-func-name": "off", + "avoid-low-level-calls": "off", + "no-inline-assembly": "off", + "max-line-length": 170, + "bracket-align": "off" + } +} diff --git a/.soliumrc.json b/.soliumrc.json new file mode 100644 index 0000000..3f27141 --- /dev/null +++ b/.soliumrc.json @@ -0,0 +1,44 @@ +{ + "extends": "solium:recommended", + "plugins": [ + "security" + ], + "rules": { + "quotes": [ + "error", + "double" + ], + "indentation": [ + "error", + 4 + ], + "max-len": ["error", 79], + "lbrace": "off", + "linebreak-style": ["error", "unix"], + "no-constant": ["error"], + "no-empty-blocks": "off", + "uppercase": "off", + "visibility-first": "error", + "security/enforce-explicit-visibility": ["error"], + "security/no-block-members": ["warning"], + "security/no-inline-assembly": ["warning"], + "blank-lines": "off", + "imports-on-top": "error", + "array-declarations": "warning", + "operator-whitespace": "warning", + "conditionals-whitespace": "warning", + "semicolon-whitespace": "warning", + "function-whitespace": "warning", + "mixedcase": "warning", + "no-unused-vars": "warning", + "pragma-on-top": "error", + "function-order": "warning", + "emit": "error", + "value-in-payable": "error", + "error-reason": "warning", + "no-experimental": "warning", + "deprecated-suicide": "error", + "whitespace": "warning", + "arg-overflow": "error" + } +} diff --git a/contracts/ConsensusUtils.sol b/contracts/ConsensusUtils.sol index 79f292b..e87e258 100644 --- a/contracts/ConsensusUtils.sol +++ b/contracts/ConsensusUtils.sol @@ -189,7 +189,7 @@ contract ConsensusUtils is EternalStorage, ValidatorSet { /** * returns number of blocks per cycle (block time is 5 seconds) */ - function getCycleDurationBlocks() public pure returns(uint256) { + function getCycleDurationBlocks() public view returns(uint256) { return CYCLE_DURATION_BLOCKS; } diff --git a/contracts/test/ConsensusMock.sol b/contracts/test/ConsensusMock.sol index 1483d5c..fea7d37 100644 --- a/contracts/test/ConsensusMock.sol +++ b/contracts/test/ConsensusMock.sol @@ -4,6 +4,7 @@ import "../Consensus.sol"; contract ConsensusMock is Consensus { uint256 currentValidatorsLengthMock = 0; + uint256 private blockTest = 120; function setSystemAddressMock(address _newAddress) public onlyOwner { addressStorage[SYSTEM_ADDRESS] = _newAddress; @@ -49,8 +50,16 @@ contract ConsensusMock is Consensus { return 5e22; } - function getCycleDurationBlocks() public pure returns(uint256) { - return 120; + function getCycleDurationBlocks() public view returns(uint256) { + return blockTest == 0 ? 120 : blockTest; + } + + function setCycleDurationBlocks(uint256 _block) public { + blockTest = _block; + } + + function setCurrentCycleEndBlock(uint256 _value) public { + uintStorage[CURRENT_CYCLE_END_BLOCK] = _value; } function getSnapshotsPerCycle() public pure returns(uint256) { diff --git a/contracts/test/VotingMock.sol b/contracts/test/VotingMock.sol index f2e21ac..fd545bd 100644 --- a/contracts/test/VotingMock.sol +++ b/contracts/test/VotingMock.sol @@ -7,4 +7,15 @@ contract VotingMock is Voting { function setNextBallotIdMock(uint256 _id) public { uintStorage[NEXT_BALLOT_ID] = _id; } + + function setAcceptedMock(uint256 _id, uint256 _value) public { + _setAccepted(_id, _value); + } + + function setBalotStartBlockMock(uint256 _balotId, uint256 block) public { + uintStorage[keccak256(abi.encodePacked("votingState", _balotId, "startBlock"))] = block; + } + function setBalotEndBlockMock(uint256 _balotId, uint256 block) public { + uintStorage[keccak256(abi.encodePacked("votingState", _balotId, "endBlock"))] = block; + } } diff --git a/package.json b/package.json index b25d780..090df67 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,15 @@ "main": "", "scripts": { "test": "scripts/test.sh", + "coverage": "node_modules/.bin/truffle run coverage", "compile": "node_modules/.bin/truffle compile", "flatten": "scripts/flatten.sh", "abi": "scripts/abi.sh", "deploy:fuse": "node_modules/.bin/truffle migrate --reset --network fuse", "deploy:local": "node_modules/.bin/truffle migrate --reset --network local", - "app": "node app/index.js" + "app": "node app/index.js", + "solhint": "node ./node_modules/solhint/solhint.js contracts/*.sol", + "solium": "solium -d contracts/" }, "repository": { "type": "git", @@ -42,6 +45,10 @@ "node-jq": "^1.9.0", "solc": "0.4.24", "truffle": "^5.0.24", - "truffle-flattener": "^1.3.0" + "truffle-flattener": "^1.3.0", + "solidity-coverage": "^0.7.11", + "solhint": "^2.3.0", + "solium": "^1.2.5", + "bn": "^1.0.5" } } diff --git a/test/blockReward.test.js b/test/blockReward.test.js index c41b744..f71a1a3 100644 --- a/test/blockReward.test.js +++ b/test/blockReward.test.js @@ -4,10 +4,12 @@ const Consensus = artifacts.require('ConsensusMock.sol') const ProxyStorage = artifacts.require('ProxyStorageMock.sol') const EternalStorageProxy = artifacts.require('EternalStorageProxyMock.sol') const BlockReward = artifacts.require('BlockRewardMock.sol') -const Voting = artifacts.require('Voting.sol') +const Voting = artifacts.require('VotingMock.sol') const { ERROR_MSG, ZERO_ADDRESS, RANDOM_ADDRESS } = require('./helpers') +const utils = require("./utils"); const { ZERO, ONE, TWO, THREE, FOUR, TEN } = require('./helpers') const {toBN, toWei, toChecksumAddress} = web3.utils +const CONTRACT_TYPES = { INVALID: 0, CONSENSUS: 1, BLOCK_REWARD: 2, PROXY_STORAGE: 3, VOTING: 4 } const INITIAL_SUPPLY = toWei(toBN(300000000000000000 || 0), 'gwei') const BLOCKS_PER_YEAR = 100 @@ -19,7 +21,7 @@ contract('BlockReward', async (accounts) => { let owner = accounts[0] let nonOwner = accounts[1] let mockSystemAddress = accounts[2] - let voting = accounts[3] + let voting beforeEach(async () => { // Consensus @@ -43,7 +45,7 @@ contract('BlockReward', async (accounts) => { // Voting const votingImpl = await Voting.new() proxy = await EternalStorageProxy.new(proxyStorage.address, votingImpl.address) - const voting = await Voting.at(proxy.address) + voting = await Voting.at(proxy.address) // Initialize ProxyStorage await proxyStorage.initializeAddresses( @@ -185,6 +187,8 @@ contract('BlockReward', async (accounts) => { const l = await consensus.currentValidatorsLength() '1'.should.be.equal(l.toString(10)) + const k = await consensus.requiredSignatures() + '1'.should.be.equal(k.toString(10)) const blockRewardAmountOfV = await blockReward.getBlockRewardAmountPerValidator(validator) const expectedReward = blockRewardAmount @@ -308,6 +312,225 @@ contract('BlockReward', async (accounts) => { // let blockRewardAmount = await blockReward.getBlockRewardAmountPerValidator(validator) // let {logs} = await blockReward.reward([validator], [0], {from: mockSystemAddress}).should.be.fulfilled }) + + describe('custom', async () =>{ + const validator = accounts[3] + beforeEach(async () => { + // Consensus + consensusImpl = await Consensus.new() + proxy = await EternalStorageProxy.new(ZERO_ADDRESS, consensusImpl.address) + consensus = await Consensus.at(proxy.address) + await consensus.initialize(owner) + + // ProxyStorage + proxyStorageImpl = await ProxyStorage.new() + proxy = await EternalStorageProxy.new(ZERO_ADDRESS, proxyStorageImpl.address) + proxyStorage = await ProxyStorage.at(proxy.address) + await proxyStorage.initialize(consensus.address) + await consensus.setProxyStorage(proxyStorage.address) + + // BlockReward + blockRewardImpl = await BlockReward.new() + proxy = await EternalStorageProxy.new(proxyStorage.address, blockRewardImpl.address) + blockReward = await BlockReward.at(proxy.address) + await blockReward.initialize(toWei(toBN(300000000000000000 || 0), 'gwei')) + + // Voting + votingImpl = await Voting.new() + proxy = await EternalStorageProxy.new(proxyStorage.address, votingImpl.address) + voting = await Voting.at(proxy.address) + + // Initialize ProxyStorage + await proxyStorage.initializeAddresses( + blockReward.address, + voting.address + ) + let ballotLimitPerValidator = (await voting.getBallotLimitPerValidator()).toNumber() + ballotLimitPerValidator.should.be.equal(Math.floor(100)) + await consensus.setNewValidatorSetMock([validator]) + await consensus.setFinalizedMock(false, {from: owner}) + await consensus.setSystemAddressMock(owner, {from: owner}) + await consensus.finalizeChange().should.be.fulfilled + + true.should.be.equal(await voting.isValidVotingKey(validator)) + + }) + it('new test', async () => { + const validator = accounts[3]; + await voting.initialize().should.be.fulfilled + const minStakeAmount = await consensus.getMinStake(); + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + await consensus.setTotalStakeAmountMock(minStakeAmount) + await consensus.sendTransaction({from: validator, value: minStakeAmount}).should.be.fulfilled + await consensus.setCycleDurationBlocks(1); + + let proposedValue = RANDOM_ADDRESS + let contractType = CONTRACT_TYPES.CONSENSUS + const CYCLE_DURATION_BLOCKS = 120; + const voteCyclesDuration = 10 + let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() + let voteStartAfterNumberOfCycles = 1 + let voteStartAfterNumberOfBlocks = toBN(voteStartAfterNumberOfCycles).mul(toBN(CYCLE_DURATION_BLOCKS)) + let startBlock = currentCycleEndBlock.add(voteStartAfterNumberOfBlocks) + let voteEndAfterNumberOfBlocks = toBN(voteCyclesDuration).mul(toBN(CYCLE_DURATION_BLOCKS)) + let endBlock = startBlock.add(voteEndAfterNumberOfBlocks) + + let {logs} = await voting.newBallot( + voteStartAfterNumberOfCycles, + voteCyclesDuration, + contractType, + proposedValue, 'description', {from: validator}).should.be.fulfilled + console.log(logs[0].event); + logs[0].args['id'].should.be.bignumber.equal(toBN(0)) + logs[0].args['creator'].should.be.equal(validator) + + console.log('activeBallots',await voting.activeBallots.call()); + await consensus.setCycleDurationBlocks(1); + await consensus.setCurrentCycleEndBlock(5); + console.log('getCurrentCycleEndBlock', toBN(await consensus.getCurrentCycleEndBlock.call()).toString()); + let block = await web3.eth.getBlock("latest") + console.log('block.number', block.number) + console.log('getCurrentCycleEndBlock', toBN(await consensus.getCurrentCycleEndBlock.call()).toString()); + true.should.be.equal(await consensus.hasCycleEnded.call()) + console.log('currentValidatorsLength',await consensus.currentValidatorsLength.call()) + console.log('activeBallotsLength',await voting.activeBallotsLength.call()) + console.log('activeBallotsAtIndex',await voting.activeBallotsAtIndex(0)) + console.log('canBeFinalized',await voting.canBeFinalized(0)) + await voting.setAcceptedMock(0,3); + console.log('getAccepted',await voting.getAccepted(0)) + console.log('getRejected',await voting.getRejected(0)) + console.log('getContractType',await voting.getContractType(0)) + console.log('getProposedValue',await voting.getProposedValue(0)) + { + await voting.setBalotStartBlockMock(0, block.number -2); + await voting.setBalotEndBlockMock(0, block.number + 2); + console.log('getStartBlock', await voting.getStartBlock(0)) + console.log('getFinalizeCalled', await voting.getFinalizeCalled(0)) + console.log('canBeFinalized', await voting.canBeFinalized(0)) + await blockReward.reward([validator], [0], {from: mockSystemAddress}) + .then(utils.receiptShouldSucceed) + // .catch(utils.catchReceiptShouldFailed); + + // let {logs} = + + // console.log('****',logs.length); + // console.log('****',logs[0].event); + } + }) + it('new test2', async () => { + const validator = accounts[3]; + await voting.initialize().should.be.fulfilled + const minStakeAmount = await consensus.getMinStake(); + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + await consensus.setTotalStakeAmountMock(minStakeAmount) + await consensus.sendTransaction({from: validator, value: minStakeAmount}).should.be.fulfilled + await consensus.setCycleDurationBlocks(1); + + let proposedValue = RANDOM_ADDRESS + let contractType = CONTRACT_TYPES.PROXY_STORAGE + const voteCyclesDuration = 10 + let voteStartAfterNumberOfCycles = 1 + + let {logs} = await voting.newBallot( + voteStartAfterNumberOfCycles, + voteCyclesDuration, + contractType, + proposedValue, 'description', {from: validator}).should.be.fulfilled + console.log(logs[0].event); + logs[0].args['id'].should.be.bignumber.equal(toBN(0)) + logs[0].args['creator'].should.be.equal(validator) + + console.log('activeBallots',await voting.activeBallots.call()); + await consensus.setCycleDurationBlocks(1); + await consensus.setCurrentCycleEndBlock(5); + console.log('getCurrentCycleEndBlock', toBN(await consensus.getCurrentCycleEndBlock.call()).toString()); + let block = await web3.eth.getBlock("latest") + console.log('block.number', block.number) + console.log('getCurrentCycleEndBlock', toBN(await consensus.getCurrentCycleEndBlock.call()).toString()); + true.should.be.equal(await consensus.hasCycleEnded.call()) + console.log('currentValidatorsLength',await consensus.currentValidatorsLength.call()) + console.log('activeBallotsLength',await voting.activeBallotsLength.call()) + console.log('activeBallotsAtIndex',await voting.activeBallotsAtIndex(0)) + console.log('canBeFinalized',await voting.canBeFinalized(0)) + await voting.setAcceptedMock(0,3); + console.log('getAccepted',await voting.getAccepted(0)) + console.log('getRejected',await voting.getRejected(0)) + console.log('getContractType',await voting.getContractType(0)) + console.log('getProposedValue',await voting.getProposedValue(0)) + { + await voting.setBalotStartBlockMock(0, block.number -2); + await voting.setBalotEndBlockMock(0, block.number + 2); + console.log('getStartBlock', await voting.getStartBlock(0)) + console.log('getFinalizeCalled', await voting.getFinalizeCalled(0)) + console.log('canBeFinalized', await voting.canBeFinalized(0)) + // await blockReward.reward([validator], [0], {from: mockSystemAddress}) + // .then(utils.receiptShouldSucceed) + } + }) + it('new test3', async () => { + const validator = accounts[3]; + await voting.initialize().should.be.fulfilled + const minStakeAmount = await consensus.getMinStake(); + await blockReward.setSystemAddressMock(mockSystemAddress, {from: owner}) + await consensus.setTotalStakeAmountMock(minStakeAmount) + await consensus.sendTransaction({from: validator, value: minStakeAmount}).should.be.fulfilled + await consensus.setCycleDurationBlocks(1); + + let proposedValue = RANDOM_ADDRESS + let contractType = CONTRACT_TYPES.VOTING + const CYCLE_DURATION_BLOCKS = 120; + const voteCyclesDuration = 10 + let currentCycleEndBlock = await consensus.getCurrentCycleEndBlock() + let voteStartAfterNumberOfCycles = 1 + let voteStartAfterNumberOfBlocks = toBN(voteStartAfterNumberOfCycles).mul(toBN(CYCLE_DURATION_BLOCKS)) + let startBlock = currentCycleEndBlock.add(voteStartAfterNumberOfBlocks) + let voteEndAfterNumberOfBlocks = toBN(voteCyclesDuration).mul(toBN(CYCLE_DURATION_BLOCKS)) + let endBlock = startBlock.add(voteEndAfterNumberOfBlocks) + + let {logs} = await voting.newBallot( + voteStartAfterNumberOfCycles, + voteCyclesDuration, + contractType, + proposedValue, 'description', {from: validator}).should.be.fulfilled + console.log(logs[0].event); + logs[0].args['id'].should.be.bignumber.equal(toBN(0)) + logs[0].args['creator'].should.be.equal(validator) + + console.log('activeBallots',await voting.activeBallots.call()); + await consensus.setCycleDurationBlocks(1); + await consensus.setCurrentCycleEndBlock(5); + console.log('getCurrentCycleEndBlock', toBN(await consensus.getCurrentCycleEndBlock.call()).toString()); + let block = await web3.eth.getBlock("latest") + console.log('block.number', block.number) + console.log('getCurrentCycleEndBlock', toBN(await consensus.getCurrentCycleEndBlock.call()).toString()); + true.should.be.equal(await consensus.hasCycleEnded.call()) + console.log('currentValidatorsLength',await consensus.currentValidatorsLength.call()) + console.log('activeBallotsLength',await voting.activeBallotsLength.call()) + console.log('activeBallotsAtIndex',await voting.activeBallotsAtIndex(0)) + console.log('canBeFinalized',await voting.canBeFinalized(0)) + await voting.setAcceptedMock(0,3); + console.log('getAccepted',await voting.getAccepted(0)) + console.log('getRejected',await voting.getRejected(0)) + console.log('getContractType',await voting.getContractType(0)) + console.log('getProposedValue',await voting.getProposedValue(0)) + { + await voting.setBalotStartBlockMock(0, block.number -2); + await voting.setBalotEndBlockMock(0, block.number + 2); + console.log('getStartBlock', await voting.getStartBlock(0)) + console.log('getFinalizeCalled', await voting.getFinalizeCalled(0)) + console.log('canBeFinalized', await voting.canBeFinalized(0)) + await blockReward.reward([validator], [0], {from: mockSystemAddress}) + .then(utils.receiptShouldSucceed) + // .catch(utils.catchReceiptShouldFailed); + + // let {logs} = + + // console.log('****',logs.length); + // console.log('****',logs[0].event); + } + }) + }); + }) describe('emitRewardedOnCycle', function () { diff --git a/test/consensus.test.js b/test/consensus.test.js index 037f4af..7eda548 100644 --- a/test/consensus.test.js +++ b/test/consensus.test.js @@ -85,7 +85,6 @@ contract('Consensus', async (accounts) => { MIN_STAKE.should.be.bignumber.equal(await consensus.getMinStake()) MAX_STAKE.should.be.bignumber.equal(await consensus.getMaxStake()) toBN(MAX_VALIDATORS).should.be.bignumber.equal(await consensus.getMaxValidators()) - toBN(CYCLE_DURATION_BLOCKS).should.be.bignumber.equal(await consensus.getCycleDurationBlocks()) toBN(SNAPSHOTS_PER_CYCLE).should.be.bignumber.equal(await consensus.getSnapshotsPerCycle()) ZERO.should.be.bignumber.equal(await consensus.stakeAmount(initialValidator)) ZERO.should.be.bignumber.equal(await consensus.totalStakeAmount()) diff --git a/test/proxyStorage.test.js b/test/proxyStorage.test.js index 547e244..6712205 100644 --- a/test/proxyStorage.test.js +++ b/test/proxyStorage.test.js @@ -119,4 +119,39 @@ contract('ProxyStorage', async (accounts) => { true.should.be.equal(await proxyStorageNew.isInitialized()) }) }) + describe('Ownership', async () => { + let proxyStorageNew + let proxyStorageStub = accounts[8] + beforeEach(async () => { + proxyStorageNew = await ProxyStorage.new() + await proxy.setProxyStorageMock(proxyStorageStub) + }) + it('transfer ownership', async () => { + await proxy.transferOwnership(accounts[1], {from: owner}).should.be.fulfilled + accounts[1].should.be.equal(await proxy.getOwner.call()) + }) + + it('remove owner', async () => { + await proxy.renounceOwnership({from: owner}).should.be.fulfilled + '0x0000000000000000000000000000000000000000'.should.be.equal(await proxy.getOwner.call()) + }) + }) + + describe('_finalizeBallot', async () => { + let proxyStorageNew + let proxyStorageStub = accounts[8] + beforeEach(async () => { + proxyStorageNew = await ProxyStorage.new() + await proxy.setProxyStorageMock(proxyStorageStub) + }) + it('transfer ownership', async () => { + await proxy.transferOwnership(accounts[1], {from: owner}).should.be.fulfilled + accounts[1].should.be.equal(await proxy.getOwner.call()) + }) + + it('remove owner', async () => { + await proxy.renounceOwnership({from: owner}).should.be.fulfilled + '0x0000000000000000000000000000000000000000'.should.be.equal(await proxy.getOwner.call()) + }) + }) }) diff --git a/test/utils.js b/test/utils.js new file mode 100644 index 0000000..0fba724 --- /dev/null +++ b/test/utils.js @@ -0,0 +1,478 @@ +var BN = require('bn.js'); + +var gasToUse = 0x47E7C4; + +function receiptShouldSucceed(result) { + return new Promise(function(resolve, reject) { + var receipt = web3.eth.getTransaction(result.tx); + + if(result.receipt.gasUsed == gasToUse) { + try { + assert.notEqual(result.receipt.gasUsed, gasToUse, "tx failed, used all gas"); + } + catch(err) { + reject(err); + } + } + else { + resolve(); + } + }); +} + +function receiptShouldFailed(result) { + return new Promise(function(resolve, reject) { + var receipt = web3.eth.getTransaction(result.tx); + + if(result.receipt.gasUsed == gasToUse) { + resolve(); + } + else { + try { + assert.equal(result.receipt.gasUsed, gasToUse, "tx succeed, used not all gas"); + } + catch(err) { + reject(err); + } + } + }); +} + +function catchReceiptShouldFailed(err) { + if (err.message.indexOf("invalid opcode") == -1 && err.message.indexOf("revert") == -1) { + throw err; + } +} + +function receiptShouldSucceedS(receipt) { + return new Promise(function(resolve, reject) { + if(receipt.gasUsed == gasToUse) { + try { + assert.notEqual(receipt.gasUsed, gasToUse, "tx failed, used all gas"); + } + catch(err) { + reject(err); + } + } + else { + resolve(); + } + }); +} + +function receiptShouldFailedS(receipt) { + return new Promise(function(resolve, reject) { + if(receipt.gasUsed == gasToUse) { + resolve(); + } + else { + try { + assert.equal(receipt.gasUsed, gasToUse, "tx succeed, used not all gas"); + } + catch(err) { + reject(err); + } + } + }); +} + + +function balanceShouldEqualTo(instance, address, expectedBalance, notCall) { + return new Promise(function(resolve, reject) { + var promise; + + if(notCall) { + promise = instance.balanceOf(address) + .then(function() { + return instance.balanceOf.call(address); + }); + } + else { + promise = instance.balanceOf.call(address); + } + + promise.then(function(balance) { + try { + assert.equal(balance.valueOf(), expectedBalance, "balance is not equal"); + } + catch(err) { + reject(err); + + return; + } + + resolve(); + }); + }); +} + +function getDividend(instance, id) { + return instance.dividends.call(id) + .then(function(obj) { + return { + id: obj[0].valueOf(), + block: obj[1].valueOf(), + time: obj[2].valueOf(), + amount: obj[3].valueOf(), + + claimedAmount: obj[4].valueOf(), + transferedBack: obj[5].valueOf(), + + totalSupply: obj[6].valueOf(), + recycleTime: obj[7].valueOf(), + + recycled: obj[8], + + claimed: obj[9] + } + }); +} + +function checkDividend(dividend, id, amount, claimedAmount, transferedBack, totalSupply, recycleTime, recycled) { + return new Promise(function(resolve, reject) { + try { + assert.equal(dividend.id, id, "dividend id is not equal"); + assert.equal(dividend.amount, amount, "dividend amount id is not equal"); + assert.equal(dividend.claimedAmount, claimedAmount, "dividend claimed amount is not equal"); + assert.equal(dividend.transferedBack, transferedBack, "dividend transfered back is not equal"); + assert.equal(dividend.totalSupply, totalSupply, "dividend total supply is not equal"); + assert.equal(dividend.recycleTime, recycleTime, "dividend recycle time is not equal"); + assert.equal(dividend.recycled, recycled, "dividend recycled is not equal"); + + resolve(); + } + catch(err) { + reject(err); + } + }); +} + +function getEmission(instance, id) { + "use strict"; + + return instance.emissions.call(id) + .then(function(obj) { + return { + blockDuration: obj[0].valueOf(), + blockTokens: obj[1].valueOf(), + periodEndsAt: obj[2].valueOf(), + removed: obj[3].valueOf() + } + }); +} + +function checkEmission(emission, blockDuration, blockTokens, periodEndsAt, removed) { + "use strict"; + + return new Promise(function(resolve, reject) { + try { + assert.equal(emission.blockDuration, blockDuration, "emission blockDuration is not equal"); + assert.equal(emission.blockTokens, blockTokens, "emission blockTokens is not equal"); + assert.equal(emission.periodEndsAt, periodEndsAt, "emission periodEndsAt is not equal"); + assert.equal(emission.removed, removed, "emission removed is not equal"); + + resolve(); + } + catch(err) { + reject(err); + } + }); +} + +function checkClaimedTokensAmount(instance, offsetDate, lastClaimedAt, currentTime, currentBalance, totalSupply, expectedValue) { + return instance.calculateEmissionTokens(offsetDate + lastClaimedAt, offsetDate + currentTime, currentBalance, totalSupply) + .then(function() { + return instance.calculateEmissionTokens.call(offsetDate + lastClaimedAt, offsetDate + currentTime, currentBalance, totalSupply); + }) + .then(function(result) { + assert.equal(result.valueOf(), expectedValue.valueOf(), "amount is not equal"); + }); +} + +function getPhase(instance, id) { + return instance.phases.call(id) + .then(function(obj) { + if(obj.length == 3) { + return { + priceShouldMultiply: obj[0].valueOf(), + price: obj[1].valueOf(), + maxAmount: obj[2].valueOf(), + } + } + + return { + price: obj[0].valueOf(), + maxAmount: obj[1].valueOf(), + } + }); +} + +function checkPhase(phase, price, maxAmount) { + return new Promise(function(resolve, reject) { + try { + assert.equal(phase.price, price, "phase price is not equal"); + assert.equal(phase.maxAmount, maxAmount, "phase maxAmount is not equal"); + + resolve(); + } + catch(err) { + reject(err); + } + }); +} + +function timeout(timeout) { + return new Promise(function(resolve, reject) { + setTimeout(function() { + resolve(); + }, timeout * 1000); + }) +} + +function getEtherBalance(_address) { + return web3.eth.getBalance(_address); +} + +function checkEtherBalance(_address, expectedBalance) { + var balance = web3.eth.getBalance(_address); + + assert.equal(balance.valueOf(), expectedBalance.valueOf(), "address balance is not equal"); +} + +function getTxCost(result) { + var tx = web3.eth.getTransaction(result.tx); + + return result.receipt.gasUsed * tx.gasPrice; +} + +async function timeJump(seconds) { + return new Promise(function(resolve, reject) { + web3.currentProvider.sendAsync({ + jsonrpc: "2.0", + method: "evm_increaseTime", + params: [ seconds ], + id: new Date().getTime(), + }, + function(error) { + if (error) { + return reject(error); + } + + web3.currentProvider.sendAsync( + { + jsonrpc: "2.0", + method: "evm_mine", + params: [], + id: new Date().getTime(), + }, + (err2) => { + if (err2) return reject(err2); + resolve(); + }, + ); + }, + ); + }); +} + +async function sendTransaction(contract, from, value, data, shouldFail) { + try { + await contract.sendTransaction({ from, value, data }); + + if(shouldFail) { + assert.fail("sendTransaction succeed"); + } + } + catch(err) { + if(err.constructor.name == "AssertionError") { + throw err; + } + + if(!shouldFail) { + throw err; + } + } +} + +async function transferERC20(contract, from, to, tokens, shouldFail) { + try { + await contract.transfer(to, tokens, { from }); + + if(shouldFail) { + assert.fail("erc20 transfer succeed"); + } + } + catch(err) { + if(err.constructor.name == "AssertionError") { + throw err; + } + + if(!shouldFail) { + throw err; + } + } +} + +async function balanceERC20(contract, holder, balance) { + assert.equal(await contract.balanceOf(holder), balance, "erc20 balance is not equal"); +} + +async function testTransferFrom(contract, granter, grantee, to, tokens) { + const granterBeforeBalance = await contract.balanceOf(granter); + const granteeBeforeBalance = await contract.balanceOf(grantee); + + await contract.approve(grantee, tokens, { from: granter }); + + // try to transfer more than allowed + + let trasnferFromResponse = await contract.transferFrom.call(granter, to, tokens + 1, {from: grantee}); + + assert.equal(trasnferFromResponse.valueOf(), false, "transferFrom with exceding amount succeed"); + + await contract.transferFrom(granter, to, tokens + 1, { from: grantee }); + + await checkState({ contract }, { + contract: { + balanceOf: [ + {[granter]: granterBeforeBalance}, + {[grantee]: granteeBeforeBalance} + ], + allowance: { + __val: tokens, + _owner: granter, + _spender: grantee + } + } + }); + + // try to transfer less than allowed + transferFromResponse = await contract.transferFrom.call(granter, to, tokens / 2, { from: grantee }); + + assert.equal(transferFromResponse, true, "transferFrom with lower amount failed"); + await contract.transferFrom(granter, to, tokens / 2, { from: grantee }); + + await checkState({ contract }, { + contract: { + balanceOf: [ + { [granter]: new BN(granterBeforeBalance).sub(new BN(tokens).div(2)).valueOf() }, + { [to]: new BN(granteeBeforeBalance).add(new BN(tokens).div(2)).valueOf() } + ], + + allowance: { + __val: new BN(tokens).sub(new BN(tokens).div(2)).valueOf(), + _owner: granter, + _spender: grantee + } + } + }); +} + +async function checkStateMethod(contract, contractId, stateId, args) { + if(Array.isArray(args)) { + for(let item of args) { + await checkStateMethod(contract, contractId, stateId, item); + } + } + else if(typeof args == "object" && args.constructor.name != "BN") { + const keys = Object.keys(args); + + if(keys.length == 1) { + const val = (await contract[stateId].call(keys[0])).valueOf(); + + assert.equal(val, args[keys[0]], + `Contract ${contractId} state ${stateId} with arg ${keys[0]} & value ${val} is not equal to ${args[keys[0]]}`); + + return; + } + + const passArgs = []; + + if(! args.hasOwnProperty("__val")) { + assert.fail(new Error("__val is not present")); + } + + for(let arg of Object.keys(args)) { + if(arg == "__val") { + continue; + } + + passArgs.push(args[arg]); + } + + const val = (await contract[stateId].call( ...passArgs )).valueOf(); + + assert.equal(val, args["__val"], `Contract ${contractId} state ${stateId} with value ${val} is not equal to ${args['__val']}`); + } + else { + const val = (await contract[stateId].call()).valueOf(); + + assert.equal(val, args, `Contract ${contractId} state ${stateId} with value ${val} is not equal to ${args.valueOf()}`); + } +} + +async function checkState(contracts, states) { + for(let contractId in states) { + if(! contracts.hasOwnProperty(contractId)) { + assert.fail("no such contract " + contractId); + } + + let contract = contracts[contractId]; + + for(let stateId in states[contractId]) { + if(! contract.hasOwnProperty(stateId)) { + assert.fail("no such property " + stateId); + } + + await checkStateMethod(contract, contractId, stateId, states[contractId][stateId]); + } + } +} + +async function shouldFail(call) { + try { + await call; + + assert.fail("call succeed"); + } + catch(err) { + if(err.constructor.name == "AssertionError") { + throw err; + } + } +} + +module.exports = { + receiptShouldSucceed: receiptShouldSucceed, + receiptShouldFailed: receiptShouldFailed, + receiptShouldSucceedS: receiptShouldSucceedS, + receiptShouldFailedS: receiptShouldFailedS, + catchReceiptShouldFailed: catchReceiptShouldFailed, + balanceShouldEqualTo: balanceShouldEqualTo, + getDividend: getDividend, + checkDividend: checkDividend, + getPhase: getPhase, + checkPhase: checkPhase, + getEmission: getEmission, + checkEmission: checkEmission, + checkClaimedTokensAmount: checkClaimedTokensAmount, + timeout: timeout, + getEtherBalance: getEtherBalance, + checkEtherBalance: checkEtherBalance, + getTxCost: getTxCost, + timeJump: timeJump, + + sendTransaction: sendTransaction, + + checkState: checkState, + + shouldFail: shouldFail, + + // erc20 + erc20: { + transfer: transferERC20, + balanceShouldEqualTo: balanceERC20, + test: { + transferFrom: testTransferFrom + } + }, +}; \ No newline at end of file diff --git a/test/voting.test.js b/test/voting.test.js index 713691a..425c6a5 100644 --- a/test/voting.test.js +++ b/test/voting.test.js @@ -52,7 +52,8 @@ contract('Voting', async (accounts) => { blockReward.address, voting.address ) - + let ballotLimitPerValidator = (await voting.getBallotLimitPerValidator()).toNumber() + ballotLimitPerValidator.should.be.equal(Math.floor(100)) await consensus.setNewValidatorSetMock(validators) await consensus.setFinalizedMock(false, {from: owner}) await consensus.setSystemAddressMock(owner, {from: owner}) @@ -146,6 +147,7 @@ contract('Voting', async (accounts) => { it('should fail if creating ballot over the ballots limit', async () => { let maxLimitOfBallots = (await voting.MAX_LIMIT_OF_BALLOTS()).toNumber() let validatorsCount = (await consensus.currentValidatorsLength()).toNumber() + console.log({validatorsCount}); let ballotLimitPerValidator = (await voting.getBallotLimitPerValidator()).toNumber() ballotLimitPerValidator.should.be.equal(Math.floor(maxLimitOfBallots / validatorsCount)) // create ballots successfully up to the limit @@ -159,6 +161,17 @@ contract('Voting', async (accounts) => { // create a ballot with different key successfully await voting.newBallot(voteStartAfterNumberOfCycles, voteCyclesDuration, contractType, proposedValue, 'description', {from: validators[1]}).should.be.fulfilled }) + it(' getBallotLimitPerValidator should return 1 if currentValidatorsLength > MAX_LIMIT_OF_BALLOTS', async () => { + await consensus.setNewValidatorSetMock(accounts) + await consensus.setFinalizedMock(false, {from: owner}) + await consensus.setSystemAddressMock(owner, {from: owner}) + await consensus.finalizeChange().should.be.fulfilled + let maxLimitOfBallots = (await voting.MAX_LIMIT_OF_BALLOTS()).toNumber() + let validatorsCount = (await consensus.currentValidatorsLength()).toNumber() + console.log({validatorsCount}); + let ballotLimitPerValidator = (await voting.getBallotLimitPerValidator()).toNumber() + ballotLimitPerValidator.should.be.equal(1) + }) }) describe('vote', async () => { @@ -559,137 +572,138 @@ contract('Voting', async (accounts) => { }) }) - // describe('finalize', async () => { - // let currentValidators - // beforeEach(async () => { - // await voting.initialize().should.be.fulfilled - // voteStartAfterNumberOfCycles = 1 - // voteCyclesDuration = 10 - // currentValidators = await consensus.getValidators() - // }) - // it('should change to proposed value successfully if quorum is reached', async () => { - // let id = await voting.getNextBallotId() - // let proposedValue = RANDOM_ADDRESS - // let contractType = CONTRACT_TYPES.BLOCK_REWARD - // await voting.newBallot(voteStartAfterNumberOfCycles, voteCyclesDuration, contractType, proposedValue, 'description', {from: validators[0]}).should.be.fulfilled - // let currentBlock = toBN(await web3.eth.getBlockNumber()) - // let voteStartBlock = await voting.getStartBlock(id) - // let blocksToAdvance = voteStartBlock.sub(currentBlock) - // await advanceBlocks(blocksToAdvance.toNumber()) - // await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[0]}).should.be.fulfilled - // await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[1]}).should.be.fulfilled - // await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[2]}).should.be.fulfilled - // let voteEndBlock = await voting.getEndBlock(id) - // blocksToAdvance = voteEndBlock.sub(currentBlock).add(toBN(1)) - // await advanceBlocks(blocksToAdvance.toNumber()) - // await proxyStorage.setConsensusMock(owner) - // let {logs} = await voting.onCycleEnd(currentValidators).should.be.fulfilled - // logs.length.should.be.equal(1) - // logs[0].event.should.be.equal('BallotFinalized') - // logs[0].args['id'].should.be.bignumber.equal(id) - // let ballotInfo = await voting.getBallotInfo(id, validators[0]) - // ballotInfo.startBlock.should.be.bignumber.equal(voteStartBlock) - // ballotInfo.endBlock.should.be.bignumber.equal(voteEndBlock) - // ballotInfo.isFinalized.should.be.equal(true) - // ballotInfo.proposedValue.should.be.equal(proposedValue) - // ballotInfo.contractType.should.be.bignumber.equal(toBN(contractType)) - // ballotInfo.creator.should.be.equal(validators[0]) - // ballotInfo.description.should.be.equal('description') - // ballotInfo.canBeFinalizedNow.should.be.equal(false) - // ballotInfo.alreadyVoted.should.be.equal(true) - // toBN(QUORUM_STATES.ACCEPTED).should.be.bignumber.equal(await voting.getQuorumState(id)) - // proposedValue.should.be.equal(await (await EternalStorageProxy.at(await proxyStorage.getBlockReward())).getImplementation()) - // }) - // it('should not change to proposed value if quorum is not reached', async () => { - // let id = await voting.getNextBallotId() - // let proposedValue = RANDOM_ADDRESS - // let contractType = CONTRACT_TYPES.BLOCK_REWARD - // await voting.newBallot(voteStartAfterNumberOfCycles, voteCyclesDuration, contractType, proposedValue, 'description', {from: validators[0]}).should.be.fulfilled - // let currentBlock = toBN(await web3.eth.getBlockNumber()) - // let voteStartBlock = await voting.getStartBlock(id) - // let blocksToAdvance = voteStartBlock.sub(currentBlock) - // await advanceBlocks(blocksToAdvance.toNumber()) - // await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[0]}).should.be.fulfilled - // await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[1]}).should.be.fulfilled - // await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[2]}).should.be.fulfilled - // let voteEndBlock = await voting.getEndBlock(id) - // blocksToAdvance = voteEndBlock.sub(currentBlock).add(toBN(1)) - // await advanceBlocks(blocksToAdvance.toNumber()) - // await proxyStorage.setConsensusMock(owner) - // let {logs} = await voting.onCycleEnd(currentValidators).should.be.fulfilled - // logs.length.should.be.equal(1) - // logs[0].event.should.be.equal('BallotFinalized') - // logs[0].args['id'].should.be.bignumber.equal(id) - // let ballotInfo = await voting.getBallotInfo(id, validators[0]) - // ballotInfo.startBlock.should.be.bignumber.equal(voteStartBlock) - // ballotInfo.endBlock.should.be.bignumber.equal(voteEndBlock) - // ballotInfo.isFinalized.should.be.equal(true) - // ballotInfo.proposedValue.should.be.equal(proposedValue) - // ballotInfo.contractType.should.be.bignumber.equal(toBN(contractType)) - // ballotInfo.creator.should.be.equal(validators[0]) - // ballotInfo.description.should.be.equal('description') - // ballotInfo.canBeFinalizedNow.should.be.equal(false) - // ballotInfo.alreadyVoted.should.be.equal(true) - // toBN(QUORUM_STATES.REJECTED).should.be.bignumber.equal(await voting.getQuorumState(id)) - // proposedValue.should.not.be.equal(await (await EternalStorageProxy.at(await proxyStorage.getBlockReward())).getImplementation()) - // }) - // }) - - // describe('upgradeTo', async () => { - // let votingOldImplementation, votingNew - // let proxyStorageStub = accounts[13] - // beforeEach(async () => { - // voting = await Voting.new() - // votingOldImplementation = voting.address - // proxy = await EternalStorageProxy.new(proxyStorage.address, voting.address) - // voting = await Voting.at(proxy.address) - // votingNew = await Voting.new() - // }) - // it('should only be called by ProxyStorage', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(votingNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) - // let {logs} = await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - // logs[0].event.should.be.equal('Upgraded') - // await proxy.setProxyStorageMock(proxyStorage.address) - // }) - // it('should change implementation address', async () => { - // votingOldImplementation.should.be.equal(await proxy.getImplementation()) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // votingNew.address.should.be.equal(await proxy.getImplementation()) - // }) - // it('should increment implementation version', async () => { - // let votingOldVersion = await proxy.getVersion() - // let votingNewVersion = votingOldVersion.add(toBN(1)) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // votingNewVersion.should.be.bignumber.equal(await proxy.getVersion()) - // }) - // it('should work after upgrade', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - // await proxy.setProxyStorageMock(proxyStorage.address) - // votingNew = await Voting.at(proxy.address) - // false.should.be.equal(await votingNew.isInitialized()) - // await votingNew.initialize().should.be.fulfilled - // true.should.be.equal(await votingNew.isInitialized()) - // }) - // it('should use same proxyStorage after upgrade', async () => { - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - // votingNew = await Voting.at(proxy.address) - // proxyStorageStub.should.be.equal(await votingNew.getProxyStorage()) - // }) - // it('should use same storage after upgrade', async () => { - // let nextBallotId = await voting.getNextBallotId() - // let newValue = nextBallotId.toNumber() + 1 - // await voting.setNextBallotIdMock(newValue) - // await proxy.setProxyStorageMock(proxyStorageStub) - // await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) - // votingNew = await Voting.at(proxy.address) - // toBN(newValue).should.be.bignumber.equal(await votingNew.getNextBallotId()) - // }) - // }) + describe('finalize', async () => { + let currentValidators + beforeEach(async () => { + await voting.initialize().should.be.fulfilled + voteStartAfterNumberOfCycles = 1 + voteCyclesDuration = 10 + currentValidators = await consensus.getValidators() + }) + it('should change to proposed value successfully if quorum is reached', async () => { + let id = await voting.getNextBallotId() + let proposedValue = RANDOM_ADDRESS + let contractType = CONTRACT_TYPES.BLOCK_REWARD + await voting.newBallot(voteStartAfterNumberOfCycles, voteCyclesDuration, contractType, proposedValue, 'description', {from: validators[0]}).should.be.fulfilled + let currentBlock = toBN(await web3.eth.getBlockNumber()) + let voteStartBlock = await voting.getStartBlock(id) + let blocksToAdvance = voteStartBlock.sub(currentBlock) + await advanceBlocks(blocksToAdvance.toNumber()) + await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[0]}).should.be.fulfilled + await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[1]}).should.be.fulfilled + await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[2]}).should.be.fulfilled + let voteEndBlock = await voting.getEndBlock(id) + blocksToAdvance = voteEndBlock.sub(currentBlock).add(toBN(1)) + await advanceBlocks(blocksToAdvance.toNumber()) + await proxyStorage.setConsensusMock(owner) + let {logs} = await voting.onCycleEnd(currentValidators).should.be.fulfilled + logs.length.should.be.equal(1) + logs[0].event.should.be.equal('BallotFinalized') + logs[0].args['id'].should.be.bignumber.equal(id) + let ballotInfo = await voting.getBallotInfo(id, validators[0]) + ballotInfo.startBlock.should.be.bignumber.equal(voteStartBlock) + ballotInfo.endBlock.should.be.bignumber.equal(voteEndBlock) + ballotInfo.isFinalized.should.be.equal(true) + ballotInfo.proposedValue.should.be.equal(proposedValue) + ballotInfo.contractType.should.be.bignumber.equal(toBN(contractType)) + ballotInfo.creator.should.be.equal(validators[0]) + ballotInfo.description.should.be.equal('description') + ballotInfo.canBeFinalizedNow.should.be.equal(false) + ballotInfo.alreadyVoted.should.be.equal(true) + toBN(QUORUM_STATES.ACCEPTED).should.be.bignumber.equal(await voting.getQuorumState(id)) + proposedValue.should.be.equal(await (await EternalStorageProxy.at(await proxyStorage.getBlockReward())).getImplementation()) + }) + it('should not change to proposed value if quorum is not reached', async () => { + let id = await voting.getNextBallotId() + let proposedValue = RANDOM_ADDRESS + let contractType = CONTRACT_TYPES.BLOCK_REWARD + await voting.newBallot(voteStartAfterNumberOfCycles, voteCyclesDuration, contractType, proposedValue, 'description', {from: validators[0]}).should.be.fulfilled + let currentBlock = toBN(await web3.eth.getBlockNumber()) + let voteStartBlock = await voting.getStartBlock(id) + let blocksToAdvance = voteStartBlock.sub(currentBlock) + await advanceBlocks(blocksToAdvance.toNumber()) + await voting.vote(id, ACTION_CHOICES.ACCEPT, {from: validators[0]}).should.be.fulfilled + await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[1]}).should.be.fulfilled + await voting.vote(id, ACTION_CHOICES.REJECT, {from: validators[2]}).should.be.fulfilled + let voteEndBlock = await voting.getEndBlock(id) + blocksToAdvance = voteEndBlock.sub(currentBlock).add(toBN(1)) + await advanceBlocks(blocksToAdvance.toNumber()) + await proxyStorage.setConsensusMock(owner) + let {logs} = await voting.onCycleEnd(currentValidators).should.be.fulfilled + logs.length.should.be.equal(1) + logs[0].event.should.be.equal('BallotFinalized') + logs[0].args['id'].should.be.bignumber.equal(id) + let ballotInfo = await voting.getBallotInfo(id, validators[0]) + ballotInfo.startBlock.should.be.bignumber.equal(voteStartBlock) + ballotInfo.endBlock.should.be.bignumber.equal(voteEndBlock) + ballotInfo.isFinalized.should.be.equal(true) + ballotInfo.proposedValue.should.be.equal(proposedValue) + ballotInfo.contractType.should.be.bignumber.equal(toBN(contractType)) + ballotInfo.creator.should.be.equal(validators[0]) + ballotInfo.description.should.be.equal('description') + ballotInfo.canBeFinalizedNow.should.be.equal(false) + ballotInfo.alreadyVoted.should.be.equal(true) + toBN(QUORUM_STATES.REJECTED).should.be.bignumber.equal(await voting.getQuorumState(id)) + proposedValue.should.not.be.equal(await (await EternalStorageProxy.at(await proxyStorage.getBlockReward())).getImplementation()) + }) + }) + + describe('upgradeTo', async () => { + let votingOldImplementation, votingNew + let proxyStorageStub = accounts[13] + beforeEach(async () => { + voting = await Voting.new() + votingOldImplementation = voting.address + proxy = await EternalStorageProxy.new(proxyStorage.address, voting.address) + voting = await Voting.at(proxy.address) + votingNew = await Voting.new() + }) + it('should only be called by ProxyStorage', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(votingNew.address, {from: owner}).should.be.rejectedWith(ERROR_MSG) + let {logs} = await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + logs[0].event.should.be.equal('Upgraded') + await proxy.setProxyStorageMock(proxyStorage.address) + }) + it('should change implementation address', async () => { + votingOldImplementation.should.be.equal(await proxy.getImplementation()) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + votingNew.address.should.be.equal(await proxy.getImplementation()) + }) + it('should increment implementation version', async () => { + let votingOldVersion = await proxy.getVersion() + let votingNewVersion = votingOldVersion.add(toBN(1)) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + votingNewVersion.should.be.bignumber.equal(await proxy.getVersion()) + }) + it('should work after upgrade', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + await proxy.setProxyStorageMock(proxyStorage.address) + votingNew = await Voting.at(proxy.address) + false.should.be.equal(await votingNew.isInitialized()) + await votingNew.initialize().should.be.fulfilled + true.should.be.equal(await votingNew.isInitialized()) + }) + it('should use same proxyStorage after upgrade', async () => { + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + votingNew = await Voting.at(proxy.address) + proxyStorageStub.should.be.equal(await votingNew.getProxyStorage()) + }) + it('should use same storage after upgrade', async () => { + let nextBallotId = await voting.getNextBallotId() + let newValue = nextBallotId.toNumber() + 1 + await voting.setNextBallotIdMock(newValue) + await proxy.setProxyStorageMock(proxyStorageStub) + await proxy.upgradeTo(votingNew.address, {from: proxyStorageStub}) + votingNew = await Voting.at(proxy.address) + toBN(newValue).should.be.bignumber.equal(await votingNew.getNextBallotId()) + }) + }) + }) diff --git a/truffle-config.js b/truffle-config.js index 7f35e9e..b753ccf 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -36,6 +36,7 @@ module.exports = { network_id: '*', gas: 10000000 }, + fuse: { provider: walletProvider, network_id: 122, @@ -58,6 +59,7 @@ module.exports = { } } }, + plugins: ["solidity-coverage"], mocha: { reporter: 'eth-gas-reporter', reporterOptions: {