@@ -4,102 +4,113 @@ pragma solidity ^0.8.20;
4
4
import {AdvancedPolicy} from "../../core/policy/AdvancedPolicy.sol " ;
5
5
import {Check} from "../../core/interfaces/IAdvancedPolicy.sol " ;
6
6
7
- /// @title AdvancedVoting.
8
- /// @notice Advanced voting system with NFT-based phases and eligibility verification.
9
- /// @dev Implements a three-phase governance process using NFT validation:
10
- /// 1. Registration: Validates ownership of signup NFT (under-the-hood uses the BaseERC721Checker).
11
- /// 2. Voting: Validates token balances and records votes (single token = single vote).
12
- /// 3. Eligibility: Validates criteria for governance participation benefits.
7
+ /// @title AdvancedVoting
8
+ /// @notice Multi-phase governance system with NFT-based validation.
9
+ /// @dev Combines pre, main, and post phases for registration, voting, and eligibility verification.
13
10
contract AdvancedVoting {
14
- /// @notice Emitted on successful phase completion .
15
- /// @param voter Address that completed the phase .
11
+ /// @notice Emitted when a voter registers successfully .
12
+ /// @param voter Address of the voter who registered .
16
13
event Registered (address voter );
17
- /// @param option Selected voting option (0 or 1).
14
+
15
+ /// @notice Emitted when a vote is cast successfully.
16
+ /// @param voter Address of the voter who cast their vote.
17
+ /// @param option The chosen voting option (0 or 1).
18
18
event Voted (address voter , uint8 option );
19
- /// @param voter Address that met eligibility criteria.
19
+
20
+ /// @notice Emitted when a voter is deemed eligible.
21
+ /// @param voter Address of the voter who met eligibility criteria.
20
22
event Eligible (address voter );
21
23
22
- /// @notice Validation error states.
23
- /// @dev Thrown when phase requirements not met.
24
- error NotRegistered (); // Pre-check (registration) not completed.
25
- error NotVoted (); // Main check (voting) not completed.
26
- error AlreadyEligible (); // Post check (eligibility) already verified.
27
- error InvalidOption (); // Vote option out of valid range.
28
- error NotEligible (); // Eligibility criteria not met.
24
+ /// @notice Error thrown when a user attempts an action without registering first.
25
+ error NotRegistered ();
26
+
27
+ /// @notice Error thrown when a user attempts to verify eligibility without voting.
28
+ error NotVoted ();
29
+
30
+ /// @notice Error thrown when a user tries to verify eligibility more than once.
31
+ error AlreadyEligible ();
32
+
33
+ /// @notice Error thrown when an invalid voting option is provided.
34
+ error InvalidOption ();
29
35
30
- /// @notice Policy contract managing multi-phase validation.
31
- /// @dev Handles all NFT-based checks through aggregated verifiers.
36
+ /// @notice Error thrown when a user does not meet the eligibility criteria.
37
+ error NotEligible ();
38
+
39
+ /// @notice Reference to the policy contract enforcing multi-phase validation.
32
40
AdvancedPolicy public immutable POLICY;
33
41
34
- /// @notice Vote tracking per option.
35
- /// @dev Maps option ID (0 or 1) to total votes received.
42
+ /// @notice Tracks the vote count for each option (0 or 1).
36
43
mapping (uint8 => uint256 ) public voteCounts;
37
44
38
- /// @notice Initializes voting system .
39
- /// @param _policy Advanced policy contract with configured verifiers .
45
+ /// @notice Constructor to set the policy contract .
46
+ /// @param _policy Address of the AdvancedPolicy contract to use for validation .
40
47
constructor (AdvancedPolicy _policy ) {
41
48
POLICY = _policy;
42
49
}
43
50
44
- /// @notice Registration phase handler.
45
- /// @dev Validates signup NFT ownership using BaseERC721Checker.
46
- /// @param tokenId ID of the signup NFT to validate.
47
- /// @custom:requirements
48
- /// - Token must exist.
49
- /// - Caller must be token owner.
50
- /// - Token ID must be within valid range.
51
- /// @custom:emits Registered when registration succeeds.
51
+ /// @notice Registers a user for voting by validating their NFT ownership.
52
+ /// @dev Enforces the pre-check phase using the AdvancedPolicy contract.
53
+ /// @param tokenId The ID of the NFT used to verify registration eligibility.
52
54
function register (uint256 tokenId ) external {
55
+ // Prepare evidence with the tokenId encoded as bytes.
53
56
bytes [] memory _evidence = new bytes [](1 );
54
57
_evidence[0 ] = abi.encode (tokenId);
55
58
59
+ // Enforce the pre-check phase using the provided policy.
56
60
POLICY.enforce (msg .sender , _evidence, Check.PRE);
57
61
62
+ // Emit an event to log the registration.
58
63
emit Registered (msg .sender );
59
64
}
60
65
61
- /// @notice Voting phase handler.
62
- /// @dev Validates voting power and records vote choice.
63
- /// @param option Binary choice (0 or 1).
64
- /// @custom:requirements
65
- /// - Registration must be completed.
66
- /// - Option must be valid (0 or 1).
67
- /// - Token balance must meet requirements.
68
- /// @custom:emits Voted when vote is recorded.
66
+ /// @notice Allows a registered user to cast their vote.
67
+ /// @dev Enforces the main-check phase and updates the vote count.
68
+ /// @param option The chosen voting option (0 or 1).
69
69
function vote (uint8 option ) external {
70
+ // Retrieve the enforcement status of the sender from the policy.
70
71
(bool pre , , ) = POLICY.enforced (msg .sender );
72
+
73
+ // Ensure the user has registered before voting.
71
74
if (! pre) revert NotRegistered ();
75
+
76
+ // Validate that the voting option is within the allowed range.
72
77
if (option >= 2 ) revert InvalidOption ();
73
78
79
+ // Prepare evidence with the chosen option encoded as bytes.
74
80
bytes [] memory _evidence = new bytes [](1 );
75
81
_evidence[0 ] = abi.encode (option);
76
82
83
+ // Enforce the main-check phase using the policy.
77
84
POLICY.enforce (msg .sender , _evidence, Check.MAIN);
78
85
86
+ // Increment the vote count for the chosen option.
79
87
unchecked {
80
88
voteCounts[option]++ ;
81
89
}
82
90
91
+ // Emit an event to log the voting action.
83
92
emit Voted (msg .sender , option);
84
93
}
85
94
86
- /// @notice Eligibility verification phase.
87
- /// @dev Validates completion of governance process and checks eligibility criteria.
88
- /// @custom:requirements
89
- /// - Caller must be registered (passed PRE check).
90
- /// - Caller must have voted (passed MAIN check).
91
- /// - Caller must not be already verified (no POST check).
92
- /// - Caller must meet eligibility criteria (no existing benefits).
93
- /// @custom:emits Eligible when verification succeeds.
95
+ /// @notice Verifies a user's eligibility after voting has concluded.
96
+ /// @dev Enforces the post-check phase to ensure eligibility criteria are met.
94
97
function eligible () external {
98
+ // Retrieve the enforcement status for all phases.
95
99
(bool pre , uint8 main , bool post ) = POLICY.enforced (msg .sender );
96
100
101
+ // Ensure the user has completed the registration phase.
97
102
if (! pre) revert NotRegistered ();
103
+
104
+ // Ensure the user has cast at least one vote.
98
105
if (main == 0 ) revert NotVoted ();
106
+
107
+ // Ensure the user has not already been marked as eligible.
99
108
if (post) revert AlreadyEligible ();
100
109
110
+ // Enforce the post-check phase using the policy.
101
111
POLICY.enforce (msg .sender , new bytes [](1 ), Check.POST);
102
112
113
+ // Emit an event to log the eligibility status.
103
114
emit Eligible (msg .sender );
104
115
}
105
116
}
0 commit comments