11// SPDX-License-Identifier: MIT
2- pragma solidity ^ 0.8.20 ;
2+ pragma solidity ^ 0.8.25 ;
33
4+ import "./Errors.sol " ;
45import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol " ;
56import "@openzeppelin/contracts/utils/ReentrancyGuard.sol " ;
67import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol " ;
78
89interface IGovernance {
910 event Register (address candidate );
1011 event Exit (address candidate );
11- event Vote (address voter , address to , uint amount );
12- event Revoke (address voter , address from , uint amount );
13- event VoterClaim (address voter , uint reward );
12+ event Vote (address indexed voter , address indexed to , uint amount );
13+ event Revoke (address indexed voter , address indexed from , uint amount );
14+ event VoterClaim (address indexed voter , uint reward );
1415 event CandidateWithdraw (address candidate , uint amount );
1516 event Persist (address [] validators );
1617
@@ -106,7 +107,7 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
106107 mapping (address => mapping (uint => uint )) public epochStartGasPerVote;
107108
108109 modifier onlyAdmin () {
109- require (msg .sender == GOV_ADMIN, " not admin " );
110+ if (msg .sender != GOV_ADMIN) revert Errors. NotAdmin ( );
110111 _;
111112 }
112113
@@ -135,7 +136,7 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
135136 }
136137
137138 receive () external payable nonReentrant {
138- require (msg .sender == GOV_REWARD, " side call not allowed " );
139+ if (msg .sender != GOV_REWARD) revert Errors. SideCallNotAllowed ( );
139140 address [] memory validators = currentConsensus;
140141 uint length = validators.length ;
141142 for (uint i = 0 ; i < length; i++ ) {
@@ -160,12 +161,11 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
160161 }
161162
162163 function registerCandidate (uint shareRate ) external payable {
163- require (tx .origin == msg .sender , "only allow EOA " );
164- require (msg .value >= registerFee, "insufficient amount " );
165- require (shareRate < 1000 , "invalid rate " );
166- require (! candidateList.contains (msg .sender ), "candidate exists " );
167- require (exitHeightOf[msg .sender ] == 0 , "left not claimed " );
168- candidateList.add (msg .sender );
164+ if (tx .origin != msg .sender ) revert Errors.OnlyEOA ();
165+ if (msg .value < registerFee) revert Errors.InsufficientValue ();
166+ if (shareRate > 1000 ) revert Errors.InvalidShareRate ();
167+ if (exitHeightOf[msg .sender ] > 0 ) revert Errors.LeftNotClaimed ();
168+ if (! candidateList.add (msg .sender )) revert Errors.CandidateExists ();
169169 if (receivedVotes[msg .sender ] > 0 ) {
170170 totalVotes += receivedVotes[msg .sender ];
171171 }
@@ -177,9 +177,9 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
177177 }
178178
179179 function exitCandidate () external {
180- require (candidateList.contains (msg .sender ), "candidate not exists " );
180+ if (! candidateList.remove (msg .sender ))
181+ revert Errors.CandidateNotExists ();
181182 // remove candidate list, balance still locked
182- candidateList.remove (msg .sender );
183183 exitHeightOf[msg .sender ] = block .number ;
184184 if (receivedVotes[msg .sender ] > 0 ) {
185185 totalVotes -= receivedVotes[msg .sender ];
@@ -190,11 +190,10 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
190190 function withdrawRegisterFee () external nonReentrant {
191191 // require 2 epochs to exit candidate list
192192 // NOTE: suppose epoch change always happens in time
193- require (
194- exitHeightOf[msg .sender ] > 0 &&
195- block .number > exitHeightOf[msg .sender ] + 2 * epochDuration,
196- "withdraw not allowed "
197- );
193+ if (
194+ exitHeightOf[msg .sender ] <= 0 ||
195+ block .number <= exitHeightOf[msg .sender ] + 2 * epochDuration
196+ ) revert Errors.CandidateWithdrawNotAllowed ();
198197
199198 // send back balance
200199 uint amount = candidateBalanceOf[msg .sender ];
@@ -207,13 +206,12 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
207206 }
208207
209208 function vote (address candidateTo ) external payable nonReentrant {
210- require (msg .value >= minVoteAmount, "insufficient amount " );
211- require (candidateList.contains (candidateTo), "candidate not allowed " );
209+ if (msg .value < minVoteAmount) revert Errors.InsufficientValue ();
210+ if (! candidateList.contains (candidateTo))
211+ revert Errors.CandidateNotExists ();
212212 address votedCandidate = votedTo[msg .sender ];
213- require (
214- votedCandidate == candidateTo || votedCandidate == address (0 ),
215- "only one choice is allowed "
216- );
213+ if (votedCandidate != candidateTo && votedCandidate != address (0 ))
214+ revert Errors.MultipleVoteNotAllowed ();
217215
218216 // settle reward here
219217 uint unclaimedReward = 0 ;
@@ -241,10 +239,7 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
241239 function revokeVote () external nonReentrant {
242240 address candidateFrom = votedTo[msg .sender ];
243241 uint amount = votedAmount[msg .sender ];
244- require (
245- candidateFrom != address (0 ) && amount > 0 ,
246- "revoke not allowed "
247- );
242+ if (candidateFrom == address (0 ) || amount <= 0 ) revert Errors.NoVote ();
248243
249244 // settle reward here
250245 uint unclaimedReward = _settleReward (msg .sender , candidateFrom);
@@ -290,7 +285,7 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
290285
291286 function claimReward () external nonReentrant {
292287 address votedCandidate = votedTo[msg .sender ];
293- require (votedCandidate != address (0 ), " claim not allowed " );
288+ if (votedCandidate == address (0 )) revert Errors. NoVote ( );
294289 uint unclaimedReward = _settleReward (msg .sender , votedCandidate);
295290 if (unclaimedReward > 0 ) _safeTransferETH (msg .sender , unclaimedReward);
296291 }
@@ -303,7 +298,7 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
303298
304299 function onPersist () external {
305300 // NOTE: suppose onPersist always happens at the beginning of every block
306- require (msg .sender == SYS_CALL, " side call not allowed " );
301+ if (msg .sender != SYS_CALL) revert Errors. SideCallNotAllowed ( );
307302 // only settle validator reward if there is no epoch change
308303 IGovReward (GOV_REWARD).withdraw ();
309304 if (block .number < currentEpochStartHeight + epochDuration) return ;
@@ -322,7 +317,7 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
322317 if (length < consensusSize || totalVotes < voteTargetAmount) {
323318 currentConsensus = standByValidators;
324319 } else {
325- currentConsensus = _computeConsensus ();
320+ currentConsensus = _computeConsensus (candidates );
326321 }
327322 emit Persist (currentConsensus);
328323 }
@@ -337,9 +332,9 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
337332 ) internal view returns (uint ) {
338333 // NOTE: suppose onPersist always happens at the beginning of every block, then latestGasPerVote is always the latest
339334 uint height = voteHeight[voter];
335+ if (currentEpochStartHeight <= height) return 0 ;
340336 uint lastGasPerVote = voterGasPerVote[voter];
341337 uint latestGasPerVote = candidateGasPerVote[candidate];
342- if (currentEpochStartHeight <= height) return 0 ;
343338
344339 // NOTE: suppose epoch change always happens at the beginning of a block, then vote in that block should wait another epoch to farm reward
345340 uint voteEpochEndGasPerVote = epochStartGasPerVote[candidate][
@@ -366,12 +361,13 @@ contract Governance is IGovernance, ReentrancyGuard, UUPSUpgradeable {
366361
367362 function _safeTransferETH (address to , uint value ) internal {
368363 (bool success , ) = to.call {value: value}(new bytes (0 ));
369- require ( success, " safeTransferETH: ETH transfer failed " );
364+ if ( ! success) revert Errors. TransferFailed ( );
370365 }
371366
372- function _computeConsensus () internal view returns (address [] memory ) {
367+ function _computeConsensus (
368+ address [] memory candidates
369+ ) internal view returns (address [] memory ) {
373370 // build up a votes array
374- address [] memory candidates = getCandidates ();
375371 uint length = candidates.length ;
376372 uint [] memory votes = new uint [](length);
377373 for (uint i = 0 ; i < length; i++ ) {
0 commit comments