From bc4f87f6baec019ed89c173e0dd090984c142644 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 11 Apr 2019 18:18:46 +0530 Subject: [PATCH 1/7] refactoring voting modules & adding functionality --- .../Experimental/Checkpoints/IVoting.sol | 50 +++++ .../Checkpoints/PLCRVotingCheckpoint.sol | 158 ++++++++++++---- .../Checkpoints/VotingCheckpoint.sol | 55 ++++++ .../Checkpoints/WeightedVoteCheckpoint.sol | 175 +++++++++++++----- test/zc_plcr_voting_checkpoint.js | 42 ++--- ...oint.js => zd_weighted_vote_checkpoint.js} | 0 6 files changed, 369 insertions(+), 111 deletions(-) create mode 100644 contracts/modules/Experimental/Checkpoints/IVoting.sol create mode 100644 contracts/modules/Experimental/Checkpoints/VotingCheckpoint.sol rename test/{zc_weighted_vote_checkpoint.js => zd_weighted_vote_checkpoint.js} (100%) diff --git a/contracts/modules/Experimental/Checkpoints/IVoting.sol b/contracts/modules/Experimental/Checkpoints/IVoting.sol new file mode 100644 index 000000000..915f1bd89 --- /dev/null +++ b/contracts/modules/Experimental/Checkpoints/IVoting.sol @@ -0,0 +1,50 @@ +pragma solidity ^0.5.0; + +interface IVoting { + + /** + * @notice Allows the token issuer to set the active stats of a ballot + * @param _ballotId The index of the target ballot + * @param _isActive The bool value of the active stats of the ballot + * @return bool success + */ + function changeBallotStatus(uint256 _ballotId, bool _isActive) external; + + /** + * @notice Queries the result of a given ballot + * @param _ballotId Id of the target ballot + * @return uint256 voteWeighting + * @return uint256 tieWith + * @return uint256 winningProposal + * @return bool isVotingSucceed + * @return uint256 totalVoters + */ + function getBallotResults(uint256 _ballotId) external view returns( + uint256[] memory voteWeighting, + uint256[] memory tieWith, + uint256 winningProposal, + bool isVotingSucceed, + uint256 totalVoters + ); + + /** + * @notice Get the voted proposal + * @param _ballotId Id of the ballot + * @param _voter Address of the voter + */ + function getSelectedProposal(uint256 _ballotId, address _voter) external view returns(uint256 proposalId); + + /** + * @notice Get the details of the ballot + * @param _ballotId The index of the target ballot + * @return uint256 quorum + * @return uint256 totalSupplyAtCheckpoint + * @return uint256 checkpointId + * @return uint256 startTime + * @return uint256 endTime + * @return uint256 totalProposals + * @return uint256 totalVoters + * @return bool isActive + */ + function getBallotDetails(uint256 _ballotId) external view returns(uint256, uint256, uint256, uint256, uint256, uint256, uint256, bool); +} \ No newline at end of file diff --git a/contracts/modules/Experimental/Checkpoints/PLCRVotingCheckpoint.sol b/contracts/modules/Experimental/Checkpoints/PLCRVotingCheckpoint.sol index c5001fabd..97d010db2 100644 --- a/contracts/modules/Experimental/Checkpoints/PLCRVotingCheckpoint.sol +++ b/contracts/modules/Experimental/Checkpoints/PLCRVotingCheckpoint.sol @@ -1,25 +1,26 @@ pragma solidity ^0.5.0; -import "../../Module.sol"; +import "./VotingCheckpoint.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -contract PLCRVotingCheckpoint is Module { +contract PLCRVotingCheckpoint is VotingCheckpoint { using SafeMath for uint256; enum Stage { PREP, COMMIT, REVEAL, RESOLVED } struct Ballot { + uint256 checkpointId; // Checkpoint At which ballot created uint256 quorum; // Should be a multiple of 10 ** 16 - uint256 checkpointId; - uint64 commitDuration; - uint64 revealDuration; - uint64 startTime; - uint24 totalProposals; - uint32 totalVoters; - bool isActive; - mapping(uint256 => uint256) weightedVote; - mapping(address => Vote) proposalToVote; + uint64 commitDuration; // no. of seconds the commit stage will live + uint64 revealDuration; // no. of seconds the reveal stage will live + uint64 startTime; // Timestamp at which ballot will come into effect + uint24 totalProposals; // Count of proposals allowed for a given ballot + uint32 totalVoters; // Count of voters who vote for the given ballot + bool isActive; // flag used to turn off/on the ballot + mapping(uint256 => uint256) proposalToVotes; // Mapping for proposal to total weight collected by the proposal + mapping(address => Vote) investorToProposal; // mapping for storing vote details of a voter + mapping(address => bool) exemptedVoters; // Mapping for blacklist voters } struct Vote { @@ -30,17 +31,25 @@ contract PLCRVotingCheckpoint is Module { Ballot[] ballots; event VoteCommit(address indexed _voter, uint256 _weight, uint256 indexed _ballotId, bytes32 _secretVote); + event VoteRevealed( + address indexed _voter, + uint256 _weight, + uint256 indexed _ballotId, + uint256 _choiceOfProposal, + uint256 _salt, + bytes32 _secretVote + ); event BallotCreated( uint256 indexed _ballotId, + uint256 indexed _checkpointId, + uint256 _startTime, uint256 _commitDuration, uint256 _revealDuration, uint256 _noOfProposals, - uint256 _startTime, - uint256 _proposedQuorum, - uint256 indexed _checkpointId + uint256 _proposedQuorum ); - event VoteRevealed(address indexed _voter, uint256 _weight, uint256 indexed _ballotId, uint256 _choiceOfProposal, uint256 _salt, bytes32 _secretVote); event BallotStatusChanged(uint256 indexed _ballotId, bool _newStatus); + event ChangedBallotExemptedVotersList(uint256 indexed _ballotId, address indexed_voter, bool _change); constructor(address _securityToken, address _polyAddress) public @@ -108,6 +117,7 @@ contract PLCRVotingCheckpoint is Module { _validValueCheck(_commitDuration); _validValueCheck(_revealDuration); _validValueCheck(_proposedQuorum); + require(_proposedQuorum <= 100 * 10 ** 16, "Invalid quorum percentage"); // not more than 100 % // Overflow check require( uint64(_commitDuration) == _commitDuration && @@ -122,8 +132,8 @@ contract PLCRVotingCheckpoint is Module { require(_totalProposals > 1, "Invalid number of totalProposals"); uint256 _ballotId = ballots.length; ballots.push(Ballot( - _proposedQuorum, _checkpointId, + _proposedQuorum, uint64(_commitDuration), uint64(_revealDuration), uint64(_startTime), @@ -131,7 +141,7 @@ contract PLCRVotingCheckpoint is Module { uint32(0), true )); - emit BallotCreated(_ballotId, _commitDuration, _revealDuration, _totalProposals, _startTime, _proposedQuorum, _checkpointId); + emit BallotCreated(_ballotId, _checkpointId, _startTime, _commitDuration, _revealDuration, _totalProposals, _proposedQuorum); } /** @@ -141,14 +151,15 @@ contract PLCRVotingCheckpoint is Module { */ function commitVote(uint256 _ballotId, bytes32 _secretVote) external { _validBallotId(_ballotId); + require(isVoterAllowed(_ballotId, msg.sender), "Invalid voter"); require(getCurrentBallotStage(_ballotId) == Stage.COMMIT, "Not in commit stage"); Ballot storage ballot = ballots[_ballotId]; - require(ballot.proposalToVote[msg.sender].secretVote == bytes32(0), "Already voted"); + require(ballot.investorToProposal[msg.sender].secretVote == bytes32(0), "Already voted"); require(_secretVote != bytes32(0), "Invalid vote"); require(ballot.isActive, "Inactive ballot"); uint256 weight = ISecurityToken(securityToken).balanceOfAt(msg.sender, ballot.checkpointId); require(weight > 0, "Zero weight is not allowed"); - ballot.proposalToVote[msg.sender] = Vote(0, _secretVote); + ballot.investorToProposal[msg.sender] = Vote(0, _secretVote); emit VoteCommit(msg.sender, weight, _ballotId, _secretVote); } @@ -163,23 +174,64 @@ contract PLCRVotingCheckpoint is Module { require(getCurrentBallotStage(_ballotId) == Stage.REVEAL, "Not in reveal stage"); Ballot storage ballot = ballots[_ballotId]; require(ballot.isActive, "Inactive ballot"); - require(ballot.proposalToVote[msg.sender].secretVote != bytes32(0), "Secret vote not available"); + require(ballot.investorToProposal[msg.sender].secretVote != bytes32(0), "Secret vote not available"); require(_choiceOfProposal < ballot.totalProposals && _choiceOfProposal >= 1, "Invalid proposal choice"); // validate the secret vote require( - bytes32(keccak256(abi.encodePacked(_choiceOfProposal, _salt))) == ballot.proposalToVote[msg.sender].secretVote, + bytes32(keccak256(abi.encodePacked(_choiceOfProposal, _salt))) == ballot.investorToProposal[msg.sender].secretVote, "Invalid vote" ); uint256 weight = ISecurityToken(securityToken).balanceOfAt(msg.sender, ballot.checkpointId); - bytes32 secretVote = ballot.proposalToVote[msg.sender].secretVote; - ballot.weightedVote[_choiceOfProposal] = ballot.weightedVote[_choiceOfProposal].add(weight); + bytes32 secretVote = ballot.investorToProposal[msg.sender].secretVote; + ballot.proposalToVotes[_choiceOfProposal] = ballot.proposalToVotes[_choiceOfProposal].add(weight); ballot.totalVoters = ballot.totalVoters + 1; - ballot.proposalToVote[msg.sender].voteOption = _choiceOfProposal; - ballot.proposalToVote[msg.sender].secretVote = bytes32(0); + ballot.investorToProposal[msg.sender] = Vote(_choiceOfProposal, bytes32(0)); emit VoteRevealed(msg.sender, weight, _ballotId, _choiceOfProposal, _salt, secretVote); } + /** + * Change the given ballot exempted list + * @param _ballotId Given ballot Id + * @param _voter Address of the voter + * @param _change Whether it is exempted or not + */ + function changeBallotExemptedVotersList(uint256 _ballotId, address _voter, bool _change) external withPerm(ADMIN) { + _changeBallotExemptedVotersList(_ballotId, _voter, _change); + } + + /** + * Change the given ballot exempted list (Multi) + * @param _ballotId Given ballot Id + * @param _voters Address of the voter + * @param _changes Whether it is exempted or not + */ + function changeBallotExemptedVotersListMulti(uint256 _ballotId, address[] calldata _voters, bool[] calldata _changes) external withPerm(ADMIN) { + require(_voters.length == _changes.length, "Array length mismatch"); + for (uint256 i = 0; i < _voters.length; i++) { + _changeBallotExemptedVotersList(_ballotId, _voters[i], _changes[i]); + } + } + + function _changeBallotExemptedVotersList(uint256 _ballotId, address _voter, bool _change) internal { + require(_voter != address(0), "Invalid address"); + _validBallotId(_ballotId); + require(ballots[_ballotId].exemptedVoters[_voter] != _change, "No change"); + ballots[_ballotId].exemptedVoters[_voter] = _change; + emit ChangedBallotExemptedVotersList(_ballotId, _voter, _change); + } + + /** + * Use to check whether the voter is allowed to vote or not + * @param _ballotId The index of the target ballot + * @param _voter Address of the voter + * @return bool + */ + function isVoterAllowed(uint256 _ballotId, address _voter) public view returns(bool) { + bool allowed = (ballots[_ballotId].exemptedVoters[_voter] || (defaultExemptIndex[_voter] != 0)); + return !allowed; + } + /** * @notice Allows the token issuer to set the active stats of a ballot * @param _ballotId The index of the target ballot @@ -226,23 +278,27 @@ contract PLCRVotingCheckpoint is Module { * @return bool isVotingSucceed * @return uint256 totalVoters */ - function getBallotResults(uint256 _ballotId) external view returns(uint256[] memory, uint256[] memory, uint256, bool, uint256) { + function getBallotResults(uint256 _ballotId) external view returns( + uint256[] memory voteWeighting, + uint256[] memory tieWith, + uint256 winningProposal, + bool isVotingSucceed, + uint256 totalVotes + ) { if (_ballotId >= ballots.length) return (new uint256[](0), new uint256[](0), 0, false, 0); Ballot storage ballot = ballots[_ballotId]; uint256 i = 0; - bool isVotingSucceed = false; uint256 counter = 0; uint256 maxWeight = 0; - uint256 winningProposal = 0; uint256 supplyAtCheckpoint = ISecurityToken(securityToken).totalSupplyAt(ballot.checkpointId); uint256 quorumWeight = (supplyAtCheckpoint.mul(ballot.quorum)).div(10 ** 18); - uint256[] memory voteWeighting = new uint256[](ballot.totalProposals); + voteWeighting = new uint256[](ballot.totalProposals); for (i = 0; i < ballot.totalProposals; i++) { - voteWeighting[i] = ballot.weightedVote[i + 1]; - if (maxWeight < ballot.weightedVote[i + 1]) { - maxWeight = ballot.weightedVote[i + 1]; + voteWeighting[i] = ballot.proposalToVotes[i + 1]; + if (maxWeight < ballot.proposalToVotes[i + 1]) { + maxWeight = ballot.proposalToVotes[i + 1]; if (maxWeight >= quorumWeight) winningProposal = i + 1; } @@ -250,22 +306,22 @@ contract PLCRVotingCheckpoint is Module { if (maxWeight >= quorumWeight) { isVotingSucceed = true; for (i = 0; i < ballot.totalProposals; i++) { - if (maxWeight == ballot.weightedVote[i + 1] && (i + 1) != winningProposal) + if (maxWeight == ballot.proposalToVotes[i + 1] && (i + 1) != winningProposal) counter ++; } } - uint256[] memory tieWith = new uint256[](counter); + tieWith = new uint256[](counter); if (counter > 0) { counter = 0; for (i = 0; i < ballot.totalProposals; i++) { - if (maxWeight == ballot.weightedVote[i + 1] && (i + 1) != winningProposal) { + if (maxWeight == ballot.proposalToVotes[i + 1] && (i + 1) != winningProposal) { tieWith[counter] = i + 1; counter ++; } } } - return (voteWeighting, tieWith, winningProposal, isVotingSucceed, ballot.totalVoters); + totalVotes = uint256(ballot.totalVoters); } /** @@ -276,28 +332,47 @@ contract PLCRVotingCheckpoint is Module { function getSelectedProposal(uint256 _ballotId, address _voter) external view returns(uint256 proposalId) { if (_ballotId >= ballots.length) return 0; - return (ballots[_ballotId].proposalToVote[_voter].voteOption); + return (ballots[_ballotId].investorToProposal[_voter].voteOption); } /** - * @notice Get the stats of the ballot + * @notice Get the details of the ballot * @param _ballotId The index of the target ballot + * @return uint256 quorum + * @return uint256 totalSupplyAtCheckpoint + * @return uint256 checkpointId + * @return uint256 startTime + * @return uint256 endTime + * @return uint256 totalProposals + * @return uint256 totalVoters + * @return bool isActive */ - function getBallotStats(uint256 _ballotId) external view returns(uint256, uint256, uint256, uint64, uint64, uint64, uint32, uint32, bool) { + function getBallotDetails(uint256 _ballotId) external view returns(uint256, uint256, uint256, uint256, uint256, uint256, uint256, bool) { Ballot memory ballot = ballots[_ballotId]; return ( ballot.quorum, ISecurityToken(securityToken).totalSupplyAt(ballot.checkpointId), ballot.checkpointId, - ballot.commitDuration, - ballot.revealDuration, ballot.startTime, + (uint256(ballot.startTime).add(uint256(ballot.commitDuration))).add(uint256(ballot.revealDuration)), ballot.totalProposals, ballot.totalVoters, ballot.isActive ); } + /** + * Return the commit relveal time duration of ballot + * @param _ballotId Id of a ballot + */ + function getBallotCommitRevealDuration(uint256 _ballotId) external view returns(uint256, uint256) { + Ballot memory ballot = ballots[_ballotId]; + return ( + ballot.commitDuration, + ballot.revealDuration + ); + } + /** * @notice This function returns the signature of configure function */ @@ -321,4 +396,5 @@ contract PLCRVotingCheckpoint is Module { function _validBallotId(uint256 _ballotId) internal view { require(ballots.length > _ballotId, "Index out of bound"); } + } \ No newline at end of file diff --git a/contracts/modules/Experimental/Checkpoints/VotingCheckpoint.sol b/contracts/modules/Experimental/Checkpoints/VotingCheckpoint.sol new file mode 100644 index 000000000..ce33d2e71 --- /dev/null +++ b/contracts/modules/Experimental/Checkpoints/VotingCheckpoint.sol @@ -0,0 +1,55 @@ +pragma solidity ^0.5.0; + +import "./IVoting.sol"; +import "../../Module.sol"; + +contract VotingCheckpoint is IVoting, Module { + + mapping(address => uint256) defaultExemptIndex; + address[] defaultExemptedVoters; + + event ChangedDefaultExemptedVotersList(address indexed _voter, bool _change); + + /** + * Change the global exempted voters list + * @param _voter Address of the voter + * @param _change Whether it is exempted or not + */ + function changeDefaultExemptedVotersList(address _voter, bool _change) external withPerm(ADMIN) { + _changeDefaultExemptedVotersList(_voter, _change); + } + + /** + * Change the global exempted voters list + * @param _voters Address of the voter + * @param _changes Whether it is exempted or not + */ + function changeDefaultExemptedVotersListMulti(address[] calldata _voters, bool[] calldata _changes) external withPerm(ADMIN) { + require(_voters.length == _changes.length, "Array length mismatch"); + for (uint256 i = 0; i < _voters.length; i++) { + _changeDefaultExemptedVotersList(_voters[i], _changes[i]); + } + } + + function _changeDefaultExemptedVotersList(address _voter, bool _change) internal { + require(_voter != address(0), "Invalid address"); + require((defaultExemptIndex[_voter] == 0) == _change); + if (_change) { + defaultExemptedVoters.push(_voter); + defaultExemptIndex[_voter] = defaultExemptedVoters.length; + } else { + defaultExemptedVoters[defaultExemptIndex[_voter] - 1] = defaultExemptedVoters[defaultExemptedVoters.length - 1]; + defaultExemptIndex[defaultExemptedVoters[defaultExemptIndex[_voter] - 1]] = defaultExemptIndex[_voter]; + delete defaultExemptIndex[_voter]; + defaultExemptedVoters.length --; + } + emit ChangedDefaultExemptedVotersList(_voter, _change); + } + + /** + * Return the default exemption list + */ + function getDefaultExemptionVotersList() external view returns(address[] memory) { + return defaultExemptedVoters; + } +} \ No newline at end of file diff --git a/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpoint.sol b/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpoint.sol index a21a31ce0..b586402fd 100644 --- a/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpoint.sol +++ b/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpoint.sol @@ -1,7 +1,6 @@ pragma solidity ^0.5.0; -import "../../Module.sol"; -import "../../Checkpoint/ICheckpoint.sol"; +import "./VotingCheckpoint.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** @@ -10,25 +9,35 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; * @notice In this module every token holder has voting right (Should be greater than zero) * Tally will be calculated as per the weight (balance of the token holder) */ -contract WeightedVoteCheckpoint is ICheckpoint, Module { +contract WeightedVoteCheckpoint is VotingCheckpoint { using SafeMath for uint256; struct Ballot { - uint256 checkpointId; - uint64 startTime; - uint64 endTime; - uint64 totalVoters; - uint56 totalProposals; - bool isActive; - mapping(uint256 => uint256) proposalToVotes; - mapping(address => uint256) investorToProposal; + uint256 checkpointId; // Checkpoint At which ballot created + uint256 quorum; // Should be a multiple of 10 ** 16 + uint64 startTime; // Timestamp at which ballot will come into effect + uint64 endTime; // Timestamp at which ballot will no more into effect + uint64 totalProposals; // Count of proposals allowed for a given ballot + uint56 totalVoters; // Count of voters who vote for the given ballot + bool isActive; // flag used to turn off/on the ballot + mapping(uint256 => uint256) proposalToVotes; // Mapping for proposal to total weight collected by the proposal + mapping(address => uint256) investorToProposal; // mapping for storing vote details of a voter + mapping(address => bool) exemptedVoters; // Mapping for blacklist voters } Ballot[] ballots; - event BallotCreated(uint256 _startTime, uint256 _endTime, uint256 indexed _ballotId, uint256 indexed _checkpointId, uint256 _noOfProposals); - event VoteCast(uint256 indexed _ballotId, uint256 indexed _proposalId, address indexed _investor, uint256 _weight); + event BallotCreated( + uint256 indexed _ballotId, + uint256 indexed _checkpointId, + uint256 _startTime, + uint256 _endTime, + uint256 _noOfProposals, + uint256 _proposedQuorum + ); + event VoteCast(address indexed _voter, uint256 _weight, uint256 indexed _ballotId, uint256 indexed _proposalId); event BallotStatusChanged(uint256 indexed _ballotId, bool _isActive); + event ChangedBallotExemptedVotersList(uint256 indexed _ballotId, address indexed_voter, bool _change); /** * @notice Constructor @@ -53,17 +62,27 @@ contract WeightedVoteCheckpoint is ICheckpoint, Module { * @notice Allows the token issuer to create a ballot * @param _duration The duration of the voting period in seconds * @param _noOfProposals Number of proposals + * @param _proposedQuorum Minimum Quorum percentage required to make a proposal won */ - function createBallot(uint256 _duration, uint256 _noOfProposals) external withPerm(ADMIN) { - require(_duration > 0, "Incorrect ballot duration."); + function createBallot(uint256 _duration, uint256 _noOfProposals, uint256 _proposedQuorum) external withPerm(ADMIN) { + require(_duration > 0, "Incorrect ballot duration"); uint256 checkpointId = ISecurityToken(securityToken).createCheckpoint(); uint256 endTime = now.add(_duration); - _createCustomBallot(now, endTime, checkpointId, _noOfProposals); + _createCustomBallot(checkpointId, _proposedQuorum, now, endTime, _noOfProposals); } - function _createCustomBallot(uint256 _startTime, uint256 _endTime, uint256 _checkpointId, uint256 _noOfProposals) internal { + function _createCustomBallot( + uint256 _checkpointId, + uint256 _proposedQuorum, + uint256 _startTime, + uint256 _endTime, + uint256 _noOfProposals + ) + internal + { require(_noOfProposals > 1, "Incorrect proposals no"); require(_endTime > _startTime, "Times are not valid"); + require(_proposedQuorum <= 100 * 10 ** 16 && _proposedQuorum > 0, "Invalid quorum percentage"); // not more than 100 % require( uint64(_startTime) == _startTime && uint64(_endTime) == _endTime && @@ -73,23 +92,24 @@ contract WeightedVoteCheckpoint is ICheckpoint, Module { uint256 ballotId = ballots.length; ballots.push( Ballot( - _checkpointId, uint64(_startTime), uint64(_endTime), uint64(0), uint56(_noOfProposals), true + _checkpointId, _proposedQuorum, uint64(_startTime), uint64(_endTime), uint56(_noOfProposals), uint64(0), true ) ); - emit BallotCreated(_startTime, _endTime, ballotId, _checkpointId, _noOfProposals); + emit BallotCreated(ballotId, _checkpointId, _startTime, _endTime, _noOfProposals, _proposedQuorum); } /** * @notice Allows the token issuer to create a ballot with custom settings + * @param _checkpointId Index of the checkpoint to use for token balances + * @param _proposedQuorum Minimum Quorum percentage required to make a proposal won * @param _startTime Start time of the voting period in Unix Epoch time * @param _endTime End time of the voting period in Unix Epoch time - * @param _checkpointId Index of the checkpoint to use for token balances * @param _noOfProposals Number of proposals */ - function createCustomBallot(uint256 _startTime, uint256 _endTime, uint256 _checkpointId, uint256 _noOfProposals) external withPerm(ADMIN) { + function createCustomBallot(uint256 _checkpointId, uint256 _proposedQuorum, uint256 _startTime, uint256 _endTime, uint256 _noOfProposals) external withPerm(ADMIN) { require(_checkpointId <= ISecurityToken(securityToken).currentCheckpointId(), "Invalid checkpoint Id"); require(_startTime >= now, "Invalid startTime"); - _createCustomBallot(_startTime, _endTime, _checkpointId, _noOfProposals); + _createCustomBallot(_checkpointId, _proposedQuorum, _startTime, _endTime, _noOfProposals); } /** @@ -100,7 +120,7 @@ contract WeightedVoteCheckpoint is ICheckpoint, Module { function castVote(uint256 _ballotId, uint256 _proposalId) external { require(_ballotId < ballots.length, "Incorrect ballot Id"); Ballot storage ballot = ballots[_ballotId]; - + require(isVoterAllowed(_ballotId, msg.sender), "Invalid voter"); uint256 weight = ISecurityToken(securityToken).balanceOfAt(msg.sender, ballot.checkpointId); require(weight > 0, "weight should be > 0"); require(ballot.totalProposals >= _proposalId && _proposalId > 0, "Incorrect proposals Id"); @@ -111,9 +131,51 @@ contract WeightedVoteCheckpoint is ICheckpoint, Module { ballot.investorToProposal[msg.sender] = _proposalId; ballot.totalVoters = ballot.totalVoters + 1; ballot.proposalToVotes[_proposalId] = ballot.proposalToVotes[_proposalId].add(weight); - emit VoteCast(_ballotId, _proposalId, msg.sender, weight); + emit VoteCast(msg.sender, weight, _ballotId, _proposalId); + } + + /** + * Change the given ballot exempted list + * @param _ballotId Given ballot Id + * @param _voter Address of the voter + * @param _change Whether it is exempted or not + */ + function changeBallotExemptedVotersList(uint256 _ballotId, address _voter, bool _change) external withPerm(ADMIN) { + _changeBallotExemptedVotersList(_ballotId, _voter, _change); } + /** + * Change the given ballot exempted list (Multi) + * @param _ballotId Given ballot Id + * @param _voters Address of the voter + * @param _changes Whether it is exempted or not + */ + function changeBallotExemptedVotersListMulti(uint256 _ballotId, address[] calldata _voters, bool[] calldata _changes) external withPerm(ADMIN) { + require(_voters.length == _changes.length, "Array length mismatch"); + for (uint256 i = 0; i < _voters.length; i++) { + _changeBallotExemptedVotersList(_ballotId, _voters[i], _changes[i]); + } + } + + function _changeBallotExemptedVotersList(uint256 _ballotId, address _voter, bool _change) internal { + require(_voter != address(0), "Invalid address"); + _validBallotId(_ballotId); + require(ballots[_ballotId].exemptedVoters[_voter] != _change, "No change"); + ballots[_ballotId].exemptedVoters[_voter] = _change; + emit ChangedBallotExemptedVotersList(_ballotId, _voter, _change); + } + + /** + * Use to check whether the voter is allowed to vote or not + * @param _ballotId The index of the target ballot + * @param _voter Address of the voter + * @return bool + */ + function isVoterAllowed(uint256 _ballotId, address _voter) public view returns(bool) { + bool allowed = (ballots[_ballotId].exemptedVoters[_voter] || (defaultExemptIndex[_voter] != 0)); + return !allowed; + } + /** * @notice Allows the token issuer to set the active stats of a ballot * @param _ballotId The index of the target ballot @@ -133,47 +195,53 @@ contract WeightedVoteCheckpoint is ICheckpoint, Module { * @return uint256 voteWeighting * @return uint256 tieWith * @return uint256 winningProposal - * @return uint256 remainingTime + * @return bool isVotingSucceed * @return uint256 totalVotes */ function getBallotResults(uint256 _ballotId) external view returns ( uint256[] memory voteWeighting, uint256[] memory tieWith, uint256 winningProposal, - uint256 remainingTime, + bool isVotingSucceed, uint256 totalVotes ) { if (_ballotId >= ballots.length) - return (new uint256[](0), new uint256[](0), winningProposal, remainingTime, totalVotes); + return (new uint256[](0), new uint256[](0), winningProposal, isVotingSucceed, totalVotes); Ballot storage ballot = ballots[_ballotId]; + uint256 i; uint256 counter = 0; uint256 maxWeight = 0; - uint256 i; + uint256 supplyAtCheckpoint = ISecurityToken(securityToken).totalSupplyAt(ballot.checkpointId); + uint256 quorumWeight = (supplyAtCheckpoint.mul(ballot.quorum)).div(10 ** 18); + voteWeighting = new uint256[](ballot.totalProposals); for (i = 0; i < ballot.totalProposals; i++) { - if (maxWeight < ballot.proposalToVotes[i+1]) { - maxWeight = ballot.proposalToVotes[i+1]; - winningProposal = i + 1; + voteWeighting[i] = ballot.proposalToVotes[i + 1]; + if (maxWeight < ballot.proposalToVotes[i + 1]) { + maxWeight = ballot.proposalToVotes[i + 1]; + if (maxWeight >= quorumWeight) + winningProposal = i + 1; } } - for (i = 0; i < ballot.totalProposals; i++) { - if (maxWeight == ballot.proposalToVotes[i+1]) - counter ++; + if (maxWeight >= quorumWeight) { + isVotingSucceed = true; + for (i = 0; i < ballot.totalProposals; i++) { + if (maxWeight == ballot.proposalToVotes[i + 1] && (i + 1) != winningProposal) + counter ++; + } } - voteWeighting = new uint256[](ballot.totalProposals); + tieWith = new uint256[](counter); - counter = 0; - for (i = 0; i < ballot.totalProposals; i++) { - voteWeighting[i] = ballot.proposalToVotes[i+1]; - if (maxWeight == ballot.proposalToVotes[i+1]) { - tieWith[counter] = i+1; - counter ++; - } + if (counter > 0) { + counter = 0; + for (i = 0; i < ballot.totalProposals; i++) { + if (maxWeight == ballot.proposalToVotes[i + 1] && (i + 1) != winningProposal) { + tieWith[counter] = i + 1; + counter ++; + } + } } - if (ballot.endTime >= uint64(now)) - remainingTime = uint256(ballot.endTime).sub(now); totalVotes = uint256(ballot.totalVoters); - return (voteWeighting, tieWith, winningProposal, remainingTime, totalVotes); } /** @@ -188,18 +256,27 @@ contract WeightedVoteCheckpoint is ICheckpoint, Module { } /** - * @notice Get the stats of the ballot + * @notice Get the details of the ballot * @param _ballotId The index of the target ballot + * @return uint256 quorum + * @return uint256 totalSupplyAtCheckpoint + * @return uint256 checkpointId + * @return uint256 startTime + * @return uint256 endTime + * @return uint256 totalProposals + * @return uint256 totalVoters + * @return bool isActive */ - function getBallotStats(uint256 _ballotId) external view returns(uint256, uint256, uint64, uint64, uint64, uint64, bool) { + function getBallotDetails(uint256 _ballotId) external view returns(uint256, uint256, uint256, uint256, uint256, uint256, uint256, bool) { Ballot memory ballot = ballots[_ballotId]; return ( - ballot.checkpointId, + ballot.quorum, ISecurityToken(securityToken).totalSupplyAt(ballot.checkpointId), + ballot.checkpointId, ballot.startTime, ballot.endTime, - ballot.totalVoters, ballot.totalProposals, + ballot.totalVoters, ballot.isActive ); } diff --git a/test/zc_plcr_voting_checkpoint.js b/test/zc_plcr_voting_checkpoint.js index 262e6accd..d96c572e9 100644 --- a/test/zc_plcr_voting_checkpoint.js +++ b/test/zc_plcr_voting_checkpoint.js @@ -315,8 +315,8 @@ contract("PLCRVotingCheckpoint", async (accounts) => { it("\t\t Should change some ballot status \n", async() => { await I_PLCRVotingCheckpoint.changeBallotStatus(new BN(0), false, {from: token_owner}); - let data = await I_PLCRVotingCheckpoint.getBallotStats.call(new BN(0)); - assert.isFalse(data[8]); + let data = await I_PLCRVotingCheckpoint.getBallotDetails.call(new BN(0)); + assert.isFalse(data[7]); }); it("\t\t Should fail to commitVote because ballot is not active \n", async() => { @@ -328,8 +328,8 @@ contract("PLCRVotingCheckpoint", async (accounts) => { it("\t\t Should change some ballot status \n", async() => { await I_PLCRVotingCheckpoint.changeBallotStatus(new BN(0), true, {from: token_owner}); - let data = await I_PLCRVotingCheckpoint.getBallotStats.call(new BN(0)); - assert.isTrue(data[8]); + let data = await I_PLCRVotingCheckpoint.getBallotDetails.call(new BN(0)); + assert.isTrue(data[7]); }); it("\t\t Should successfully vote by account investor1 \n", async() => { @@ -340,9 +340,9 @@ contract("PLCRVotingCheckpoint", async (accounts) => { assert.equal(tx.logs[0].args._secretVote, web3.utils.soliditySha3(2, salt)); assert.equal(tx.logs[0].args._voter, account_investor1); - let data = await I_PLCRVotingCheckpoint.getBallotStats.call(new BN(0)); - assert.equal(data[6], 3); - assert.equal(data[8], true); + let data = await I_PLCRVotingCheckpoint.getBallotDetails.call(new BN(0)); + assert.equal(data[5], 3); + assert.equal(data[7], true); }); it("\t\t Should failed to vote again \n", async() => { @@ -360,9 +360,9 @@ contract("PLCRVotingCheckpoint", async (accounts) => { assert.equal(tx.logs[0].args._secretVote, web3.utils.soliditySha3(1, salt)); assert.equal(tx.logs[0].args._voter, account_investor3); - let data = await I_PLCRVotingCheckpoint.getBallotStats.call(new BN(0)); - assert.equal(data[6], 3); - assert.equal(data[8], true); + let data = await I_PLCRVotingCheckpoint.getBallotDetails.call(new BN(0)); + assert.equal(data[5], 3); + assert.equal(data[7], true); }); it("\t\t Should successfully vote by account investor2 \n", async() => { @@ -373,9 +373,9 @@ contract("PLCRVotingCheckpoint", async (accounts) => { assert.equal(tx.logs[0].args._secretVote, web3.utils.soliditySha3(2, salt)); assert.equal(tx.logs[0].args._voter, account_investor2); - let data = await I_PLCRVotingCheckpoint.getBallotStats.call(new BN(0)); - assert.equal(data[6], 3); - assert.equal(data[8], true); + let data = await I_PLCRVotingCheckpoint.getBallotDetails.call(new BN(0)); + assert.equal(data[5], 3); + assert.equal(data[7], true); }); it("\t\t Mint some more tokens and transferred to the tokens holders \n", async() => { @@ -452,10 +452,10 @@ contract("PLCRVotingCheckpoint", async (accounts) => { assert.equal(tx.logs[0].args._ballotId, 0); assert.equal(tx.logs[0].args._choiceOfProposal, 1); assert.equal(tx.logs[0].args._salt, saltArray[1]); - let data = await I_PLCRVotingCheckpoint.getBallotStats.call(new BN(0)); - assert.equal(data[6], 3); - assert.equal(data[7], 1); - assert.equal(data[8], true); + let data = await I_PLCRVotingCheckpoint.getBallotDetails.call(new BN(0)); + assert.equal(data[5], 3); + assert.equal(data[6], 1); + assert.equal(data[7], true); }); it("\t\t Should fail to change the ballot status-- bad owner \n", async() => { @@ -492,10 +492,10 @@ contract("PLCRVotingCheckpoint", async (accounts) => { assert.equal(txData.logs[0].args._ballotId, 0); assert.equal(txData.logs[0].args._choiceOfProposal, 2); assert.equal(txData.logs[0].args._salt, saltArray[0]); - let data = await I_PLCRVotingCheckpoint.getBallotStats.call(new BN(0)); - assert.equal(data[6], 3); - assert.equal(data[7], 2); - assert.equal(data[8], true); + let data = await I_PLCRVotingCheckpoint.getBallotDetails.call(new BN(0)); + assert.equal(data[5], 3); + assert.equal(data[6], 2); + assert.equal(data[7], true); }); it("\t\t Should fail to reveal vote again \n", async() => { diff --git a/test/zc_weighted_vote_checkpoint.js b/test/zd_weighted_vote_checkpoint.js similarity index 100% rename from test/zc_weighted_vote_checkpoint.js rename to test/zd_weighted_vote_checkpoint.js From 97f093dacb7448e12402d62c4e1136e39fc889d5 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 11 Apr 2019 19:15:10 +0530 Subject: [PATCH 2/7] fix compiler error --- .../Checkpoints/WeightedVoteCheckpoint.sol | 10 ++++-- test/zd_weighted_vote_checkpoint.js | 35 ++++++++++++++----- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpoint.sol b/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpoint.sol index b586402fd..43f3ef667 100644 --- a/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpoint.sol +++ b/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpoint.sol @@ -86,13 +86,13 @@ contract WeightedVoteCheckpoint is VotingCheckpoint { require( uint64(_startTime) == _startTime && uint64(_endTime) == _endTime && - uint56(_noOfProposals) == _noOfProposals, + uint64(_noOfProposals) == _noOfProposals, "values get overflowed" ); uint256 ballotId = ballots.length; ballots.push( Ballot( - _checkpointId, _proposedQuorum, uint64(_startTime), uint64(_endTime), uint56(_noOfProposals), uint64(0), true + _checkpointId, _proposedQuorum, uint64(_startTime), uint64(_endTime), uint64(_noOfProposals), uint56(0), true ) ); emit BallotCreated(ballotId, _checkpointId, _startTime, _endTime, _noOfProposals, _proposedQuorum); @@ -118,7 +118,7 @@ contract WeightedVoteCheckpoint is VotingCheckpoint { * @param _proposalId Id of the proposal which investor want to vote for proposal */ function castVote(uint256 _ballotId, uint256 _proposalId) external { - require(_ballotId < ballots.length, "Incorrect ballot Id"); + _validBallotId(_ballotId); Ballot storage ballot = ballots[_ballotId]; require(isVoterAllowed(_ballotId, msg.sender), "Invalid voter"); uint256 weight = ISecurityToken(securityToken).balanceOfAt(msg.sender, ballot.checkpointId); @@ -291,4 +291,8 @@ contract WeightedVoteCheckpoint is VotingCheckpoint { return allPermissions; } + function _validBallotId(uint256 _ballotId) internal view { + require(ballots.length > _ballotId, "Index out of bound"); + } + } diff --git a/test/zd_weighted_vote_checkpoint.js b/test/zd_weighted_vote_checkpoint.js index 5578d142f..62005e720 100644 --- a/test/zd_weighted_vote_checkpoint.js +++ b/test/zd_weighted_vote_checkpoint.js @@ -182,19 +182,31 @@ contract("WeightedVoteCheckpoint", async (accounts) => { it("\t\t Should fail to create ballot -- bad owner \n", async() => { await catchRevert( - I_WeightedVoteCheckpoint.createBallot(new BN(duration.days(5)), new BN(5), {from: account_polymath}) + I_WeightedVoteCheckpoint.createBallot(new BN(duration.days(5)), new BN(5), new BN(51).mul(new BN(10).pow(new BN(16))), {from: account_polymath}) ); }); it("\t\t Should fail to create ballot -- bad duration \n", async() => { await catchRevert( - I_WeightedVoteCheckpoint.createBallot(new BN(0), new BN(5), {from: token_owner}) + I_WeightedVoteCheckpoint.createBallot(new BN(0), new BN(5), new BN(51).mul(new BN(10).pow(new BN(16))), {from: token_owner}) ); }); it("\t\t Should fail to create ballot -- bad no of proposals \n", async() => { await catchRevert( - I_WeightedVoteCheckpoint.createBallot(new BN(duration.days(5)), new BN(1), {from: token_owner}) + I_WeightedVoteCheckpoint.createBallot(new BN(duration.days(5)), new BN(1), new BN(51).mul(new BN(10).pow(new BN(16))), {from: token_owner}) + ); + }); + + it("\t\t Should fail to create ballot -- zero value of quorum \n", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.createBallot(new BN(duration.days(5)), new BN(1), new BN(0), {from: token_owner}) + ); + }); + + it("\t\t Should fail to create ballot -- value of quorum is more than the limit\n", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.createBallot(new BN(duration.days(5)), new BN(1), new BN(51).mul(new BN(10).pow(new BN(17))), {from: token_owner}) ); }); @@ -230,12 +242,12 @@ contract("WeightedVoteCheckpoint", async (accounts) => { let startTime = new BN(await latestTime()); let endTime = new BN(await latestTime() + duration.days(4)); await catchRevert( - I_WeightedVoteCheckpoint.createCustomBallot(startTime, endTime, new BN(100), new BN(5), {from: token_owner}) + I_WeightedVoteCheckpoint.createCustomBallot(new BN(5), new BN(51).mul(new BN(10).pow(new BN(17))), startTime, endTime, new BN(100), {from: token_owner}) ); }); it("\t\t Should create the ballot successfully \n", async() => { - let tx = await I_WeightedVoteCheckpoint.createBallot(new BN(duration.days(5)), new BN(3), {from: token_owner}); + let tx = await I_WeightedVoteCheckpoint.createBallot(new BN(duration.days(5)), new BN(3), new BN(51).mul(new BN(10).pow(new BN(17))), {from: token_owner}); assert.equal((tx.logs[0].args._noOfProposals).toString(), 3); assert.equal((tx.logs[0].args._checkpointId).toString(), 1); assert.equal((tx.logs[0].args._ballotId).toString(), 0); @@ -268,7 +280,8 @@ contract("WeightedVoteCheckpoint", async (accounts) => { assert.equal(tx.logs[0].args._proposalId, 1); assert.equal(tx.logs[0].args._investor, account_investor1); - let data = await I_WeightedVoteCheckpoint.getBallotStats.call(new BN(0)); + let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); + console.log(data); assert.equal(data[4], 1); assert.equal(data[5], 3); assert.equal(data[6], true); @@ -280,7 +293,7 @@ contract("WeightedVoteCheckpoint", async (accounts) => { assert.equal(tx.logs[0].args._proposalId, 2); assert.equal(tx.logs[0].args._investor, account_investor2); - let data = await I_WeightedVoteCheckpoint.getBallotStats.call(new BN(0)); + let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); assert.equal(data[4], 2); assert.equal(data[5], 3); assert.equal(data[6], true); @@ -290,7 +303,11 @@ contract("WeightedVoteCheckpoint", async (accounts) => { await catchRevert( I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}) ); - }) + }); + + it("\t\t Should add the voter in to the ballot exemption list", async() => { + + }); it("\t\t Should fail to change the ballot status-- bad owner \n", async() => { await catchRevert( @@ -328,7 +345,7 @@ contract("WeightedVoteCheckpoint", async (accounts) => { assert.equal(tx.logs[0].args._proposalId, 1); assert.equal(tx.logs[0].args._investor, account_investor3); - let data = await I_WeightedVoteCheckpoint.getBallotStats.call(new BN(0)); + let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); assert.equal(data[4], 3); assert.equal(data[5], 3); assert.equal(data[6], true); From 34e6be4f3ef60a953a7dbe208e55575aa3f7dc4b Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 12 Apr 2019 14:06:07 +0530 Subject: [PATCH 3/7] move voting modules from experimental --- .../Checkpoints => interfaces}/IVoting.sol | 0 .../{ => Dividend}/DividendCheckpoint.sol | 6 +- .../ERC20/ERC20DividendCheckpoint.sol | 2 +- .../ERC20/ERC20DividendCheckpointFactory.sol | 6 +- .../ERC20/ERC20DividendCheckpointProxy.sol | 8 +- .../ERC20/ERC20DividendCheckpointStorage.sol | 0 .../Ether/EtherDividendCheckpoint.sol | 2 +- .../Ether/EtherDividendCheckpointFactory.sol | 6 +- .../Ether/EtherDividendCheckpointProxy.sol | 8 +- .../Voting/PLCR}/PLCRVotingCheckpoint.sol | 28 +-- .../PLCR}/PLCRVotingCheckpointFactory.sol | 16 +- .../Voting/PLCR/PLCRVotingCheckpointProxy.sol | 32 +++ .../PLCR/PLCRVotingCheckpointStorage.sol | 27 +++ .../Transparent}/WeightedVoteCheckpoint.sol | 20 +- .../WeightedVoteCheckpointFactory.sol | 18 +- .../WeightedVoteCheckpointProxy.sol | 32 +++ .../WeightedVoteCheckpointStorage.sol | 19 ++ .../Voting}/VotingCheckpoint.sol | 9 +- .../DividendCheckpointStorage.sol | 0 .../Voting/VotingCheckpointStorage.sol | 8 + test/helpers/createInstances.js | 16 +- test/zd_weighted_vote_checkpoint.js | 204 +++++++++--------- 22 files changed, 280 insertions(+), 187 deletions(-) rename contracts/{modules/Experimental/Checkpoints => interfaces}/IVoting.sol (100%) rename contracts/modules/Checkpoint/{ => Dividend}/DividendCheckpoint.sol (99%) rename contracts/modules/Checkpoint/{ => Dividend}/ERC20/ERC20DividendCheckpoint.sol (99%) rename contracts/modules/Checkpoint/{ => Dividend}/ERC20/ERC20DividendCheckpointFactory.sol (93%) rename contracts/modules/Checkpoint/{ => Dividend}/ERC20/ERC20DividendCheckpointProxy.sol (79%) rename contracts/modules/Checkpoint/{ => Dividend}/ERC20/ERC20DividendCheckpointStorage.sol (100%) rename contracts/modules/Checkpoint/{ => Dividend}/Ether/EtherDividendCheckpoint.sol (99%) rename contracts/modules/Checkpoint/{ => Dividend}/Ether/EtherDividendCheckpointFactory.sol (93%) rename contracts/modules/Checkpoint/{ => Dividend}/Ether/EtherDividendCheckpointProxy.sol (78%) rename contracts/modules/{Experimental/Checkpoints => Checkpoint/Voting/PLCR}/PLCRVotingCheckpoint.sol (92%) rename contracts/modules/{Experimental/Checkpoints => Checkpoint/Voting/PLCR}/PLCRVotingCheckpointFactory.sol (68%) create mode 100644 contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpointProxy.sol create mode 100644 contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpointStorage.sol rename contracts/modules/{Experimental/Checkpoints => Checkpoint/Voting/Transparent}/WeightedVoteCheckpoint.sol (92%) rename contracts/modules/{Experimental/Checkpoints => Checkpoint/Voting/Transparent}/WeightedVoteCheckpointFactory.sol (67%) create mode 100644 contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpointProxy.sol create mode 100644 contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpointStorage.sol rename contracts/modules/{Experimental/Checkpoints => Checkpoint/Voting}/VotingCheckpoint.sol (89%) rename contracts/storage/modules/Checkpoint/{ => Dividend}/DividendCheckpointStorage.sol (100%) create mode 100644 contracts/storage/modules/Checkpoint/Voting/VotingCheckpointStorage.sol diff --git a/contracts/modules/Experimental/Checkpoints/IVoting.sol b/contracts/interfaces/IVoting.sol similarity index 100% rename from contracts/modules/Experimental/Checkpoints/IVoting.sol rename to contracts/interfaces/IVoting.sol diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/Dividend/DividendCheckpoint.sol similarity index 99% rename from contracts/modules/Checkpoint/DividendCheckpoint.sol rename to contracts/modules/Checkpoint/Dividend/DividendCheckpoint.sol index 591aed22a..4fc462f95 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/Dividend/DividendCheckpoint.sol @@ -7,9 +7,9 @@ */ pragma solidity ^0.5.0; -import "./ICheckpoint.sol"; -import "../../storage/modules/Checkpoint/DividendCheckpointStorage.sol"; -import "../Module.sol"; +import ".././ICheckpoint.sol"; +import "../../../storage/modules/Checkpoint/Dividend/DividendCheckpointStorage.sol"; +import "../../Module.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/math/Math.sol"; diff --git a/contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/Dividend/ERC20/ERC20DividendCheckpoint.sol similarity index 99% rename from contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpoint.sol rename to contracts/modules/Checkpoint/Dividend/ERC20/ERC20DividendCheckpoint.sol index b4120122d..dd070d176 100644 --- a/contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/Dividend/ERC20/ERC20DividendCheckpoint.sol @@ -2,7 +2,7 @@ pragma solidity ^0.5.0; import "../DividendCheckpoint.sol"; import "./ERC20DividendCheckpointStorage.sol"; -import "../../../interfaces/IOwnable.sol"; +import "../../../../interfaces/IOwnable.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; /** diff --git a/contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/Dividend/ERC20/ERC20DividendCheckpointFactory.sol similarity index 93% rename from contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpointFactory.sol rename to contracts/modules/Checkpoint/Dividend/ERC20/ERC20DividendCheckpointFactory.sol index 30b88f1b9..1443d7a1f 100644 --- a/contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/Dividend/ERC20/ERC20DividendCheckpointFactory.sol @@ -1,9 +1,9 @@ pragma solidity ^0.5.0; import "./ERC20DividendCheckpointProxy.sol"; -import "../../../libraries/Util.sol"; -import "../../../interfaces/IBoot.sol"; -import "../../UpgradableModuleFactory.sol"; +import "../../../../libraries/Util.sol"; +import "../../../../interfaces/IBoot.sol"; +import "../../../UpgradableModuleFactory.sol"; /** * @title Factory for deploying ERC20DividendCheckpoint module diff --git a/contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpointProxy.sol b/contracts/modules/Checkpoint/Dividend/ERC20/ERC20DividendCheckpointProxy.sol similarity index 79% rename from contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpointProxy.sol rename to contracts/modules/Checkpoint/Dividend/ERC20/ERC20DividendCheckpointProxy.sol index 2cd814bf0..7b13a2bf8 100644 --- a/contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpointProxy.sol +++ b/contracts/modules/Checkpoint/Dividend/ERC20/ERC20DividendCheckpointProxy.sol @@ -1,10 +1,10 @@ pragma solidity ^0.5.0; -import "../../../proxy/OwnedUpgradeabilityProxy.sol"; +import "../../../../proxy/OwnedUpgradeabilityProxy.sol"; import "./ERC20DividendCheckpointStorage.sol"; -import "../../../storage/modules/Checkpoint/DividendCheckpointStorage.sol"; -import "../../../Pausable.sol"; -import "../../../storage/modules/ModuleStorage.sol"; +import "../../../../storage/modules/Checkpoint/Dividend/DividendCheckpointStorage.sol"; +import "../../../../Pausable.sol"; +import "../../../../storage/modules/ModuleStorage.sol"; /** * @title Transfer Manager module for core transfer validation functionality diff --git a/contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/Dividend/ERC20/ERC20DividendCheckpointStorage.sol similarity index 100% rename from contracts/modules/Checkpoint/ERC20/ERC20DividendCheckpointStorage.sol rename to contracts/modules/Checkpoint/Dividend/ERC20/ERC20DividendCheckpointStorage.sol diff --git a/contracts/modules/Checkpoint/Ether/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/Dividend/Ether/EtherDividendCheckpoint.sol similarity index 99% rename from contracts/modules/Checkpoint/Ether/EtherDividendCheckpoint.sol rename to contracts/modules/Checkpoint/Dividend/Ether/EtherDividendCheckpoint.sol index 6478f3e55..f8e20f3b0 100644 --- a/contracts/modules/Checkpoint/Ether/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/Dividend/Ether/EtherDividendCheckpoint.sol @@ -1,7 +1,7 @@ pragma solidity ^0.5.0; import "../DividendCheckpoint.sol"; -import "../../../interfaces/IOwnable.sol"; +import "../../../../interfaces/IOwnable.sol"; /** * @title Checkpoint module for issuing ether dividends diff --git a/contracts/modules/Checkpoint/Ether/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/Dividend/Ether/EtherDividendCheckpointFactory.sol similarity index 93% rename from contracts/modules/Checkpoint/Ether/EtherDividendCheckpointFactory.sol rename to contracts/modules/Checkpoint/Dividend/Ether/EtherDividendCheckpointFactory.sol index 7cd20074e..97eda239a 100644 --- a/contracts/modules/Checkpoint/Ether/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/Dividend/Ether/EtherDividendCheckpointFactory.sol @@ -1,9 +1,9 @@ pragma solidity ^0.5.0; import "./EtherDividendCheckpointProxy.sol"; -import "../../../libraries/Util.sol"; -import "../../../interfaces/IBoot.sol"; -import "../../UpgradableModuleFactory.sol"; +import "../../../../libraries/Util.sol"; +import "../../../../interfaces/IBoot.sol"; +import "../../../UpgradableModuleFactory.sol"; /** * @title Factory for deploying EtherDividendCheckpoint module diff --git a/contracts/modules/Checkpoint/Ether/EtherDividendCheckpointProxy.sol b/contracts/modules/Checkpoint/Dividend/Ether/EtherDividendCheckpointProxy.sol similarity index 78% rename from contracts/modules/Checkpoint/Ether/EtherDividendCheckpointProxy.sol rename to contracts/modules/Checkpoint/Dividend/Ether/EtherDividendCheckpointProxy.sol index d0298d204..3e97b585d 100644 --- a/contracts/modules/Checkpoint/Ether/EtherDividendCheckpointProxy.sol +++ b/contracts/modules/Checkpoint/Dividend/Ether/EtherDividendCheckpointProxy.sol @@ -1,9 +1,9 @@ pragma solidity ^0.5.0; -import "../../../proxy/OwnedUpgradeabilityProxy.sol"; -import "../../../storage/modules/Checkpoint/DividendCheckpointStorage.sol"; -import "../../../Pausable.sol"; -import "../../../storage/modules/ModuleStorage.sol"; +import "../../../../proxy/OwnedUpgradeabilityProxy.sol"; +import "../../../../storage/modules/Checkpoint/Dividend/DividendCheckpointStorage.sol"; +import "../../../../Pausable.sol"; +import "../../../../storage/modules/ModuleStorage.sol"; /** * @title Transfer Manager module for core transfer validation functionality diff --git a/contracts/modules/Experimental/Checkpoints/PLCRVotingCheckpoint.sol b/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpoint.sol similarity index 92% rename from contracts/modules/Experimental/Checkpoints/PLCRVotingCheckpoint.sol rename to contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpoint.sol index 97d010db2..8d5a069c4 100644 --- a/contracts/modules/Experimental/Checkpoints/PLCRVotingCheckpoint.sol +++ b/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpoint.sol @@ -1,35 +1,13 @@ pragma solidity ^0.5.0; -import "./VotingCheckpoint.sol"; +import "../VotingCheckpoint.sol"; +import "./PLCRVotingCheckpointStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -contract PLCRVotingCheckpoint is VotingCheckpoint { +contract PLCRVotingCheckpoint is PLCRVotingCheckpointStorage, VotingCheckpoint { using SafeMath for uint256; - enum Stage { PREP, COMMIT, REVEAL, RESOLVED } - - struct Ballot { - uint256 checkpointId; // Checkpoint At which ballot created - uint256 quorum; // Should be a multiple of 10 ** 16 - uint64 commitDuration; // no. of seconds the commit stage will live - uint64 revealDuration; // no. of seconds the reveal stage will live - uint64 startTime; // Timestamp at which ballot will come into effect - uint24 totalProposals; // Count of proposals allowed for a given ballot - uint32 totalVoters; // Count of voters who vote for the given ballot - bool isActive; // flag used to turn off/on the ballot - mapping(uint256 => uint256) proposalToVotes; // Mapping for proposal to total weight collected by the proposal - mapping(address => Vote) investorToProposal; // mapping for storing vote details of a voter - mapping(address => bool) exemptedVoters; // Mapping for blacklist voters - } - - struct Vote { - uint256 voteOption; - bytes32 secretVote; - } - - Ballot[] ballots; - event VoteCommit(address indexed _voter, uint256 _weight, uint256 indexed _ballotId, bytes32 _secretVote); event VoteRevealed( address indexed _voter, diff --git a/contracts/modules/Experimental/Checkpoints/PLCRVotingCheckpointFactory.sol b/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpointFactory.sol similarity index 68% rename from contracts/modules/Experimental/Checkpoints/PLCRVotingCheckpointFactory.sol rename to contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpointFactory.sol index 173ed0c5b..cb0f07efe 100644 --- a/contracts/modules/Experimental/Checkpoints/PLCRVotingCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpointFactory.sol @@ -1,28 +1,32 @@ pragma solidity ^0.5.0; -import "./PLCRVotingCheckpoint.sol"; -import "../../ModuleFactory.sol"; +import "./PLCRVotingCheckpointProxy.sol"; +import "../../../../libraries/Util.sol"; +import "../../../../interfaces/IBoot.sol"; +import "../../../UpgradableModuleFactory.sol"; /** * @title Factory for deploying PLCRVotingCheckpoint module */ -contract PLCRVotingCheckpointFactory is ModuleFactory { +contract PLCRVotingCheckpointFactory is UpgradableModuleFactory { /** * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module + * @param _logicContract Contract address that contains the logic related to `description` * @param _polymathRegistry Address of the Polymath registry * @param _isCostInPoly true = cost in Poly, false = USD */ constructor ( uint256 _setupCost, uint256 _usageCost, + address _logicContract, address _polymathRegistry, bool _isCostInPoly - ) + ) public - ModuleFactory(_setupCost, _usageCost, _polymathRegistry, _isCostInPoly) + UpgradableModuleFactory("3.0.0", _setupCost, _usageCost, _logicContract, _polymathRegistry, _isCostInPoly) { initialVersion = "3.0.0"; name = "PLCRVotingCheckpoint"; @@ -42,7 +46,7 @@ contract PLCRVotingCheckpointFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes calldata _data) external returns(address) { - address plcrVotingCheckpoint = address(new PLCRVotingCheckpoint(msg.sender, IPolymathRegistry(polymathRegistry).getAddress("PolyToken"))); + address plcrVotingCheckpoint = address(new PLCRVotingCheckpointProxy(logicContracts[latestUpgrade].version, msg.sender, IPolymathRegistry(polymathRegistry).getAddress("PolyToken"), logicContracts[latestUpgrade].logicContract)); _initializeModule(plcrVotingCheckpoint, _data); return plcrVotingCheckpoint; } diff --git a/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpointProxy.sol b/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpointProxy.sol new file mode 100644 index 000000000..f225511c1 --- /dev/null +++ b/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpointProxy.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.5.0; + +import "../../../../Pausable.sol"; +import "./PLCRVotingCheckpointStorage.sol"; +import "../../../../storage/modules/ModuleStorage.sol"; +import "../../../../proxy/OwnedUpgradeabilityProxy.sol"; +import "../../../../storage/modules/Checkpoint/Voting/VotingCheckpointStorage.sol"; + +/** + * @title Voting module for governance + */ +contract PLCRVotingCheckpointProxy is PLCRVotingCheckpointStorage, VotingCheckpointStorage, ModuleStorage, Pausable, OwnedUpgradeabilityProxy { + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor( + string memory _version, + address _securityToken, + address _polyAddress, + address _implementation + ) + public + ModuleStorage(_securityToken, _polyAddress) + { + require(_implementation != address(0), "Implementation address should not be 0x"); + _upgradeTo(_version, _implementation); + } + +} \ No newline at end of file diff --git a/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpointStorage.sol b/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpointStorage.sol new file mode 100644 index 000000000..99be4a0c6 --- /dev/null +++ b/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpointStorage.sol @@ -0,0 +1,27 @@ +pragma solidity ^0.5.0; + +contract PLCRVotingCheckpointStorage { + + enum Stage { PREP, COMMIT, REVEAL, RESOLVED } + + struct Ballot { + uint256 checkpointId; // Checkpoint At which ballot created + uint256 quorum; // Should be a multiple of 10 ** 16 + uint64 commitDuration; // no. of seconds the commit stage will live + uint64 revealDuration; // no. of seconds the reveal stage will live + uint64 startTime; // Timestamp at which ballot will come into effect + uint24 totalProposals; // Count of proposals allowed for a given ballot + uint32 totalVoters; // Count of voters who vote for the given ballot + bool isActive; // flag used to turn off/on the ballot + mapping(uint256 => uint256) proposalToVotes; // Mapping for proposal to total weight collected by the proposal + mapping(address => Vote) investorToProposal; // mapping for storing vote details of a voter + mapping(address => bool) exemptedVoters; // Mapping for blacklist voters + } + + struct Vote { + uint256 voteOption; + bytes32 secretVote; + } + + Ballot[] ballots; +} \ No newline at end of file diff --git a/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpoint.sol b/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpoint.sol similarity index 92% rename from contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpoint.sol rename to contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpoint.sol index 43f3ef667..2ccd96bd3 100644 --- a/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpoint.sol +++ b/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpoint.sol @@ -1,6 +1,7 @@ pragma solidity ^0.5.0; -import "./VotingCheckpoint.sol"; +import "../VotingCheckpoint.sol"; +import "./WeightedVoteCheckpointStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** @@ -9,24 +10,9 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; * @notice In this module every token holder has voting right (Should be greater than zero) * Tally will be calculated as per the weight (balance of the token holder) */ -contract WeightedVoteCheckpoint is VotingCheckpoint { +contract WeightedVoteCheckpoint is WeightedVoteCheckpointStorage, VotingCheckpoint { using SafeMath for uint256; - struct Ballot { - uint256 checkpointId; // Checkpoint At which ballot created - uint256 quorum; // Should be a multiple of 10 ** 16 - uint64 startTime; // Timestamp at which ballot will come into effect - uint64 endTime; // Timestamp at which ballot will no more into effect - uint64 totalProposals; // Count of proposals allowed for a given ballot - uint56 totalVoters; // Count of voters who vote for the given ballot - bool isActive; // flag used to turn off/on the ballot - mapping(uint256 => uint256) proposalToVotes; // Mapping for proposal to total weight collected by the proposal - mapping(address => uint256) investorToProposal; // mapping for storing vote details of a voter - mapping(address => bool) exemptedVoters; // Mapping for blacklist voters - } - - Ballot[] ballots; - event BallotCreated( uint256 indexed _ballotId, uint256 indexed _checkpointId, diff --git a/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpointFactory.sol b/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpointFactory.sol similarity index 67% rename from contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpointFactory.sol rename to contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpointFactory.sol index 08dfcb417..65c530b6a 100644 --- a/contracts/modules/Experimental/Checkpoints/WeightedVoteCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpointFactory.sol @@ -1,28 +1,32 @@ pragma solidity ^0.5.0; -import "./WeightedVoteCheckpoint.sol"; -import "../../ModuleFactory.sol"; +import "./WeightedVoteCheckpointProxy.sol"; +import "../../../../libraries/Util.sol"; +import "../../../../interfaces/IBoot.sol"; +import "../../../UpgradableModuleFactory.sol"; /** * @title Factory for deploying WeightedVoteCheckpoint module */ -contract WeightedVoteCheckpointFactory is ModuleFactory { +contract WeightedVoteCheckpointFactory is UpgradableModuleFactory { /** * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module + * @param _logicContract Contract address that contains the logic related to `description` * @param _polymathRegistry Address of the Polymath registry * @param _isCostInPoly true = cost in Poly, false = USD */ constructor ( uint256 _setupCost, uint256 _usageCost, + address _logicContract, address _polymathRegistry, bool _isCostInPoly - ) + ) public - ModuleFactory(_setupCost, _usageCost, _polymathRegistry, _isCostInPoly) + UpgradableModuleFactory("3.0.0", _setupCost, _usageCost, _logicContract, _polymathRegistry, _isCostInPoly) { initialVersion = "3.0.0"; name = "WeightedVoteCheckpoint"; @@ -34,7 +38,6 @@ contract WeightedVoteCheckpointFactory is ModuleFactory { tagsData.push("Checkpoint"); compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(3), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(3), uint8(0), uint8(0)); - } /** @@ -42,9 +45,8 @@ contract WeightedVoteCheckpointFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes calldata _data) external returns(address) { - address weightedVoteCheckpoint = address(new WeightedVoteCheckpoint(msg.sender, IPolymathRegistry(polymathRegistry).getAddress("PolyToken"))); + address weightedVoteCheckpoint = address(new WeightedVoteCheckpointProxy(logicContracts[latestUpgrade].version, msg.sender, IPolymathRegistry(polymathRegistry).getAddress("PolyToken"), logicContracts[latestUpgrade].logicContract)); _initializeModule(weightedVoteCheckpoint, _data); return weightedVoteCheckpoint; } - } diff --git a/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpointProxy.sol b/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpointProxy.sol new file mode 100644 index 000000000..b926b0371 --- /dev/null +++ b/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpointProxy.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.5.0; + +import "../../../../Pausable.sol"; +import "./WeightedVoteCheckpointStorage.sol"; +import "../../../../storage/modules/ModuleStorage.sol"; +import "../../../../proxy/OwnedUpgradeabilityProxy.sol"; +import "../../../../storage/modules/Checkpoint/Voting/VotingCheckpointStorage.sol"; + +/** + * @title Voting module for governance + */ +contract WeightedVoteCheckpointProxy is WeightedVoteCheckpointStorage, VotingCheckpointStorage, ModuleStorage, Pausable, OwnedUpgradeabilityProxy { + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + * @param _implementation representing the address of the new implementation to be set + */ + constructor( + string memory _version, + address _securityToken, + address _polyAddress, + address _implementation + ) + public + ModuleStorage(_securityToken, _polyAddress) + { + require(_implementation != address(0), "Implementation address should not be 0x"); + _upgradeTo(_version, _implementation); + } + +} \ No newline at end of file diff --git a/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpointStorage.sol b/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpointStorage.sol new file mode 100644 index 000000000..776427102 --- /dev/null +++ b/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpointStorage.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.5.0; + +contract WeightedVoteCheckpointStorage { + + struct Ballot { + uint256 checkpointId; // Checkpoint At which ballot created + uint256 quorum; // Should be a multiple of 10 ** 16 + uint64 startTime; // Timestamp at which ballot will come into effect + uint64 endTime; // Timestamp at which ballot will no more into effect + uint64 totalProposals; // Count of proposals allowed for a given ballot + uint56 totalVoters; // Count of voters who vote for the given ballot + bool isActive; // flag used to turn off/on the ballot + mapping(uint256 => uint256) proposalToVotes; // Mapping for proposal to total weight collected by the proposal + mapping(address => uint256) investorToProposal; // mapping for storing vote details of a voter + mapping(address => bool) exemptedVoters; // Mapping for blacklist voters + } + + Ballot[] ballots; +} \ No newline at end of file diff --git a/contracts/modules/Experimental/Checkpoints/VotingCheckpoint.sol b/contracts/modules/Checkpoint/Voting/VotingCheckpoint.sol similarity index 89% rename from contracts/modules/Experimental/Checkpoints/VotingCheckpoint.sol rename to contracts/modules/Checkpoint/Voting/VotingCheckpoint.sol index ce33d2e71..30e8df3ee 100644 --- a/contracts/modules/Experimental/Checkpoints/VotingCheckpoint.sol +++ b/contracts/modules/Checkpoint/Voting/VotingCheckpoint.sol @@ -1,12 +1,11 @@ pragma solidity ^0.5.0; -import "./IVoting.sol"; +import "../../../interfaces/IVoting.sol"; import "../../Module.sol"; +import ".././ICheckpoint.sol"; +import "../../../storage/modules/Checkpoint/Voting/VotingCheckpointStorage.sol"; -contract VotingCheckpoint is IVoting, Module { - - mapping(address => uint256) defaultExemptIndex; - address[] defaultExemptedVoters; +contract VotingCheckpoint is VotingCheckpointStorage, ICheckpoint, IVoting, Module { event ChangedDefaultExemptedVotersList(address indexed _voter, bool _change); diff --git a/contracts/storage/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/storage/modules/Checkpoint/Dividend/DividendCheckpointStorage.sol similarity index 100% rename from contracts/storage/modules/Checkpoint/DividendCheckpointStorage.sol rename to contracts/storage/modules/Checkpoint/Dividend/DividendCheckpointStorage.sol diff --git a/contracts/storage/modules/Checkpoint/Voting/VotingCheckpointStorage.sol b/contracts/storage/modules/Checkpoint/Voting/VotingCheckpointStorage.sol new file mode 100644 index 000000000..868e9d4db --- /dev/null +++ b/contracts/storage/modules/Checkpoint/Voting/VotingCheckpointStorage.sol @@ -0,0 +1,8 @@ +pragma solidity ^0.5.0; + +contract VotingCheckpointStorage { + + mapping(address => uint256) defaultExemptIndex; + address[] defaultExemptedVoters; + +} \ No newline at end of file diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index fecfb2216..206d8648e 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -52,6 +52,8 @@ const VestingEscrowWalletFactory = artifacts.require("./VestingEscrowWalletFacto const VestingEscrowWallet = artifacts.require("./VestingEscrowWallet.sol"); const PLCRVotingCheckpointFactory = artifacts.require("./PLCRVotingCheckpointFactory.sol"); const WeightedVoteCheckpointFactory = artifacts.require("./WeightedVoteCheckpointFactory.sol"); +const PLCRVotingCheckpoint = artifacts.require("./PLCRVotingCheckpoint.sol"); +const WeightedVoteCheckpoint = artifacts.require("./WeightedVoteCheckpoint.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -112,6 +114,8 @@ let I_USDOracle; let I_POLYOracle; let I_StablePOLYOracle; let I_PLCRVotingCheckpointFactory; +let I_WeightedVoteCheckpointLogic; +let I_PLCRVotingCheckpointLogic; // Initial fee for ticker registry and security token registry const initRegFee = new BN(web3.utils.toWei("250")); @@ -612,21 +616,23 @@ export async function deploySignedTMAndVerifyed(accountPolymath, MRProxyInstance // Deploy voting modules -export async function deployPLCRVoteCheckpoint(accountPolymath, MRProxyInstance, setupCost) { - I_PLCRVotingCheckpointFactory = await PLCRVotingCheckpointFactory.new(setupCost, new BN(0), I_PolymathRegistry.address, { from: accountPolymath }); +export async function deployPLCRVoteCheckpoint(accountPolymath, MRProxyInstance, setupCost, feeInPoly = false) { + I_PLCRVotingCheckpointLogic = await PLCRVotingCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_PLCRVotingCheckpointFactory = await PLCRVotingCheckpointFactory.new(setupCost, new BN(0), I_PLCRVotingCheckpointLogic.address, I_PolymathRegistry.address, feeInPoly, { from: accountPolymath }); assert.notEqual( I_PLCRVotingCheckpointFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", "PLCRVotingCheckpointFactory contract was not deployed" ); - await registerAndVerifyByMR(I_PLCRVotingCheckpointFactory.address, accountPolymath, MRProxyInstance); + await registerAndVerifyByMR(I_PLCRVotingCheckpointFactory.address, accountPolymath, MRProxyInstance); return new Array(I_PLCRVotingCheckpointFactory); } // Deploy the voting modules -export async function deployWeightedVoteCheckpoint(accountPolymath, MRProxyInstance, setupCost) { - I_WeightedVoteCheckpointFactory = await WeightedVoteCheckpointFactory.new(setupCost, new BN(0), I_PolymathRegistry.address, { from: accountPolymath }); +export async function deployWeightedVoteCheckpoint(accountPolymath, MRProxyInstance, setupCost, feeInPoly = false) { + I_WeightedVoteCheckpointLogic = await WeightedVoteCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_WeightedVoteCheckpointFactory = await WeightedVoteCheckpointFactory.new(setupCost, new BN(0), I_WeightedVoteCheckpointLogic.address, I_PolymathRegistry.address, feeInPoly, { from: accountPolymath }); assert.notEqual( I_WeightedVoteCheckpointFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", diff --git a/test/zd_weighted_vote_checkpoint.js b/test/zd_weighted_vote_checkpoint.js index 62005e720..a8513855c 100644 --- a/test/zd_weighted_vote_checkpoint.js +++ b/test/zd_weighted_vote_checkpoint.js @@ -247,7 +247,7 @@ contract("WeightedVoteCheckpoint", async (accounts) => { }); it("\t\t Should create the ballot successfully \n", async() => { - let tx = await I_WeightedVoteCheckpoint.createBallot(new BN(duration.days(5)), new BN(3), new BN(51).mul(new BN(10).pow(new BN(17))), {from: token_owner}); + let tx = await I_WeightedVoteCheckpoint.createBallot(new BN(duration.days(5)), new BN(3), new BN(51).mul(new BN(10).pow(new BN(16))), {from: token_owner}); assert.equal((tx.logs[0].args._noOfProposals).toString(), 3); assert.equal((tx.logs[0].args._checkpointId).toString(), 1); assert.equal((tx.logs[0].args._ballotId).toString(), 0); @@ -287,110 +287,110 @@ contract("WeightedVoteCheckpoint", async (accounts) => { assert.equal(data[6], true); }); - it("\t\t Should successfully vote by account investor2 \n", async() => { - let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}); - assert.equal(tx.logs[0].args._ballotId, 0); - assert.equal(tx.logs[0].args._proposalId, 2); - assert.equal(tx.logs[0].args._investor, account_investor2); + // it("\t\t Should successfully vote by account investor2 \n", async() => { + // let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}); + // assert.equal(tx.logs[0].args._ballotId, 0); + // assert.equal(tx.logs[0].args._proposalId, 2); + // assert.equal(tx.logs[0].args._investor, account_investor2); - let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); - assert.equal(data[4], 2); - assert.equal(data[5], 3); - assert.equal(data[6], true); - }); - - it("\t\t Should fail to vote again \n", async() => { - await catchRevert( - I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}) - ); - }); - - it("\t\t Should add the voter in to the ballot exemption list", async() => { - - }); - - it("\t\t Should fail to change the ballot status-- bad owner \n", async() => { - await catchRevert( - I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: account_polymath}) - ); - }); - - it("\t\t Should fail to change the ballot status-- no change in the state \n", async() => { - await catchRevert( - I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), true, {from: account_polymath}) - ); - }); - - it("\t\t Should change the status of the ballot with the help of changeBallotStatus \n", async() => { - let tx = await I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: token_owner}); - assert.equal(tx.logs[0].args._ballotId, 0); - assert.equal(tx.logs[0].args._isActive, false); - }); - - it("\t\t Should fail to vote because ballot is disabled \n", async() => { - await catchRevert( - I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor3}) - ); - }); - - it("\t\t Should turn on the ballot \n", async() => { - let tx = await I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), true, {from: token_owner}); - assert.equal(tx.logs[0].args._ballotId, 0); - assert.equal(tx.logs[0].args._isActive, true); - }); - - it("\t\t Should successfully vote \n", async() => { - let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(1), {from: account_investor3}); - assert.equal(tx.logs[0].args._ballotId, 0); - assert.equal(tx.logs[0].args._proposalId, 1); - assert.equal(tx.logs[0].args._investor, account_investor3); + // let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); + // assert.equal(data[4], 2); + // assert.equal(data[5], 3); + // assert.equal(data[6], true); + // }); + + // it("\t\t Should fail to vote again \n", async() => { + // await catchRevert( + // I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}) + // ); + // }); + + // it("\t\t Should add the voter in to the ballot exemption list", async() => { + + // }); + + // it("\t\t Should fail to change the ballot status-- bad owner \n", async() => { + // await catchRevert( + // I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: account_polymath}) + // ); + // }); + + // it("\t\t Should fail to change the ballot status-- no change in the state \n", async() => { + // await catchRevert( + // I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), true, {from: account_polymath}) + // ); + // }); + + // it("\t\t Should change the status of the ballot with the help of changeBallotStatus \n", async() => { + // let tx = await I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: token_owner}); + // assert.equal(tx.logs[0].args._ballotId, 0); + // assert.equal(tx.logs[0].args._isActive, false); + // }); + + // it("\t\t Should fail to vote because ballot is disabled \n", async() => { + // await catchRevert( + // I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor3}) + // ); + // }); + + // it("\t\t Should turn on the ballot \n", async() => { + // let tx = await I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), true, {from: token_owner}); + // assert.equal(tx.logs[0].args._ballotId, 0); + // assert.equal(tx.logs[0].args._isActive, true); + // }); + + // it("\t\t Should successfully vote \n", async() => { + // let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(1), {from: account_investor3}); + // assert.equal(tx.logs[0].args._ballotId, 0); + // assert.equal(tx.logs[0].args._proposalId, 1); + // assert.equal(tx.logs[0].args._investor, account_investor3); - let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); - assert.equal(data[4], 3); - assert.equal(data[5], 3); - assert.equal(data[6], true); - }); - - it("\t\t Should fail to vote when the duration of vote is complete \n", async() => { - await increaseTime(duration.days(6)); - - // transfer some funds to account_investor4 - await I_SecurityToken.issue( - account_investor4, - new BN(web3.utils.toWei("500")), - "0x0", - { - from: token_owner - } - ); - await catchRevert( - I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor4}) - ); - }); - - it("\t\t Should fail to change the status of the ballot -- already ended \n", async() => { - await catchRevert( - I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: token_owner}) - ); - }); - - it("\t\t Should check who votes whom \n", async() => { - assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor1)).toString(), 1); - assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor2)).toString(), 2); - assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor3)).toString(), 1); - }); - - it("\t\t Should get the result of the ballot \n", async() => { - let data = await I_WeightedVoteCheckpoint.getBallotResults.call(new BN(0)); - assert.equal(data[4], 3); - assert.equal(web3.utils.fromWei((data[0][0]).toString()), 5500); - assert.equal(web3.utils.fromWei((data[0][1]).toString()), 1000); - assert.equal(data[2], 1); - assert.equal(data[3], 0); - }); + // let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); + // assert.equal(data[4], 3); + // assert.equal(data[5], 3); + // assert.equal(data[6], true); + // }); + + // it("\t\t Should fail to vote when the duration of vote is complete \n", async() => { + // await increaseTime(duration.days(6)); + + // // transfer some funds to account_investor4 + // await I_SecurityToken.issue( + // account_investor4, + // new BN(web3.utils.toWei("500")), + // "0x0", + // { + // from: token_owner + // } + // ); + // await catchRevert( + // I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor4}) + // ); + // }); + + // it("\t\t Should fail to change the status of the ballot -- already ended \n", async() => { + // await catchRevert( + // I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: token_owner}) + // ); + // }); + + // it("\t\t Should check who votes whom \n", async() => { + // assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor1)).toString(), 1); + // assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor2)).toString(), 2); + // assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor3)).toString(), 1); + // }); + + // it("\t\t Should get the result of the ballot \n", async() => { + // let data = await I_WeightedVoteCheckpoint.getBallotResults.call(new BN(0)); + // assert.equal(data[4], 3); + // assert.equal(web3.utils.fromWei((data[0][0]).toString()), 5500); + // assert.equal(web3.utils.fromWei((data[0][1]).toString()), 1000); + // assert.equal(data[2], 1); + // assert.equal(data[3], 0); + // }); }); - describe("\t\t General function test \n", async() => { + describe.skip("\t\t General function test \n", async() => { it("\t\t Should check the permission \n", async() => { let data = await I_WeightedVoteCheckpoint.getPermissions.call(); @@ -402,7 +402,7 @@ contract("WeightedVoteCheckpoint", async (accounts) => { }); }); - describe("\t\t Factory test cases \n", async() => { + describe.skip("\t\t Factory test cases \n", async() => { it("\t\t Should get the exact details of the factory \n", async () => { assert.equal((await I_WeightedVoteCheckpointFactory.setupCost.call()).toNumber(), 0); assert.equal((await I_WeightedVoteCheckpointFactory.types.call())[0], 4); From 40b95eb68aaac4394c6246bd4a70ed1221a20752 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 12 Apr 2019 19:03:17 +0530 Subject: [PATCH 4/7] fix test for weighted vote module --- test/zd_weighted_vote_checkpoint.js | 181 ++++++++++++++-------------- 1 file changed, 91 insertions(+), 90 deletions(-) diff --git a/test/zd_weighted_vote_checkpoint.js b/test/zd_weighted_vote_checkpoint.js index a8513855c..6e145a13a 100644 --- a/test/zd_weighted_vote_checkpoint.js +++ b/test/zd_weighted_vote_checkpoint.js @@ -278,119 +278,120 @@ contract("WeightedVoteCheckpoint", async (accounts) => { let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(1), {from: account_investor1}); assert.equal(tx.logs[0].args._ballotId, 0); assert.equal(tx.logs[0].args._proposalId, 1); - assert.equal(tx.logs[0].args._investor, account_investor1); + assert.equal(tx.logs[0].args._voter, account_investor1); let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); - console.log(data); - assert.equal(data[4], 1); + assert.equal(data[6], 1); assert.equal(data[5], 3); - assert.equal(data[6], true); + assert.equal(data[7], true); }); - // it("\t\t Should successfully vote by account investor2 \n", async() => { - // let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}); - // assert.equal(tx.logs[0].args._ballotId, 0); - // assert.equal(tx.logs[0].args._proposalId, 2); - // assert.equal(tx.logs[0].args._investor, account_investor2); + it("\t\t Should successfully vote by account investor2 \n", async() => { + let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}); + assert.equal(tx.logs[0].args._ballotId, 0); + assert.equal(tx.logs[0].args._proposalId, 2); + assert.equal(tx.logs[0].args._voter, account_investor2); - // let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); - // assert.equal(data[4], 2); - // assert.equal(data[5], 3); - // assert.equal(data[6], true); - // }); + let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); + assert.equal(data[6], 2); + assert.equal(data[5], 3); + assert.equal(data[7], true); + }); - // it("\t\t Should fail to vote again \n", async() => { - // await catchRevert( - // I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}) - // ); - // }); + it("\t\t Should fail to vote again \n", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}) + ); + }); // it("\t\t Should add the voter in to the ballot exemption list", async() => { // }); - // it("\t\t Should fail to change the ballot status-- bad owner \n", async() => { - // await catchRevert( - // I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: account_polymath}) - // ); - // }); + it("\t\t Should fail to change the ballot status-- bad owner \n", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: account_polymath}) + ); + }); - // it("\t\t Should fail to change the ballot status-- no change in the state \n", async() => { - // await catchRevert( - // I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), true, {from: account_polymath}) - // ); - // }); + it("\t\t Should fail to change the ballot status-- no change in the state \n", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), true, {from: account_polymath}) + ); + }); - // it("\t\t Should change the status of the ballot with the help of changeBallotStatus \n", async() => { - // let tx = await I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: token_owner}); - // assert.equal(tx.logs[0].args._ballotId, 0); - // assert.equal(tx.logs[0].args._isActive, false); - // }); + it("\t\t Should change the status of the ballot with the help of changeBallotStatus \n", async() => { + let tx = await I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: token_owner}); + assert.equal(tx.logs[0].args._ballotId, 0); + assert.equal(tx.logs[0].args._isActive, false); + }); - // it("\t\t Should fail to vote because ballot is disabled \n", async() => { - // await catchRevert( - // I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor3}) - // ); - // }); + it("\t\t Should fail to vote because ballot is disabled \n", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor3}) + ); + }); - // it("\t\t Should turn on the ballot \n", async() => { - // let tx = await I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), true, {from: token_owner}); - // assert.equal(tx.logs[0].args._ballotId, 0); - // assert.equal(tx.logs[0].args._isActive, true); - // }); + it("\t\t Should turn on the ballot \n", async() => { + let tx = await I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), true, {from: token_owner}); + assert.equal(tx.logs[0].args._ballotId, 0); + assert.equal(tx.logs[0].args._isActive, true); + }); - // it("\t\t Should successfully vote \n", async() => { - // let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(1), {from: account_investor3}); - // assert.equal(tx.logs[0].args._ballotId, 0); - // assert.equal(tx.logs[0].args._proposalId, 1); - // assert.equal(tx.logs[0].args._investor, account_investor3); + it("\t\t Should successfully vote \n", async() => { + let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(1), {from: account_investor3}); + assert.equal(tx.logs[0].args._ballotId, 0); + assert.equal(tx.logs[0].args._proposalId, 1); + assert.equal(tx.logs[0].args._voter, account_investor3); - // let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); - // assert.equal(data[4], 3); - // assert.equal(data[5], 3); - // assert.equal(data[6], true); - // }); + let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); + console.log(data); + assert.equal(data[6], 3); + assert.equal(data[5], 3); + assert.equal(data[7], true); + }); - // it("\t\t Should fail to vote when the duration of vote is complete \n", async() => { - // await increaseTime(duration.days(6)); - - // // transfer some funds to account_investor4 - // await I_SecurityToken.issue( - // account_investor4, - // new BN(web3.utils.toWei("500")), - // "0x0", - // { - // from: token_owner - // } - // ); - // await catchRevert( - // I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor4}) - // ); - // }); + it("\t\t Should fail to vote when the duration of vote is complete \n", async() => { + await increaseTime(duration.days(6)); - // it("\t\t Should fail to change the status of the ballot -- already ended \n", async() => { - // await catchRevert( - // I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: token_owner}) - // ); - // }); + // transfer some funds to account_investor4 + await I_SecurityToken.issue( + account_investor4, + new BN(web3.utils.toWei("500")), + "0x0", + { + from: token_owner + } + ); + await catchRevert( + I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor4}) + ); + }); - // it("\t\t Should check who votes whom \n", async() => { - // assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor1)).toString(), 1); - // assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor2)).toString(), 2); - // assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor3)).toString(), 1); - // }); + it("\t\t Should fail to change the status of the ballot -- already ended \n", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: token_owner}) + ); + }); - // it("\t\t Should get the result of the ballot \n", async() => { - // let data = await I_WeightedVoteCheckpoint.getBallotResults.call(new BN(0)); - // assert.equal(data[4], 3); - // assert.equal(web3.utils.fromWei((data[0][0]).toString()), 5500); - // assert.equal(web3.utils.fromWei((data[0][1]).toString()), 1000); - // assert.equal(data[2], 1); - // assert.equal(data[3], 0); - // }); + it("\t\t Should check who votes whom \n", async() => { + assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor1)).toString(), 1); + assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor2)).toString(), 2); + assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor3)).toString(), 1); + }); + + it("\t\t Should get the result of the ballot \n", async() => { + let data = await I_WeightedVoteCheckpoint.getBallotResults.call(new BN(0)); + console.log(data); + assert.equal(data[4], 3); + assert.equal(web3.utils.fromWei((data[0][0]).toString()), 5500); + assert.equal(web3.utils.fromWei((data[0][1]).toString()), 1000); + assert.equal(data[2], 1); + assert.isTrue(data[3]); + }); }); - describe.skip("\t\t General function test \n", async() => { + describe("\t\t General function test \n", async() => { it("\t\t Should check the permission \n", async() => { let data = await I_WeightedVoteCheckpoint.getPermissions.call(); @@ -402,7 +403,7 @@ contract("WeightedVoteCheckpoint", async (accounts) => { }); }); - describe.skip("\t\t Factory test cases \n", async() => { + describe("\t\t Factory test cases \n", async() => { it("\t\t Should get the exact details of the factory \n", async () => { assert.equal((await I_WeightedVoteCheckpointFactory.setupCost.call()).toNumber(), 0); assert.equal((await I_WeightedVoteCheckpointFactory.types.call())[0], 4); From 1c828f852ba5670cc499cb276c36e46ea1e694e9 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 12 Apr 2019 20:57:43 +0530 Subject: [PATCH 5/7] add more tests --- .../Voting/PLCR/PLCRVotingCheckpoint.sol | 2 +- .../Transparent/WeightedVoteCheckpoint.sol | 2 +- .../Checkpoint/Voting/VotingCheckpoint.sol | 6 +- test/zc_plcr_voting_checkpoint.js | 107 +++++++++++++++--- test/zd_weighted_vote_checkpoint.js | 91 +++++++++++++-- 5 files changed, 175 insertions(+), 33 deletions(-) diff --git a/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpoint.sol b/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpoint.sol index 8d5a069c4..a08677222 100644 --- a/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpoint.sol +++ b/contracts/modules/Checkpoint/Voting/PLCR/PLCRVotingCheckpoint.sol @@ -27,7 +27,7 @@ contract PLCRVotingCheckpoint is PLCRVotingCheckpointStorage, VotingCheckpoint { uint256 _proposedQuorum ); event BallotStatusChanged(uint256 indexed _ballotId, bool _newStatus); - event ChangedBallotExemptedVotersList(uint256 indexed _ballotId, address indexed_voter, bool _change); + event ChangedBallotExemptedVotersList(uint256 indexed _ballotId, address indexed _voter, bool _change); constructor(address _securityToken, address _polyAddress) public diff --git a/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpoint.sol b/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpoint.sol index 2ccd96bd3..04a1b7828 100644 --- a/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpoint.sol +++ b/contracts/modules/Checkpoint/Voting/Transparent/WeightedVoteCheckpoint.sol @@ -23,7 +23,7 @@ contract WeightedVoteCheckpoint is WeightedVoteCheckpointStorage, VotingCheckpoi ); event VoteCast(address indexed _voter, uint256 _weight, uint256 indexed _ballotId, uint256 indexed _proposalId); event BallotStatusChanged(uint256 indexed _ballotId, bool _isActive); - event ChangedBallotExemptedVotersList(uint256 indexed _ballotId, address indexed_voter, bool _change); + event ChangedBallotExemptedVotersList(uint256 indexed _ballotId, address indexed _voter, bool _change); /** * @notice Constructor diff --git a/contracts/modules/Checkpoint/Voting/VotingCheckpoint.sol b/contracts/modules/Checkpoint/Voting/VotingCheckpoint.sol index 30e8df3ee..77ae226ea 100644 --- a/contracts/modules/Checkpoint/Voting/VotingCheckpoint.sol +++ b/contracts/modules/Checkpoint/Voting/VotingCheckpoint.sol @@ -37,8 +37,10 @@ contract VotingCheckpoint is VotingCheckpointStorage, ICheckpoint, IVoting, Modu defaultExemptedVoters.push(_voter); defaultExemptIndex[_voter] = defaultExemptedVoters.length; } else { - defaultExemptedVoters[defaultExemptIndex[_voter] - 1] = defaultExemptedVoters[defaultExemptedVoters.length - 1]; - defaultExemptIndex[defaultExemptedVoters[defaultExemptIndex[_voter] - 1]] = defaultExemptIndex[_voter]; + if (defaultExemptedVoters.length != defaultExemptIndex[_voter]) { + defaultExemptedVoters[defaultExemptIndex[_voter] - 1] = defaultExemptedVoters[defaultExemptedVoters.length - 1]; + defaultExemptIndex[defaultExemptedVoters[defaultExemptIndex[_voter] - 1]] = defaultExemptIndex[_voter]; + } delete defaultExemptIndex[_voter]; defaultExemptedVoters.length --; } diff --git a/test/zc_plcr_voting_checkpoint.js b/test/zc_plcr_voting_checkpoint.js index d96c572e9..d6e10c055 100644 --- a/test/zc_plcr_voting_checkpoint.js +++ b/test/zc_plcr_voting_checkpoint.js @@ -86,23 +86,23 @@ contract("PLCRVotingCheckpoint", async (accounts) => { // ----------- POLYMATH NETWORK Configuration ------------ // Step 1: Deploy the genral PM ecosystem - let instances = await setUpPolymathNetwork(account_polymath, token_owner); - - [ - I_PolymathRegistry, - I_PolyToken, - I_FeatureRegistry, - I_ModuleRegistry, - I_ModuleRegistryProxy, - I_MRProxied, - I_GeneralTransferManagerFactory, - I_STFactory, - I_SecurityTokenRegistry, - I_SecurityTokenRegistryProxy, - I_STRProxied, - I_STRGetter, - I_STGetter - ] = instances; + let instances = await setUpPolymathNetwork(account_polymath, token_owner); + + [ + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied, + I_STRGetter, + I_STGetter + ] = instances; // STEP 4: Deploy the WeightedVoteCheckpoint @@ -332,6 +332,49 @@ contract("PLCRVotingCheckpoint", async (accounts) => { assert.isTrue(data[7]); }); + it("\t\t Should fail to add voter in ballot exemption list -- address is zero", async() => { + await catchRevert( + I_PLCRVotingCheckpoint.changeBallotExemptedVotersList(new BN(0), "0x0000000000000000000000000000000000000000", true, {from: token_owner}) + ); + }); + + it("\t\t Should fail to add voter in ballot exemption list -- invalid ballot id", async() => { + await catchRevert( + I_PLCRVotingCheckpoint.changeBallotExemptedVotersList(new BN(5), account_investor1, true, {from: token_owner}) + ); + }); + + it("\t\t Should add the voter in to the ballot exemption list", async() => { + let tx = await I_PLCRVotingCheckpoint.changeBallotExemptedVotersList(new BN(0), account_investor1, true, {from: token_owner}); + assert.equal((tx.logs[0].args._ballotId).toString(), 0); + assert.equal(tx.logs[0].args._voter, account_investor1); + assert.equal(tx.logs[0].args._change, true); + }); + + it("\t\t Should fail to add voter in ballot exemption list -- doing the same change again", async() => { + await catchRevert( + I_PLCRVotingCheckpoint.changeBallotExemptedVotersList(new BN(0), account_investor1, true, {from: token_owner}) + ); + }); + + it("\t\t Should fail to vote -- voter is present in the exemption list", async() => { + let salt = getRandom(); + await catchRevert( + I_PLCRVotingCheckpoint.commitVote(new BN(0), web3.utils.soliditySha3(2, salt), {from: account_investor1}) + ); + }); + + it("\t\t Should add the multiple voter in to the ballot exemption list -- failed ", async() => { + await catchRevert( + I_PLCRVotingCheckpoint.changeBallotExemptedVotersListMulti(new BN(0), [account_investor1, account_investor2], [false], {from: token_owner}) + ); + }); + + it("\t\t Should add the multiple voter in to the ballot exemption list", async() => { + await I_PLCRVotingCheckpoint.changeBallotExemptedVotersListMulti(new BN(0), [account_investor1], [false], {from: token_owner}); + assert.isTrue(await I_PLCRVotingCheckpoint.isVoterAllowed.call(new BN(0), account_investor1)); + }); + it("\t\t Should successfully vote by account investor1 \n", async() => { let salt = getRandom(); saltArray.push(salt); @@ -352,6 +395,36 @@ contract("PLCRVotingCheckpoint", async (accounts) => { ) }); + it("\t\t Should fail to add voter in default exemption list -- address is zero", async() => { + await catchRevert( + I_PLCRVotingCheckpoint.changeDefaultExemptedVotersList("0x0000000000000000000000000000000000000000", true, {from: token_owner}) + ); + }); + + it("\t\t Should add the voter in to the default exemption list", async() => { + let tx = await I_PLCRVotingCheckpoint.changeDefaultExemptedVotersList(account_investor3, true, {from: token_owner}); + assert.equal(tx.logs[0].args._voter, account_investor3); + assert.equal(tx.logs[0].args._change, true); + }); + + it("\t\t Should fail to add voter in default exemption list -- doing the same change again", async() => { + await catchRevert( + I_PLCRVotingCheckpoint.changeDefaultExemptedVotersList(account_investor3, true, {from: token_owner}) + ); + }); + + it("\t\t Should fail to vote -- voter is present in the exemption list", async() => { + let salt = getRandom(); + await catchRevert( + I_PLCRVotingCheckpoint.commitVote(new BN(0), web3.utils.soliditySha3(1, salt), {from: account_investor3}) + ); + }); + + it("\t\t Should change the default exemption list by allowing investor 1 to vote", async() => { + await I_PLCRVotingCheckpoint.changeDefaultExemptedVotersList(account_investor3, false, {from: token_owner}); + assert.isTrue(await I_PLCRVotingCheckpoint.isVoterAllowed.call(new BN(0), account_investor3)); + }); + it("\t\t Should successfully vote by account investor3 \n", async() => { let salt = getRandom(); saltArray.push(salt); diff --git a/test/zd_weighted_vote_checkpoint.js b/test/zd_weighted_vote_checkpoint.js index 6e145a13a..f2e8f78c1 100644 --- a/test/zd_weighted_vote_checkpoint.js +++ b/test/zd_weighted_vote_checkpoint.js @@ -274,11 +274,53 @@ contract("WeightedVoteCheckpoint", async (accounts) => { ); }); - it("\t\t Should successfully vote by account investor1 \n", async() => { - let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(1), {from: account_investor1}); + it("\t\t Should fail to add voter in ballot exemption list -- address is zero", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.changeBallotExemptedVotersList(new BN(0), "0x0000000000000000000000000000000000000000", true, {from: token_owner}) + ); + }); + + it("\t\t Should fail to add voter in ballot exemption list -- invalid ballot id", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.changeBallotExemptedVotersList(new BN(5), account_investor2, true, {from: token_owner}) + ); + }); + + it("\t\t Should add the voter in to the ballot exemption list", async() => { + let tx = await I_WeightedVoteCheckpoint.changeBallotExemptedVotersList(new BN(0), account_investor2, true, {from: token_owner}); + assert.equal((tx.logs[0].args._ballotId).toString(), 0); + assert.equal(tx.logs[0].args._voter, account_investor2); + assert.equal(tx.logs[0].args._change, true); + }); + + it("\t\t Should fail to add voter in ballot exemption list -- doing the same change again", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.changeBallotExemptedVotersList(new BN(0), account_investor2, true, {from: token_owner}) + ); + }); + + it("\t\t Should fail to vote -- voter is present in the exemption list", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}) + ); + }); + + it("\t\t Should add the multiple voter in to the ballot exemption list -- failed ", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.changeBallotExemptedVotersListMulti(new BN(0), [account_investor2, account_investor1], [false], {from: token_owner}) + ); + }); + + it("\t\t Should add the multiple voter in to the ballot exemption list", async() => { + await I_WeightedVoteCheckpoint.changeBallotExemptedVotersListMulti(new BN(0), [account_investor2], [false], {from: token_owner}); + assert.isTrue(await I_WeightedVoteCheckpoint.isVoterAllowed.call(new BN(0), account_investor2)); + }); + + it("\t\t Should successfully vote by account investor2 \n", async() => { + let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}); assert.equal(tx.logs[0].args._ballotId, 0); - assert.equal(tx.logs[0].args._proposalId, 1); - assert.equal(tx.logs[0].args._voter, account_investor1); + assert.equal(tx.logs[0].args._proposalId, 2); + assert.equal(tx.logs[0].args._voter, account_investor2); let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); assert.equal(data[6], 1); @@ -286,11 +328,40 @@ contract("WeightedVoteCheckpoint", async (accounts) => { assert.equal(data[7], true); }); - it("\t\t Should successfully vote by account investor2 \n", async() => { - let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(2), {from: account_investor2}); + it("\t\t Should fail to add voter in default exemption list -- address is zero", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.changeDefaultExemptedVotersList("0x0000000000000000000000000000000000000000", true, {from: token_owner}) + ); + }); + + it("\t\t Should add the voter in to the default exemption list", async() => { + let tx = await I_WeightedVoteCheckpoint.changeDefaultExemptedVotersList(account_investor1, true, {from: token_owner}); + assert.equal(tx.logs[0].args._voter, account_investor1); + assert.equal(tx.logs[0].args._change, true); + }); + + it("\t\t Should fail to add voter in default exemption list -- doing the same change again", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.changeDefaultExemptedVotersList(account_investor1, true, {from: token_owner}) + ); + }); + + it("\t\t Should fail to vote -- voter is present in the exemption list", async() => { + await catchRevert( + I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(1), {from: account_investor1}) + ); + }); + + it("\t\t Should change the default exemption list by allowing investor 1 to vote", async() => { + await I_WeightedVoteCheckpoint.changeDefaultExemptedVotersList(account_investor1, false, {from: token_owner}); + assert.isTrue(await I_WeightedVoteCheckpoint.isVoterAllowed.call(new BN(0), account_investor1)); + }); + + it("\t\t Should successfully vote by account investor1 \n", async() => { + let tx = await I_WeightedVoteCheckpoint.castVote(new BN(0), new BN(1), {from: account_investor1}); assert.equal(tx.logs[0].args._ballotId, 0); - assert.equal(tx.logs[0].args._proposalId, 2); - assert.equal(tx.logs[0].args._voter, account_investor2); + assert.equal(tx.logs[0].args._proposalId, 1); + assert.equal(tx.logs[0].args._voter, account_investor1); let data = await I_WeightedVoteCheckpoint.getBallotDetails.call(new BN(0)); assert.equal(data[6], 2); @@ -304,10 +375,6 @@ contract("WeightedVoteCheckpoint", async (accounts) => { ); }); - // it("\t\t Should add the voter in to the ballot exemption list", async() => { - - // }); - it("\t\t Should fail to change the ballot status-- bad owner \n", async() => { await catchRevert( I_WeightedVoteCheckpoint.changeBallotStatus(new BN(0), false, {from: account_polymath}) From 40365dc8104558804b34c8917b1eb3b22f46322e Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 15 Apr 2019 12:06:36 +0530 Subject: [PATCH 6/7] increase test coverage --- test/zc_plcr_voting_checkpoint.js | 39 ++++++++++++++++++++++++++--- test/zd_weighted_vote_checkpoint.js | 32 ++++++++++++++++++++++- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/test/zc_plcr_voting_checkpoint.js b/test/zc_plcr_voting_checkpoint.js index d6e10c055..e4d90112e 100644 --- a/test/zc_plcr_voting_checkpoint.js +++ b/test/zc_plcr_voting_checkpoint.js @@ -205,25 +205,37 @@ contract("PLCRVotingCheckpoint", async (accounts) => { it("\t\t Should fail to create ballot -- bad commit duration \n", async() => { await catchRevert( - I_PLCRVotingCheckpoint.createBallot(new BN(0), new BN(duration.days(10)), new BN(3), new BN(46.57).mul(new BN(10).pow(new BN(16))), {from: account_polymath}) + I_PLCRVotingCheckpoint.createBallot(new BN(0), new BN(duration.days(10)), new BN(3), new BN(46.57).mul(new BN(10).pow(new BN(16))), {from: token_owner}) ); }); it("\t\t Should fail to create ballot -- bad reveal duration \n", async() => { await catchRevert( - I_PLCRVotingCheckpoint.createBallot(new BN(duration.days(10)), new BN(0), new BN(3), new BN(46.57).mul(new BN(10).pow(new BN(16))), {from: account_polymath}) + I_PLCRVotingCheckpoint.createBallot(new BN(duration.days(10)), new BN(0), new BN(3), new BN(46.57).mul(new BN(10).pow(new BN(16))), {from: token_owner}) ); }); it("\t\t Should fail to create ballot -- bad proposed quorum \n", async() => { await catchRevert( - I_PLCRVotingCheckpoint.createBallot(new BN(duration.days(10)), new BN(duration.days(10)), new BN(3), new BN(46.57).mul(new BN(10).pow(new BN(16))), {from: account_polymath}) + I_PLCRVotingCheckpoint.createBallot(new BN(duration.days(10)), new BN(duration.days(10)), new BN(3), new BN(0).mul(new BN(10).pow(new BN(16))), {from: token_owner}) + ); + }); + + it("\t\t Should fail to create ballot -- bad proposed quorum more than 100 % \n", async() => { + await catchRevert( + I_PLCRVotingCheckpoint.createBallot(new BN(duration.days(10)), new BN(duration.days(10)), new BN(3), new BN(46.57).mul(new BN(10).pow(new BN(18))), {from: token_owner}) + ); + }); + + it("\t\t Should fail to create ballot -- bad no of proposals \n", async() => { + await catchRevert( + I_PLCRVotingCheckpoint.createBallot(new BN(duration.days(5)), new BN(duration.days(10)), new BN(0), new BN(46.57).mul(new BN(10).pow(new BN(16))), {from: token_owner}) ); }); it("\t\t Should fail to create ballot -- bad no of proposals \n", async() => { await catchRevert( - I_PLCRVotingCheckpoint.createBallot(new BN(duration.days(5)), new BN(duration.days(10)), new BN(0), new BN(46.57).mul(new BN(10).pow(new BN(16))), {from: account_polymath}) + I_PLCRVotingCheckpoint.createBallot(new BN(duration.days(5)), new BN(duration.days(10)), new BN(1), new BN(46.57).mul(new BN(10).pow(new BN(16))), {from: token_owner}) ); }); @@ -285,6 +297,9 @@ contract("PLCRVotingCheckpoint", async (accounts) => { await I_SecurityToken.createCheckpoint({from: token_owner}); let checkpointId = await I_SecurityToken.currentCheckpointId.call(); let tx = await I_PLCRVotingCheckpoint.createCustomBallot(commitTime, revealTime, new BN(3), new BN(47.8).mul(new BN(10).pow(new BN(16))), checkpointId, startTime, {from: account_delegate}); + let timeData = await I_PLCRVotingCheckpoint.getBallotCommitRevealDuration.call(new BN(0)); + assert.equal(timeData[0].toString(), commitTime); + assert.equal(timeData[1].toString(), revealTime); assert.equal((tx.logs[0].args._noOfProposals).toString(), 3); assert.equal((tx.logs[0].args._checkpointId).toString(), 1); assert.equal((tx.logs[0].args._ballotId).toString(), 0); @@ -519,6 +534,12 @@ contract("PLCRVotingCheckpoint", async (accounts) => { ); }); + it("\t\t Should fail to reveal vote -- Invalid salt \n", async() => { + await catchRevert( + I_PLCRVotingCheckpoint.revealVote(new BN(0), new BN(1), getRandom(), {from: account_investor3}) + ); + }); + it("\t\t Should successfully reveal the vote by investor 3 \n", async() => { let tx = await I_PLCRVotingCheckpoint.revealVote(new BN(0), new BN(1), saltArray[1], {from: account_investor3}); assert.equal(tx.logs[0].args._voter, account_investor3); @@ -592,6 +613,9 @@ contract("PLCRVotingCheckpoint", async (accounts) => { }); it("\t\t Should check who votes whom \n", async() => { + // If we give Invalid ballot id, This function will always return 0 + assert.equal(((await I_PLCRVotingCheckpoint.getSelectedProposal.call(new BN(5), account_investor1))).toString(), 0); + assert.equal(((await I_PLCRVotingCheckpoint.getSelectedProposal.call(new BN(0), account_investor1))).toString(), 2); assert.equal(((await I_PLCRVotingCheckpoint.getSelectedProposal.call(new BN(0), account_investor2))).toString(), 0); assert.equal(((await I_PLCRVotingCheckpoint.getSelectedProposal.call(new BN(0), account_investor3))).toString(), 1); @@ -615,6 +639,13 @@ contract("PLCRVotingCheckpoint", async (accounts) => { assert.isTrue(data[3]); assert.equal(data[4].toString(), 2); }); + + it("\t\t Should fail to change the ballot status after the ballot ends", async() => { + await increaseTime(duration.days(20)); + await catchRevert( + I_PLCRVotingCheckpoint.changeBallotStatus(new BN(1), false, {from: token_owner}) + ); + }); }); describe("\t\t General function test \n", async() => { diff --git a/test/zd_weighted_vote_checkpoint.js b/test/zd_weighted_vote_checkpoint.js index f2e8f78c1..5986039ab 100644 --- a/test/zd_weighted_vote_checkpoint.js +++ b/test/zd_weighted_vote_checkpoint.js @@ -246,10 +246,28 @@ contract("WeightedVoteCheckpoint", async (accounts) => { ); }); + it("\t\t Should fail to create ballot -- Invalid startTime \n", async() => { + let startTime = new BN(await latestTime()); + let endTime = new BN(await latestTime() + duration.days(4)); + await I_SecurityToken.createCheckpoint({from: token_owner}); + let checkpointId = await I_SecurityToken.currentCheckpointId.call(); + await catchRevert( + I_WeightedVoteCheckpoint.createCustomBallot(checkpointId, new BN(51).mul(new BN(10).pow(new BN(16))), 0, endTime, new BN(3), {from: token_owner}) + ); + }); + + it("\t\t Should fail to create ballot -- Invalid endTimes \n", async() => { + let startTime = new BN(await latestTime() + duration.days(10)); + let endTime = new BN(await latestTime() + duration.days(4)); + await catchRevert( + I_WeightedVoteCheckpoint.createCustomBallot(new BN(1), new BN(51).mul(new BN(10).pow(new BN(16))), startTime, endTime, new BN(3), {from: token_owner}) + ); + }); + it("\t\t Should create the ballot successfully \n", async() => { let tx = await I_WeightedVoteCheckpoint.createBallot(new BN(duration.days(5)), new BN(3), new BN(51).mul(new BN(10).pow(new BN(16))), {from: token_owner}); assert.equal((tx.logs[0].args._noOfProposals).toString(), 3); - assert.equal((tx.logs[0].args._checkpointId).toString(), 1); + assert.equal((tx.logs[0].args._checkpointId).toString(), 2); assert.equal((tx.logs[0].args._ballotId).toString(), 0); }); }); @@ -442,11 +460,23 @@ contract("WeightedVoteCheckpoint", async (accounts) => { }); it("\t\t Should check who votes whom \n", async() => { + // If we give Invalid ballot id, This function will always return 0 + assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(13), account_investor1)).toString(), 0); + assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor1)).toString(), 1); assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor2)).toString(), 2); assert.equal((await I_WeightedVoteCheckpoint.getSelectedProposal.call(new BN(0), account_investor3)).toString(), 1); }); + it("\t\t Should get the result of the ballot \n", async() => { + let data = await I_WeightedVoteCheckpoint.getBallotResults.call(new BN(5)); + assert.equal(data[4], 0); + assert.equal(data[0].length, 0); + assert.equal(data[0].length, 0); + assert.equal(data[2], 0); + assert.isFalse(data[3]); + }); + it("\t\t Should get the result of the ballot \n", async() => { let data = await I_WeightedVoteCheckpoint.getBallotResults.call(new BN(0)); console.log(data); From 2019a88cefb93c9dacf9c50b7dfd57e84486df02 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 15 Apr 2019 13:54:34 +0530 Subject: [PATCH 7/7] increase more coverage --- test/zc_plcr_voting_checkpoint.js | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/zc_plcr_voting_checkpoint.js b/test/zc_plcr_voting_checkpoint.js index e4d90112e..d147c7a8d 100644 --- a/test/zc_plcr_voting_checkpoint.js +++ b/test/zc_plcr_voting_checkpoint.js @@ -385,6 +385,13 @@ contract("PLCRVotingCheckpoint", async (accounts) => { ); }); + it("\t\t Should add the multiple voter in to the ballot exemption list --failed because of bad msg.sender", async() => { + await catchRevert( + I_PLCRVotingCheckpoint.changeBallotExemptedVotersListMulti(new BN(0), [account_investor1], [false], {from: account_polymath}) + ); + }); + + it("\t\t Should add the multiple voter in to the ballot exemption list", async() => { await I_PLCRVotingCheckpoint.changeBallotExemptedVotersListMulti(new BN(0), [account_investor1], [false], {from: token_owner}); assert.isTrue(await I_PLCRVotingCheckpoint.isVoterAllowed.call(new BN(0), account_investor1)); @@ -435,11 +442,36 @@ contract("PLCRVotingCheckpoint", async (accounts) => { ); }); + it("\t\t Should change the deafult exemption list using Multi function -- failed because of mismatch array length", async() => { + await catchRevert( + I_PLCRVotingCheckpoint.changeDefaultExemptedVotersListMulti([account_investor3, account_investor1], [false], {from: token_owner}) + ); + }); + it("\t\t Should change the default exemption list by allowing investor 1 to vote", async() => { + await I_PLCRVotingCheckpoint.changeDefaultExemptedVotersListMulti([account_investor3], [false], {from: token_owner}); + assert.isTrue(await I_PLCRVotingCheckpoint.isVoterAllowed.call(new BN(0), account_investor3)); + }); + + it("\t\t Should change the default exemption list using Multi function", async() => { + await I_PLCRVotingCheckpoint.changeDefaultExemptedVotersListMulti([account_investor3, account_investor1, account_investor2], [true, true, true], {from: token_owner}); + assert.isFalse(await I_PLCRVotingCheckpoint.isVoterAllowed.call(new BN(0), account_investor3)); + assert.isFalse(await I_PLCRVotingCheckpoint.isVoterAllowed.call(new BN(0), account_investor1)); + assert.isFalse(await I_PLCRVotingCheckpoint.isVoterAllowed.call(new BN(0), account_investor2)); + assert.equal((await I_PLCRVotingCheckpoint.getDefaultExemptionVotersList.call()).length, 3); + }); + + it("\t\t Should change the default exemption list by allowing investor 1 to vote again", async() => { await I_PLCRVotingCheckpoint.changeDefaultExemptedVotersList(account_investor3, false, {from: token_owner}); assert.isTrue(await I_PLCRVotingCheckpoint.isVoterAllowed.call(new BN(0), account_investor3)); }); + it("\t\t Should change the default exemption list using Multi function", async() => { + await I_PLCRVotingCheckpoint.changeDefaultExemptedVotersListMulti([account_investor2, account_investor1], [false, false], {from: token_owner}); + assert.isTrue(await I_PLCRVotingCheckpoint.isVoterAllowed.call(new BN(0), account_investor1)); + assert.isTrue(await I_PLCRVotingCheckpoint.isVoterAllowed.call(new BN(0), account_investor2)); + }); + it("\t\t Should successfully vote by account investor3 \n", async() => { let salt = getRandom(); saltArray.push(salt);