From 4e5c5e45fcc1ecdd25d02d6e1e6765119840de94 Mon Sep 17 00:00:00 2001 From: Max Alekseenko Date: Mon, 17 Jun 2019 15:59:09 +0300 Subject: [PATCH 1/9] move ballot duration check from VotingToChange to VotingTo --- contracts/VotingToManageEmissionFunds.sol | 12 ++++++++-- contracts/abstracts/VotingTo.sol | 27 ++++++++++++++++++++++- contracts/abstracts/VotingToChange.sol | 24 +------------------- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/contracts/VotingToManageEmissionFunds.sol b/contracts/VotingToManageEmissionFunds.sol index 31a8625..af584fc 100644 --- a/contracts/VotingToManageEmissionFunds.sol +++ b/contracts/VotingToManageEmissionFunds.sol @@ -44,14 +44,20 @@ contract VotingToManageEmissionFunds is VotingTo { // solhint-disable code-complexity function canBeFinalizedNow(uint256 _id) public view returns(bool) { + uint256 currentTime = getTime(); + uint256 startTime = _getStartTime(_id); + uint256 diffTime = currentTime.sub(startTime); + if (_id >= nextBallotId()) return false; if (_id != nextBallotId().sub(1)) return false; - if (_getStartTime(_id) > getTime()) return false; + if (startTime > currentTime) return false; if (isActive(_id)) return false; if (_getIsCanceled(_id)) return false; if (_getIsFinalized(_id)) return false; if (noActiveBallotExists()) return false; if (_withinCancelingThreshold(_id)) return false; + if (diffTime < minBallotDuration()) return false; + return true; } // solhint-enable code-complexity @@ -159,7 +165,8 @@ contract VotingToManageEmissionFunds is VotingTo { uint256 _emissionReleaseTime, // unix timestamp uint256 _emissionReleaseThreshold, // seconds uint256 _distributionThreshold, // seconds - address _emissionFunds + address _emissionFunds, + uint256 _minBallotDuration ) public onlyOwner { require(!initDisabled()); require(_emissionReleaseTime > getTime()); @@ -167,6 +174,7 @@ contract VotingToManageEmissionFunds is VotingTo { require(_distributionThreshold > ballotCancelingThreshold()); require(_emissionReleaseThreshold > _distributionThreshold); require(_emissionFunds != address(0)); + _init(_minBallotDuration); _setNoActiveBallotExists(true); _setEmissionReleaseTime(_emissionReleaseTime); addressStorage[EMISSION_FUNDS] = _emissionFunds; diff --git a/contracts/abstracts/VotingTo.sol b/contracts/abstracts/VotingTo.sol index 58c8b8c..3692845 100644 --- a/contracts/abstracts/VotingTo.sol +++ b/contracts/abstracts/VotingTo.sol @@ -26,6 +26,7 @@ contract VotingTo is EternalStorage, EnumBallotTypes, EnumThresholdTypes { bytes32 internal constant START_TIME = "startTime"; bytes32 internal constant VOTERS = "voters"; bytes32 internal constant VOTING_STATE = "votingState"; + bytes32 internal constant MIN_BALLOT_DURATION = keccak256("minBallotDuration"); event BallotCreated( uint256 indexed id, @@ -56,6 +57,15 @@ contract VotingTo is EternalStorage, EnumBallotTypes, EnumThresholdTypes { _; } + modifier onlyValidTime(uint256 _startTime, uint256 _endTime) { + require(_startTime > 0 && _endTime > 0); + require(_endTime > _startTime && _startTime > getTime()); + uint256 diffTime = _endTime.sub(_startTime); + require(diffTime > minBallotDuration()); + require(diffTime <= maxBallotDuration()); + _; + } + function areOldMiningKeysVoted(uint256 _id, address _miningKey) public view @@ -131,6 +141,21 @@ contract VotingTo is EternalStorage, EnumBallotTypes, EnumThresholdTypes { return addressStorage[PROXY_STORAGE]; } + function maxBallotDuration() public pure returns(uint256) { + return 14 days; + } + + function minBallotDuration() public view returns(uint256) { + return uintStorage[MIN_BALLOT_DURATION]; + } + + function _init(uint256 _minBallotDuration) internal onlyOwner { + require(!initDisabled()); + require(_minBallotDuration < maxBallotDuration()); + uintStorage[MIN_BALLOT_DURATION] = _minBallotDuration; + boolStorage[INIT_DISABLED] = true; + } + function _createBallot( uint256 _ballotType, uint256 _startTime, @@ -138,7 +163,7 @@ contract VotingTo is EternalStorage, EnumBallotTypes, EnumThresholdTypes { string _memo, uint256 _quorumState, address _creatorMiningKey - ) internal returns(uint256) { + ) internal onlyValidTime(_startTime, _endTime) returns(uint256) { require(initDisabled()); uint256 ballotId = nextBallotId(); _setNextBallotId(ballotId.add(1)); diff --git a/contracts/abstracts/VotingToChange.sol b/contracts/abstracts/VotingToChange.sol index e83a0ed..0299b65 100644 --- a/contracts/abstracts/VotingToChange.sol +++ b/contracts/abstracts/VotingToChange.sol @@ -8,7 +8,6 @@ import "./VotingTo.sol"; contract VotingToChange is VotingTo { bytes32 internal constant ACTIVE_BALLOTS = keccak256("activeBallots"); bytes32 internal constant MIGRATE_DISABLED = keccak256("migrateDisabled"); - bytes32 internal constant MIN_BALLOT_DURATION = keccak256("minBallotDuration"); bytes32 internal constant INDEX = "index"; bytes32 internal constant FINALIZE_CALLED = "finalizeCalled"; @@ -19,15 +18,6 @@ contract VotingToChange is VotingTo { enum QuorumStates {Invalid, InProgress, Accepted, Rejected} enum ActionChoice {Invalid, Accept, Reject} - modifier onlyValidTime(uint256 _startTime, uint256 _endTime) { - require(_startTime > 0 && _endTime > 0); - require(_endTime > _startTime && _startTime > getTime()); - uint256 diffTime = _endTime.sub(_startTime); - require(diffTime > minBallotDuration()); - require(diffTime <= maxBallotDuration()); - _; - } - function activeBallots(uint256 _index) public view returns(uint256) { return uintArrayStorage[ACTIVE_BALLOTS][_index]; } @@ -49,10 +39,6 @@ contract VotingToChange is VotingTo { return uintStorage[keccak256(abi.encode(VOTING_STATE, _id, INDEX))]; } - function maxBallotDuration() public pure returns(uint256) { - return 14 days; - } - function migrateBasicAll(address _prevVotingToChange) public onlyOwner { require(_prevVotingToChange != address(0)); require(initDisabled()); @@ -92,10 +78,6 @@ contract VotingToChange is VotingTo { return boolStorage[MIGRATE_DISABLED]; } - function minBallotDuration() public view returns(uint256) { - return uintStorage[MIN_BALLOT_DURATION]; - } - function validatorActiveBallots(address _miningKey) public view returns(uint256) { return uintStorage[ keccak256(abi.encode(VALIDATOR_ACTIVE_BALLOTS, _miningKey)) @@ -171,7 +153,6 @@ contract VotingToChange is VotingTo { ) internal onlyValidVotingKey(msg.sender) - onlyValidTime(_startTime, _endTime) returns(uint256) { require(migrateDisabled()); @@ -259,11 +240,8 @@ contract VotingToChange is VotingTo { } function _init(uint256 _minBallotDuration) internal onlyOwner { - require(!initDisabled()); require(!migrateDisabled()); - require(_minBallotDuration < maxBallotDuration()); - uintStorage[MIN_BALLOT_DURATION] = _minBallotDuration; - boolStorage[INIT_DISABLED] = true; + super._init(_minBallotDuration); } function _setIndex(uint256 _ballotId, uint256 _value) internal { From d19df44baf408e8eedbd74bd6324606f19e43280 Mon Sep 17 00:00:00 2001 From: Max Alekseenko Date: Mon, 17 Jun 2019 16:19:28 +0300 Subject: [PATCH 2/9] fix existing tests --- test/voting_to_manage_emission_funds_test.js | 29 ++++++++++++------- ...g_to_manage_emission_funds_upgrade_test.js | 28 +++++++++++------- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/test/voting_to_manage_emission_funds_test.js b/test/voting_to_manage_emission_funds_test.js index cc70362..df13290 100644 --- a/test/voting_to_manage_emission_funds_test.js +++ b/test/voting_to_manage_emission_funds_test.js @@ -27,6 +27,8 @@ const choice = { freeze: 3 } +const minBallotDuration = 600 // 10 minutes + let coinbase; let poaNetworkConsensus, masterOfCeremony, proxyStorage, keysManager; let ballotsStorage, votingForKeysEternalStorage, voting, votingEternalStorage, emissionFunds; @@ -98,19 +100,22 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { emissionReleaseThreshold, distributionThreshold, emissionFunds.address, + minBallotDuration, {from: accounts[8]} ).should.be.rejectedWith(ERROR_MSG); await voting.init( emissionReleaseTime, emissionReleaseThreshold, 300, - emissionFunds.address + emissionFunds.address, + minBallotDuration ).should.be.rejectedWith(ERROR_MSG); await voting.init( emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address + emissionFunds.address, + minBallotDuration ).should.be.fulfilled; rewardByBlock = await RewardByBlock.new(); @@ -160,7 +165,8 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address + emissionFunds.address, + minBallotDuration ).should.be.rejectedWith(ERROR_MSG); }); }); @@ -267,7 +273,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { emissionReleaseTime + emissionReleaseThreshold + 1 ); VOTING_START_DATE = emissionReleaseTime + emissionReleaseThreshold + 2; - VOTING_END_DATE = VOTING_START_DATE + 100; + VOTING_END_DATE = VOTING_START_DATE + minBallotDuration + 1; await voting.createBallot( VOTING_START_DATE, VOTING_END_DATE, accounts[5], "memo", {from: votingKey} ).should.be.fulfilled; @@ -923,8 +929,8 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { }); it('does not finalize immediately until ballot canceling threshold is reached', async () => { - VOTING_START_DATE = moment.utc().add(17, 'minutes').unix(); - VOTING_END_DATE = moment.utc().add(20, 'minutes').unix(); + VOTING_START_DATE = moment.utc().add(17 * 60, 'seconds').unix(); + VOTING_END_DATE = moment.utc().add(17 * 60 + minBallotDuration + 1, 'seconds').unix(); await voting.createBallot( VOTING_START_DATE, VOTING_END_DATE, receiver, "memo", {from: votingKey} ).should.be.fulfilled; @@ -939,7 +945,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { false.should.be.equal((await voting.getBallotInfo.call(id))[4]); // isFinalized - await voting.setTime(moment.utc().add(31, 'minutes').unix()); + await voting.setTime(moment.utc().add(31 * 60 + minBallotDuration + 1, 'seconds').unix()); await voting.finalize(id, {from: votingKey3}).should.be.fulfilled; true.should.be.equal((await voting.getBallotInfo.call(id))[4]); // isFinalized @@ -995,8 +1001,8 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { }); it('deny finalization within ballot canceling threshold', async () => { - VOTING_START_DATE = moment.utc().add(17, 'minutes').unix(); - VOTING_END_DATE = moment.utc().add(20, 'minutes').unix(); + VOTING_START_DATE = moment.utc().add(17 * 60, 'seconds').unix(); + VOTING_END_DATE = moment.utc().add(17 * 60 + minBallotDuration + 1, 'seconds').unix(); await voting.createBallot( VOTING_START_DATE, VOTING_END_DATE, receiver, "memo", {from: votingKey} @@ -1005,7 +1011,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { await voting.setTime(VOTING_END_DATE + 1); await voting.finalize(id, {from: votingKey}).should.be.rejectedWith(ERROR_MSG); - await voting.setTime(moment.utc().add(31, 'minutes').unix()); + await voting.setTime(moment.utc().add(31 * 60 + minBallotDuration + 1, 'seconds').unix()); await voting.finalize(id, {from: votingKey}).should.be.fulfilled; }); @@ -1038,7 +1044,8 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address + emissionFunds.address, + minBallotDuration ).should.be.fulfilled; }); it('may only be called by ProxyStorage', async () => { diff --git a/test/voting_to_manage_emission_funds_upgrade_test.js b/test/voting_to_manage_emission_funds_upgrade_test.js index 83bd678..63a53ad 100644 --- a/test/voting_to_manage_emission_funds_upgrade_test.js +++ b/test/voting_to_manage_emission_funds_upgrade_test.js @@ -27,6 +27,8 @@ const choice = { freeze: 3 } +const minBallotDuration = 600 // 10 minutes + let coinbase; let poaNetworkConsensus, masterOfCeremony, proxyStorage, keysManager; let ballotsStorage, votingForKeysEternalStorage, voting, votingEternalStorage, emissionFunds; @@ -98,19 +100,22 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun emissionReleaseThreshold, distributionThreshold, emissionFunds.address, + minBallotDuration, {from: accounts[8]} ).should.be.rejectedWith(ERROR_MSG); await voting.init( emissionReleaseTime, emissionReleaseThreshold, 300, - emissionFunds.address + emissionFunds.address, + minBallotDuration ).should.be.rejectedWith(ERROR_MSG); await voting.init( emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address + emissionFunds.address, + minBallotDuration ).should.be.fulfilled; rewardByBlock = await RewardByBlock.new(); @@ -167,7 +172,8 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address + emissionFunds.address, + minBallotDuration ).should.be.rejectedWith(ERROR_MSG); }); }); @@ -274,7 +280,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun emissionReleaseTime + emissionReleaseThreshold + 1 ); VOTING_START_DATE = emissionReleaseTime + emissionReleaseThreshold + 2; - VOTING_END_DATE = VOTING_START_DATE + 100; + VOTING_END_DATE = VOTING_START_DATE + minBallotDuration + 1; await voting.createBallot( VOTING_START_DATE, VOTING_END_DATE, accounts[5], "memo", {from: votingKey} ).should.be.fulfilled; @@ -930,8 +936,8 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun }); it('does not finalize immediately until ballot canceling threshold is reached', async () => { - VOTING_START_DATE = moment.utc().add(17, 'minutes').unix(); - VOTING_END_DATE = moment.utc().add(20, 'minutes').unix(); + VOTING_START_DATE = moment.utc().add(17 * 60, 'seconds').unix(); + VOTING_END_DATE = moment.utc().add(17 * 60 + minBallotDuration + 1, 'seconds').unix(); await voting.createBallot( VOTING_START_DATE, VOTING_END_DATE, receiver, "memo", {from: votingKey} ).should.be.fulfilled; @@ -946,7 +952,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun false.should.be.equal((await voting.getBallotInfo.call(id))[4]); // isFinalized - await voting.setTime(moment.utc().add(31, 'minutes').unix()); + await voting.setTime(moment.utc().add(31 * 60 + minBallotDuration + 1, 'seconds').unix()); await voting.finalize(id, {from: votingKey3}).should.be.fulfilled; true.should.be.equal((await voting.getBallotInfo.call(id))[4]); // isFinalized @@ -1002,8 +1008,8 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun }); it('deny finalization within ballot canceling threshold', async () => { - VOTING_START_DATE = moment.utc().add(17, 'minutes').unix(); - VOTING_END_DATE = moment.utc().add(20, 'minutes').unix(); + VOTING_START_DATE = moment.utc().add(17 * 60, 'seconds').unix(); + VOTING_END_DATE = moment.utc().add(17 * 60 + minBallotDuration + 1, 'seconds').unix(); await voting.createBallot( VOTING_START_DATE, VOTING_END_DATE, receiver, "memo", {from: votingKey} @@ -1012,7 +1018,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun await voting.setTime(VOTING_END_DATE + 1); await voting.finalize(id, {from: votingKey}).should.be.rejectedWith(ERROR_MSG); - await voting.setTime(moment.utc().add(31, 'minutes').unix()); + await voting.setTime(moment.utc().add(31 * 60 + minBallotDuration + 1, 'seconds').unix()); await voting.finalize(id, {from: votingKey}).should.be.fulfilled; }); @@ -1048,4 +1054,4 @@ async function addValidator(_votingKey, _miningKey) { async function swapVotingKey(_key, _miningKey) { const {logs} = await keysManager.swapVotingKey(_key, _miningKey); logs[0].event.should.be.equal("VotingKeyChanged"); -} \ No newline at end of file +} From 62d2203c8f995082613290c9e7c6b25d76a76d74 Mon Sep 17 00:00:00 2001 From: Max Alekseenko Date: Mon, 17 Jun 2019 16:39:41 +0300 Subject: [PATCH 3/9] add a test for min ballot duration --- test/voting_to_manage_emission_funds_test.js | 7 +++++++ test/voting_to_manage_emission_funds_upgrade_test.js | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/test/voting_to_manage_emission_funds_test.js b/test/voting_to_manage_emission_funds_test.js index df13290..68ac382 100644 --- a/test/voting_to_manage_emission_funds_test.js +++ b/test/voting_to_manage_emission_funds_test.js @@ -247,6 +247,13 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { VOTING_START_DATE, VOTING_END_DATE, accounts[5], "memo", {from: votingKey} ).should.be.rejectedWith(ERROR_MSG); }); + it('ballot duration must be greater than min ballot duration', async () => { + VOTING_START_DATE = moment.utc().add(31 * 60, 'seconds').unix(); + VOTING_END_DATE = moment.utc().add(31 * 60 + minBallotDuration - 1, 'seconds').unix(); + await voting.createBallot( + VOTING_START_DATE, VOTING_END_DATE, accounts[5], "memo", {from: votingKey} + ).should.be.rejectedWith(ERROR_MSG); + }); it('receiver address should not be 0x0', async () => { await voting.createBallot( VOTING_START_DATE, VOTING_END_DATE, '0x0000000000000000000000000000000000000000', "memo", {from: votingKey} diff --git a/test/voting_to_manage_emission_funds_upgrade_test.js b/test/voting_to_manage_emission_funds_upgrade_test.js index 63a53ad..4e07cf4 100644 --- a/test/voting_to_manage_emission_funds_upgrade_test.js +++ b/test/voting_to_manage_emission_funds_upgrade_test.js @@ -254,6 +254,13 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun VOTING_START_DATE, VOTING_END_DATE, accounts[5], "memo", {from: votingKey} ).should.be.rejectedWith(ERROR_MSG); }); + it('ballot duration must be greater than min ballot duration', async () => { + VOTING_START_DATE = moment.utc().add(31 * 60, 'seconds').unix(); + VOTING_END_DATE = moment.utc().add(31 * 60 + minBallotDuration - 1, 'seconds').unix(); + await voting.createBallot( + VOTING_START_DATE, VOTING_END_DATE, accounts[5], "memo", {from: votingKey} + ).should.be.rejectedWith(ERROR_MSG); + }); it('receiver address should not be 0x0', async () => { await voting.createBallot( VOTING_START_DATE, VOTING_END_DATE, '0x0000000000000000000000000000000000000000', "memo", {from: votingKey} From a70ddb1b912838d8203138a7d9d83ed844ff012b Mon Sep 17 00:00:00 2001 From: Max Alekseenko Date: Tue, 18 Jun 2019 13:46:57 +0300 Subject: [PATCH 4/9] make requested changes --- contracts/VotingToManageEmissionFunds.sol | 6 +----- contracts/abstracts/VotingTo.sol | 2 +- migrations/2_deploy_contract.js | 3 ++- test/voting_to_manage_emission_funds_test.js | 4 ++++ test/voting_to_manage_emission_funds_upgrade_test.js | 4 ++++ 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/contracts/VotingToManageEmissionFunds.sol b/contracts/VotingToManageEmissionFunds.sol index af584fc..ad05cc4 100644 --- a/contracts/VotingToManageEmissionFunds.sol +++ b/contracts/VotingToManageEmissionFunds.sol @@ -56,7 +56,7 @@ contract VotingToManageEmissionFunds is VotingTo { if (_getIsFinalized(_id)) return false; if (noActiveBallotExists()) return false; if (_withinCancelingThreshold(_id)) return false; - if (diffTime < minBallotDuration()) return false; + if (diffTime <= minBallotDuration()) return false; return true; } @@ -80,9 +80,7 @@ contract VotingToManageEmissionFunds is VotingTo { address _receiver, string _memo ) public onlyValidVotingKey(msg.sender) { - require(_startTime > 0 && _endTime > 0); uint256 currentTime = getTime(); - require(_endTime > _startTime && _startTime > currentTime); uint256 releaseTimeSnapshot = emissionReleaseTime(); uint256 releaseTime = refreshEmissionReleaseTime(); require(currentTime >= releaseTime); @@ -168,7 +166,6 @@ contract VotingToManageEmissionFunds is VotingTo { address _emissionFunds, uint256 _minBallotDuration ) public onlyOwner { - require(!initDisabled()); require(_emissionReleaseTime > getTime()); require(_emissionReleaseThreshold > 0); require(_distributionThreshold > ballotCancelingThreshold()); @@ -180,7 +177,6 @@ contract VotingToManageEmissionFunds is VotingTo { addressStorage[EMISSION_FUNDS] = _emissionFunds; uintStorage[EMISSION_RELEASE_THRESHOLD] = _emissionReleaseThreshold; uintStorage[DISTRIBUTION_THRESHOLD] = _distributionThreshold; - boolStorage[INIT_DISABLED] = true; } function noActiveBallotExists() public view returns(bool) { diff --git a/contracts/abstracts/VotingTo.sol b/contracts/abstracts/VotingTo.sol index 3692845..2b87766 100644 --- a/contracts/abstracts/VotingTo.sol +++ b/contracts/abstracts/VotingTo.sol @@ -14,6 +14,7 @@ contract VotingTo is EternalStorage, EnumBallotTypes, EnumThresholdTypes { bytes32 internal constant OWNER = keccak256("owner"); bytes32 internal constant INIT_DISABLED = keccak256("initDisabled"); + bytes32 internal constant MIN_BALLOT_DURATION = keccak256("minBallotDuration"); bytes32 internal constant NEXT_BALLOT_ID = keccak256("nextBallotId"); bytes32 internal constant PROXY_STORAGE = keccak256("proxyStorage"); @@ -26,7 +27,6 @@ contract VotingTo is EternalStorage, EnumBallotTypes, EnumThresholdTypes { bytes32 internal constant START_TIME = "startTime"; bytes32 internal constant VOTERS = "voters"; bytes32 internal constant VOTING_STATE = "votingState"; - bytes32 internal constant MIN_BALLOT_DURATION = keccak256("minBallotDuration"); event BallotCreated( uint256 indexed id, diff --git a/migrations/2_deploy_contract.js b/migrations/2_deploy_contract.js index 028017f..cdef365 100644 --- a/migrations/2_deploy_contract.js +++ b/migrations/2_deploy_contract.js @@ -180,7 +180,8 @@ module.exports = function(deployer, network, accounts) { demoMode ? moment.utc().add(10, 'minutes').unix() : moment.utc().add(3, 'months').unix(), demoMode ? 3600 : 7776000, // emissionReleaseThreshold: 1 hour for demo, 3 months for production demoMode ? 1500 : 604800, // distributionThreshold: 25 minutes for demo, 7 days for production - emissionFunds.address + emissionFunds.address, + minBallotDuration ); // Initialize ProxyStorage diff --git a/test/voting_to_manage_emission_funds_test.js b/test/voting_to_manage_emission_funds_test.js index 68ac382..84cedaf 100644 --- a/test/voting_to_manage_emission_funds_test.js +++ b/test/voting_to_manage_emission_funds_test.js @@ -253,6 +253,10 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { await voting.createBallot( VOTING_START_DATE, VOTING_END_DATE, accounts[5], "memo", {from: votingKey} ).should.be.rejectedWith(ERROR_MSG); + VOTING_END_DATE = moment.utc().add(31 * 60 + minBallotDuration + 1, 'seconds').unix(); + await voting.createBallot( + VOTING_START_DATE, VOTING_END_DATE, accounts[5], "memo", {from: votingKey} + ).should.be.fulfilled; }); it('receiver address should not be 0x0', async () => { await voting.createBallot( diff --git a/test/voting_to_manage_emission_funds_upgrade_test.js b/test/voting_to_manage_emission_funds_upgrade_test.js index 4e07cf4..0f2b27e 100644 --- a/test/voting_to_manage_emission_funds_upgrade_test.js +++ b/test/voting_to_manage_emission_funds_upgrade_test.js @@ -260,6 +260,10 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun await voting.createBallot( VOTING_START_DATE, VOTING_END_DATE, accounts[5], "memo", {from: votingKey} ).should.be.rejectedWith(ERROR_MSG); + VOTING_END_DATE = moment.utc().add(31 * 60 + minBallotDuration + 1, 'seconds').unix(); + await voting.createBallot( + VOTING_START_DATE, VOTING_END_DATE, accounts[5], "memo", {from: votingKey} + ).should.be.fulfilled; }); it('receiver address should not be 0x0', async () => { await voting.createBallot( From f7a374573200e5b002338036cc17f4fb2ec85d14 Mon Sep 17 00:00:00 2001 From: Max Alekseenko Date: Tue, 18 Jun 2019 15:10:39 +0300 Subject: [PATCH 5/9] swap function params --- contracts/VotingToManageEmissionFunds.sol | 5 +++-- migrations/2_deploy_contract.js | 4 ++-- test/voting_to_manage_emission_funds_test.js | 18 +++++++++--------- ...ng_to_manage_emission_funds_upgrade_test.js | 14 +++++++------- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/contracts/VotingToManageEmissionFunds.sol b/contracts/VotingToManageEmissionFunds.sol index ad05cc4..88cf94d 100644 --- a/contracts/VotingToManageEmissionFunds.sol +++ b/contracts/VotingToManageEmissionFunds.sol @@ -163,13 +163,14 @@ contract VotingToManageEmissionFunds is VotingTo { uint256 _emissionReleaseTime, // unix timestamp uint256 _emissionReleaseThreshold, // seconds uint256 _distributionThreshold, // seconds - address _emissionFunds, - uint256 _minBallotDuration + uint256 _minBallotDuration, // seconds + address _emissionFunds ) public onlyOwner { require(_emissionReleaseTime > getTime()); require(_emissionReleaseThreshold > 0); require(_distributionThreshold > ballotCancelingThreshold()); require(_emissionReleaseThreshold > _distributionThreshold); + require(_minBallotDuration < _distributionThreshold); require(_emissionFunds != address(0)); _init(_minBallotDuration); _setNoActiveBallotExists(true); diff --git a/migrations/2_deploy_contract.js b/migrations/2_deploy_contract.js index cdef365..79d73e8 100644 --- a/migrations/2_deploy_contract.js +++ b/migrations/2_deploy_contract.js @@ -180,8 +180,8 @@ module.exports = function(deployer, network, accounts) { demoMode ? moment.utc().add(10, 'minutes').unix() : moment.utc().add(3, 'months').unix(), demoMode ? 3600 : 7776000, // emissionReleaseThreshold: 1 hour for demo, 3 months for production demoMode ? 1500 : 604800, // distributionThreshold: 25 minutes for demo, 7 days for production - emissionFunds.address, - minBallotDuration + minBallotDuration, + emissionFunds.address ); // Initialize ProxyStorage diff --git a/test/voting_to_manage_emission_funds_test.js b/test/voting_to_manage_emission_funds_test.js index 84cedaf..42bed88 100644 --- a/test/voting_to_manage_emission_funds_test.js +++ b/test/voting_to_manage_emission_funds_test.js @@ -99,23 +99,23 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address, minBallotDuration, + emissionFunds.address, {from: accounts[8]} ).should.be.rejectedWith(ERROR_MSG); await voting.init( emissionReleaseTime, emissionReleaseThreshold, 300, - emissionFunds.address, - minBallotDuration + minBallotDuration, + emissionFunds.address ).should.be.rejectedWith(ERROR_MSG); await voting.init( emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address, - minBallotDuration + minBallotDuration, + emissionFunds.address ).should.be.fulfilled; rewardByBlock = await RewardByBlock.new(); @@ -165,8 +165,8 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address, - minBallotDuration + minBallotDuration, + emissionFunds.address ).should.be.rejectedWith(ERROR_MSG); }); }); @@ -1055,8 +1055,8 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address, - minBallotDuration + minBallotDuration, + emissionFunds.address ).should.be.fulfilled; }); it('may only be called by ProxyStorage', async () => { diff --git a/test/voting_to_manage_emission_funds_upgrade_test.js b/test/voting_to_manage_emission_funds_upgrade_test.js index 0f2b27e..d89a43b 100644 --- a/test/voting_to_manage_emission_funds_upgrade_test.js +++ b/test/voting_to_manage_emission_funds_upgrade_test.js @@ -99,23 +99,23 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address, minBallotDuration, + emissionFunds.address, {from: accounts[8]} ).should.be.rejectedWith(ERROR_MSG); await voting.init( emissionReleaseTime, emissionReleaseThreshold, 300, - emissionFunds.address, - minBallotDuration + minBallotDuration, + emissionFunds.address ).should.be.rejectedWith(ERROR_MSG); await voting.init( emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address, - minBallotDuration + minBallotDuration, + emissionFunds.address ).should.be.fulfilled; rewardByBlock = await RewardByBlock.new(); @@ -172,8 +172,8 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun emissionReleaseTime, emissionReleaseThreshold, distributionThreshold, - emissionFunds.address, - minBallotDuration + minBallotDuration, + emissionFunds.address ).should.be.rejectedWith(ERROR_MSG); }); }); From 5553cfef10e611e127279dd7712cf35a2374079f Mon Sep 17 00:00:00 2001 From: Max Alekseenko Date: Thu, 20 Jun 2019 16:16:03 +0300 Subject: [PATCH 6/9] remove redundant check --- contracts/VotingToManageEmissionFunds.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/VotingToManageEmissionFunds.sol b/contracts/VotingToManageEmissionFunds.sol index 88cf94d..deb845f 100644 --- a/contracts/VotingToManageEmissionFunds.sol +++ b/contracts/VotingToManageEmissionFunds.sol @@ -167,7 +167,6 @@ contract VotingToManageEmissionFunds is VotingTo { address _emissionFunds ) public onlyOwner { require(_emissionReleaseTime > getTime()); - require(_emissionReleaseThreshold > 0); require(_distributionThreshold > ballotCancelingThreshold()); require(_emissionReleaseThreshold > _distributionThreshold); require(_minBallotDuration < _distributionThreshold); From a6e8c17fa203d6aaf3b0e30882fe6c81431a386d Mon Sep 17 00:00:00 2001 From: Max Alekseenko Date: Thu, 20 Jun 2019 16:37:50 +0300 Subject: [PATCH 7/9] add a check for "vote" method --- contracts/VotingToManageEmissionFunds.sol | 6 +++++- test/voting_to_manage_emission_funds_test.js | 21 ++++++++++--------- ...g_to_manage_emission_funds_upgrade_test.js | 21 ++++++++++--------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/contracts/VotingToManageEmissionFunds.sol b/contracts/VotingToManageEmissionFunds.sol index deb845f..537d8df 100644 --- a/contracts/VotingToManageEmissionFunds.sol +++ b/contracts/VotingToManageEmissionFunds.sol @@ -219,7 +219,11 @@ contract VotingToManageEmissionFunds is VotingTo { IProxyStorage(proxyStorage()).getPoaConsensus() ).getCurrentValidatorsLengthWithoutMoC(); - if (getTotalVoters(_id) >= validatorsLength && !_withinCancelingThreshold(_id)) { + if ( + getTotalVoters(_id) >= validatorsLength && + !_withinCancelingThreshold(_id) && + getTime().sub(_getStartTime(_id)) > minBallotDuration() + ) { _finalize(_id); } } diff --git a/test/voting_to_manage_emission_funds_test.js b/test/voting_to_manage_emission_funds_test.js index 42bed88..aa49eb3 100644 --- a/test/voting_to_manage_emission_funds_test.js +++ b/test/voting_to_manage_emission_funds_test.js @@ -545,7 +545,8 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { const emissionFundsBalanceOld = await web3.eth.getBalance(emissionFunds.address); const receiverBalanceOld = await web3.eth.getBalance(receiver); - await voting.setTime(VOTING_START_DATE); + const time = VOTING_START_DATE + minBallotDuration + 1; + await voting.setTime(time); const {logs} = await voting.vote(id, choice.freeze, {from: votingKey}).should.be.fulfilled; const ballotInfo = await voting.getBallotInfo.call(id); @@ -563,7 +564,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { logs[0].args.id.should.be.bignumber.equal(0); logs[0].args.decision.should.be.bignumber.equal(choice.freeze); logs[0].args.voter.should.be.equal(votingKey); - logs[0].args.time.should.be.bignumber.equal(VOTING_START_DATE); + logs[0].args.time.should.be.bignumber.equal(time); logs[0].args.voterMiningKey.should.be.equal(miningKey); logs[1].event.should.be.equal('BallotFinalized'); logs[1].args.id.should.be.bignumber.equal(0); @@ -588,7 +589,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { ); (await voting.getAmount.call(id)).should.be.bignumber.above(0); - await voting.setTime(VOTING_START_DATE+3); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.burn, {from: votingKey3}).should.be.fulfilled; const ballotInfo = await voting.getBallotInfo.call(id); @@ -676,7 +677,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { it('should not let vote with old miningKey', async () => { await addValidator(votingKey2, miningKey2); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; false.should.be.equal((await voting.getBallotInfo.call(id))[4]); // isFinalized @@ -795,7 +796,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { await addValidator(votingKey2, miningKey2); await addValidator(votingKey3, miningKey3); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey2}).should.be.fulfilled; await voting.vote(id, choice.freeze, {from: votingKey3}).should.be.fulfilled; @@ -815,7 +816,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { await addValidator(votingKey3, miningKey3); await addValidator(votingKey4, miningKey4); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey2}).should.be.fulfilled; await voting.vote(id, choice.send, {from: votingKey3}).should.be.fulfilled; @@ -838,7 +839,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { await addValidator(votingKey4, miningKey4); const receiverInitBalance = await web3.eth.getBalance(receiver); (await web3.eth.getBalance(emissionFunds.address)).should.be.bignumber.equal(emissionFundsInitBalance); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.send, {from: votingKey2}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey3}).should.be.fulfilled; @@ -865,7 +866,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { (await web3.eth.getBalance(emissionFunds.address)).should.be.bignumber.equal(emissionFundsInitBalance); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.send, {from: votingKey2}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey3}).should.be.fulfilled; @@ -891,7 +892,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { (await web3.eth.getBalance(emissionFunds.address)).should.be.bignumber.above(0); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey2}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey3}).should.be.fulfilled; @@ -927,7 +928,7 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { await addValidator(votingKey2, miningKey2); await addValidator(votingKey3, miningKey3); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey2}).should.be.fulfilled; diff --git a/test/voting_to_manage_emission_funds_upgrade_test.js b/test/voting_to_manage_emission_funds_upgrade_test.js index d89a43b..a172581 100644 --- a/test/voting_to_manage_emission_funds_upgrade_test.js +++ b/test/voting_to_manage_emission_funds_upgrade_test.js @@ -552,7 +552,8 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun const emissionFundsBalanceOld = await web3.eth.getBalance(emissionFunds.address); const receiverBalanceOld = await web3.eth.getBalance(receiver); - await voting.setTime(VOTING_START_DATE); + const time = VOTING_START_DATE + minBallotDuration + 1; + await voting.setTime(time); const {logs} = await voting.vote(id, choice.freeze, {from: votingKey}).should.be.fulfilled; const ballotInfo = await voting.getBallotInfo.call(id); @@ -570,7 +571,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun logs[0].args.id.should.be.bignumber.equal(0); logs[0].args.decision.should.be.bignumber.equal(choice.freeze); logs[0].args.voter.should.be.equal(votingKey); - logs[0].args.time.should.be.bignumber.equal(VOTING_START_DATE); + logs[0].args.time.should.be.bignumber.equal(time); logs[0].args.voterMiningKey.should.be.equal(miningKey); logs[1].event.should.be.equal('BallotFinalized'); logs[1].args.id.should.be.bignumber.equal(0); @@ -595,7 +596,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun ); (await voting.getAmount.call(id)).should.be.bignumber.above(0); - await voting.setTime(VOTING_START_DATE+3); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.burn, {from: votingKey3}).should.be.fulfilled; const ballotInfo = await voting.getBallotInfo.call(id); @@ -683,7 +684,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun it('should not let vote with old miningKey', async () => { await addValidator(votingKey2, miningKey2); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; false.should.be.equal((await voting.getBallotInfo.call(id))[4]); // isFinalized @@ -802,7 +803,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun await addValidator(votingKey2, miningKey2); await addValidator(votingKey3, miningKey3); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey2}).should.be.fulfilled; await voting.vote(id, choice.freeze, {from: votingKey3}).should.be.fulfilled; @@ -822,7 +823,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun await addValidator(votingKey3, miningKey3); await addValidator(votingKey4, miningKey4); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey2}).should.be.fulfilled; await voting.vote(id, choice.send, {from: votingKey3}).should.be.fulfilled; @@ -845,7 +846,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun await addValidator(votingKey4, miningKey4); const receiverInitBalance = await web3.eth.getBalance(receiver); (await web3.eth.getBalance(emissionFunds.address)).should.be.bignumber.equal(emissionFundsInitBalance); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.send, {from: votingKey2}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey3}).should.be.fulfilled; @@ -872,7 +873,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun (await web3.eth.getBalance(emissionFunds.address)).should.be.bignumber.equal(emissionFundsInitBalance); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.send, {from: votingKey2}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey3}).should.be.fulfilled; @@ -898,7 +899,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun (await web3.eth.getBalance(emissionFunds.address)).should.be.bignumber.above(0); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey2}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey3}).should.be.fulfilled; @@ -934,7 +935,7 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun await addValidator(votingKey2, miningKey2); await addValidator(votingKey3, miningKey3); - await voting.setTime(VOTING_START_DATE); + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; await voting.vote(id, choice.burn, {from: votingKey2}).should.be.fulfilled; From db59fa45db7ec23df1213cf1704bdffa92ba6a8a Mon Sep 17 00:00:00 2001 From: Max Alekseenko Date: Thu, 20 Jun 2019 18:56:43 +0300 Subject: [PATCH 8/9] add more tests --- test/voting_to_manage_emission_funds_test.js | 19 +++++++++++++++++++ ...g_to_manage_emission_funds_upgrade_test.js | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/test/voting_to_manage_emission_funds_test.js b/test/voting_to_manage_emission_funds_test.js index aa49eb3..1194d55 100644 --- a/test/voting_to_manage_emission_funds_test.js +++ b/test/voting_to_manage_emission_funds_test.js @@ -110,6 +110,13 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { minBallotDuration, emissionFunds.address ).should.be.rejectedWith(ERROR_MSG); + await voting.init( + emissionReleaseTime, + emissionReleaseThreshold, + distributionThreshold, + distributionThreshold + 1, + emissionFunds.address + ).should.be.rejectedWith(ERROR_MSG); // minBallotDuration can't be more than distributionThreshold await voting.init( emissionReleaseTime, emissionReleaseThreshold, @@ -732,6 +739,18 @@ contract('VotingToManageEmissionFunds [all features]', function (accounts) { await voting.setTime(VOTING_START_DATE); await voting.vote(id, choice.send, {from: votingKey}).should.be.rejectedWith(ERROR_MSG); }); + + it('should be finalized if elapsed time is greater than minBallotDuration', async () => { + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); + await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; + true.should.be.equal((await voting.getBallotInfo.call(id))[4]); // isFinalized + }); + + it('should not be finalized if elapsed time is less than minBallotDuration', async () => { + await voting.setTime(VOTING_START_DATE + minBallotDuration - 1); + await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; + false.should.be.equal((await voting.getBallotInfo.call(id))[4]); // isFinalized + }); }); describe('#finalize', async () => { diff --git a/test/voting_to_manage_emission_funds_upgrade_test.js b/test/voting_to_manage_emission_funds_upgrade_test.js index a172581..caf47dc 100644 --- a/test/voting_to_manage_emission_funds_upgrade_test.js +++ b/test/voting_to_manage_emission_funds_upgrade_test.js @@ -110,6 +110,13 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun minBallotDuration, emissionFunds.address ).should.be.rejectedWith(ERROR_MSG); + await voting.init( + emissionReleaseTime, + emissionReleaseThreshold, + distributionThreshold, + distributionThreshold + 1, + emissionFunds.address + ).should.be.rejectedWith(ERROR_MSG); // minBallotDuration can't be more than distributionThreshold await voting.init( emissionReleaseTime, emissionReleaseThreshold, @@ -739,6 +746,18 @@ contract('VotingToManageEmissionFunds upgraded [all features]', function (accoun await voting.setTime(VOTING_START_DATE); await voting.vote(id, choice.send, {from: votingKey}).should.be.rejectedWith(ERROR_MSG); }); + + it('should be finalized if elapsed time is greater than minBallotDuration', async () => { + await voting.setTime(VOTING_START_DATE + minBallotDuration + 1); + await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; + true.should.be.equal((await voting.getBallotInfo.call(id))[4]); // isFinalized + }); + + it('should not be finalized if elapsed time is less than minBallotDuration', async () => { + await voting.setTime(VOTING_START_DATE + minBallotDuration - 1); + await voting.vote(id, choice.send, {from: votingKey}).should.be.fulfilled; + false.should.be.equal((await voting.getBallotInfo.call(id))[4]); // isFinalized + }); }); describe('#finalize', async () => { From 139e40a5bea589fc526edd02a7b2b8d6aad1596c Mon Sep 17 00:00:00 2001 From: Max Alekseenko Date: Thu, 20 Jun 2019 19:38:54 +0300 Subject: [PATCH 9/9] remove redundant check --- contracts/VotingToManageEmissionFunds.sol | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/contracts/VotingToManageEmissionFunds.sol b/contracts/VotingToManageEmissionFunds.sol index 537d8df..3a8c92e 100644 --- a/contracts/VotingToManageEmissionFunds.sol +++ b/contracts/VotingToManageEmissionFunds.sol @@ -44,20 +44,14 @@ contract VotingToManageEmissionFunds is VotingTo { // solhint-disable code-complexity function canBeFinalizedNow(uint256 _id) public view returns(bool) { - uint256 currentTime = getTime(); - uint256 startTime = _getStartTime(_id); - uint256 diffTime = currentTime.sub(startTime); - if (_id >= nextBallotId()) return false; if (_id != nextBallotId().sub(1)) return false; - if (startTime > currentTime) return false; + if (_getStartTime(_id) > getTime()) return false; if (isActive(_id)) return false; if (_getIsCanceled(_id)) return false; if (_getIsFinalized(_id)) return false; if (noActiveBallotExists()) return false; if (_withinCancelingThreshold(_id)) return false; - if (diffTime <= minBallotDuration()) return false; - return true; } // solhint-enable code-complexity