@@ -28,6 +28,7 @@ import "./ColonyExtension.sol";
2828abstract contract VotingBase is ColonyExtension , PatriciaTreeProofs {
2929
3030 // Events
31+
3132 event MotionCreated (uint256 indexed motionId , address creator , uint256 indexed domainId );
3233 event MotionStaked (uint256 indexed motionId , address indexed staker , uint256 indexed vote , uint256 amount );
3334 event MotionVoteSubmitted (uint256 indexed motionId , address indexed voter );
@@ -38,6 +39,7 @@ abstract contract VotingBase is ColonyExtension, PatriciaTreeProofs {
3839 event MotionEventSet (uint256 indexed motionId , uint256 eventIndex );
3940
4041 // Constants
42+
4143 uint256 constant UINT128_MAX = 2 ** 128 - 1 ;
4244
4345 uint256 constant NAY = 0 ;
@@ -62,7 +64,29 @@ abstract contract VotingBase is ColonyExtension, PatriciaTreeProofs {
6264
6365 enum ExtensionState { Deployed, Active, Deprecated }
6466
65- // Initialization data
67+ // Data structures
68+
69+ enum MotionState { Null, Staking, Submit, Reveal, Closed, Finalizable, Finalized, Failed }
70+
71+ struct Motion {
72+ uint64 [3 ] events; // For recording motion lifecycle timestamps (STAKE, SUBMIT, REVEAL)
73+ bytes32 rootHash;
74+ uint256 domainId;
75+ uint256 skillId;
76+ uint256 paidVoterComp;
77+ uint256 [2 ] pastVoterComp; // [nay, yay]
78+ uint256 [2 ] stakes; // [nay, yay]
79+ uint256 [2 ][] votes; // [nay, yay]
80+ uint256 [] totalVotes;
81+ uint256 [] maxVotes;
82+ bool escalated;
83+ bool finalized;
84+ address altTarget;
85+ bytes action;
86+ }
87+
88+ // Storage variables
89+
6690 ExtensionState state;
6791
6892 IColonyNetwork colonyNetwork;
@@ -90,6 +114,14 @@ abstract contract VotingBase is ColonyExtension, PatriciaTreeProofs {
90114 uint256 revealPeriod; // Length of time for revealing votes
91115 uint256 escalationPeriod; // Length of time for escalating after a vote
92116
117+ uint256 motionCount;
118+ mapping (uint256 => Motion) motions;
119+ mapping (uint256 => mapping (address => mapping (uint256 => uint256 ))) stakes;
120+ mapping (uint256 => mapping (address => bytes32 )) voteSecrets;
121+
122+ mapping (bytes32 => uint256 ) expenditurePastVotes; // expenditure slot signature => voting power
123+ mapping (bytes32 => uint256 ) expenditureMotionCounts; // expenditure struct signature => count
124+
93125 // Modifiers
94126
95127 modifier onlyRoot () {
@@ -102,7 +134,13 @@ abstract contract VotingBase is ColonyExtension, PatriciaTreeProofs {
102134 _;
103135 }
104136
105- // Public
137+ // Virtual functions
138+
139+ function getInfluence (uint256 _motionId , address _user ) public view virtual returns (uint256 [] memory );
140+ function postReveal (uint256 _motionId , address _user ) internal virtual ;
141+ function postClaim (uint256 _motionId , address _user ) internal virtual ;
142+
143+ // Public functions
106144
107145 /// @notice Install the extension
108146 /// @param _colony Base colony for the installation
@@ -115,6 +153,19 @@ abstract contract VotingBase is ColonyExtension, PatriciaTreeProofs {
115153 token = colony.getToken ();
116154 }
117155
156+ /// @notice Called when upgrading the extension
157+ function finishUpgrade () public override auth {} // solhint-disable-line no-empty-blocks
158+
159+ /// @notice Called when deprecating (or undeprecating) the extension
160+ function deprecate (bool _deprecated ) public override auth {
161+ deprecated = _deprecated;
162+ }
163+
164+ /// @notice Called when uninstalling the extension
165+ function uninstall () public override auth {
166+ selfdestruct (address (uint160 (address (colony))));
167+ }
168+
118169 /// @notice Initialise the extension
119170 /// @param _totalStakeFraction The fraction of the domain's reputation we need to stake
120171 /// @param _userMinStakeFraction The minimum per-user stake as fraction of total stake
@@ -166,56 +217,6 @@ abstract contract VotingBase is ColonyExtension, PatriciaTreeProofs {
166217 emit ExtensionInitialised ();
167218 }
168219
169- /// @notice Called when upgrading the extension
170- function finishUpgrade () public override auth {} // solhint-disable-line no-empty-blocks
171-
172- /// @notice Called when deprecating (or undeprecating) the extension
173- function deprecate (bool _deprecated ) public override auth {
174- deprecated = _deprecated;
175- }
176-
177- /// @notice Called when uninstalling the extension
178- function uninstall () public override auth {
179- selfdestruct (address (uint160 (address (colony))));
180- }
181-
182- // Data structures
183- enum MotionState { Null, Staking, Submit, Reveal, Closed, Finalizable, Finalized, Failed }
184-
185- struct Motion {
186- uint64 [3 ] events; // For recording motion lifecycle timestamps (STAKE, SUBMIT, REVEAL)
187- bytes32 rootHash;
188- uint256 domainId;
189- uint256 skillId;
190- uint256 paidVoterComp;
191- uint256 [2 ] pastVoterComp; // [nay, yay]
192- uint256 [2 ] stakes; // [nay, yay]
193- uint256 [2 ][] votes; // [nay, yay]
194- uint256 [] totalVotes;
195- uint256 [] maxVotes;
196- bool escalated;
197- bool finalized;
198- address altTarget;
199- bytes action;
200- }
201-
202- // Storage
203- uint256 motionCount;
204- mapping (uint256 => Motion) motions;
205- mapping (uint256 => mapping (address => mapping (uint256 => uint256 ))) stakes;
206- mapping (uint256 => mapping (address => bytes32 )) voteSecrets;
207-
208- mapping (bytes32 => uint256 ) expenditurePastVotes; // expenditure slot signature => voting power
209- mapping (bytes32 => uint256 ) expenditureMotionCounts; // expenditure struct signature => count
210-
211- // Virtual functions
212-
213- function getInfluence (uint256 _motionId , address _user ) public view virtual returns (uint256 [] memory );
214- function postReveal (uint256 _motionId , address _user ) internal virtual ;
215- function postClaim (uint256 _motionId , address _user ) internal virtual ;
216-
217- // Public functions (interface)
218-
219220 /// @notice Reveal a vote secret for a motion
220221 /// @param _motionId The id of the motion
221222 /// @param _salt The salt used to hash the vote
@@ -526,8 +527,9 @@ abstract contract VotingBase is ColonyExtension, PatriciaTreeProofs {
526527 uint256 fractionUserInfluence;
527528
528529 for (uint256 i; i < influence.length ; i++ ) {
529- // TODO: Divide-by-zero ?
530- fractionUserInfluence = add (fractionUserInfluence, wdiv (influence[i], motion.totalVotes[i]));
530+ if (motion.totalVotes[i] > 0 ) {
531+ fractionUserInfluence = add (fractionUserInfluence, wdiv (influence[i], motion.totalVotes[i]));
532+ }
531533 }
532534
533535 fractionUserInfluence = fractionUserInfluence / influence.length ;
@@ -559,9 +561,13 @@ abstract contract VotingBase is ColonyExtension, PatriciaTreeProofs {
559561 // If user hasn't voted, add their influence to totalVotes
560562 uint256 pendingVote = (voteSecrets[_motionId][_user] == bytes32 (0 )) ? influence[i] : 0 ;
561563
562- // TODO: Divide-by-zero ?
563- minFractionUserInfluence = add (minFractionUserInfluence, wdiv (influence[i], motion.maxVotes[i]));
564- maxFractionUserInfluence = add (maxFractionUserInfluence, wdiv (influence[i], add (motion.totalVotes[i], pendingVote)));
564+ if (motion.maxVotes[i] > 0 ) {
565+ minFractionUserInfluence = add (minFractionUserInfluence, wdiv (influence[i], motion.maxVotes[i]));
566+ }
567+
568+ if (add (motion.totalVotes[i], pendingVote) > 0 ) {
569+ maxFractionUserInfluence = add (maxFractionUserInfluence, wdiv (influence[i], add (motion.totalVotes[i], pendingVote)));
570+ }
565571 }
566572
567573 minFractionUserInfluence = minFractionUserInfluence / influence.length ;
@@ -599,13 +605,13 @@ abstract contract VotingBase is ColonyExtension, PatriciaTreeProofs {
599605 uint256 stakerReward;
600606 uint256 repPenalty;
601607
602- uint256 sumVotes ;
608+ bool wasVote ;
603609
604- for (uint256 i; i < motion.votes.length ; i++ ) {
605- sumVotes = add (sumVotes, add ( motion.votes[i][NAY], motion.votes[i][YAY])) ;
610+ for (uint256 i; i < motion.votes.length && ! wasVote ; i++ ) {
611+ wasVote = add (motion.votes[i][NAY], motion.votes[i][YAY]) > 0 ;
606612 }
607613
608- if (sumVotes > 0 ) {
614+ if (wasVote ) {
609615 // Went to a vote, use vote to determine reward or penalty
610616 (stakerReward, repPenalty) = getStakerRewardByVote (_motionId, _vote, stakeFraction, realStake);
611617 } else {
@@ -831,8 +837,9 @@ abstract contract VotingBase is ColonyExtension, PatriciaTreeProofs {
831837 for (uint256 i; i < motion.votes.length ; i++ ) {
832838 yayWon = yayWon && motion.votes[i][NAY] < motion.votes[i][YAY];
833839
834- // TODO: divide-by-zero ??
835- winFraction = add (winFraction, wdiv (motion.votes[i][_vote], motion.totalVotes[i]));
840+ if (motion.totalVotes[i] > 0 ) {
841+ winFraction = add (winFraction, wdiv (motion.votes[i][_vote], motion.totalVotes[i]));
842+ }
836843 }
837844
838845 winFraction = winFraction / motion.votes.length ;
0 commit comments