Skip to content

Commit a2695f4

Browse files
committed
refactor(contracts): add missing harnesses and comments to base and advanced test contracts
1 parent 71f7911 commit a2695f4

18 files changed

+314
-240
lines changed

packages/contracts/contracts/src/test/advanced/AdvancedERC721Checker.sol

+21-27
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,14 @@ import {AdvancedChecker} from "../../core/checker/AdvancedChecker.sol";
55
import {BaseERC721Checker} from "../base/BaseERC721Checker.sol";
66
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
77

8-
/// @title AdvancedERC721Checker.
9-
/// @notice Multi-phase NFT validation with aggregated verification contracts.
10-
/// @dev Implements three-phase validation using multiple NFT contracts and external verifiers:
11-
/// - Pre-check: Basic signup token validation using BaseERC721Checker.
12-
/// - Main-check: Balance threshold validation for signup token.
13-
/// - Post-check: Reward eligibility verification for reward token.
8+
/// @title AdvancedERC721Checker
9+
/// @notice Multi-phase NFT validation using external contracts and thresholds.
10+
/// @dev Implements three-phase validation:
11+
/// - Pre-check: Basic ownership verification using `BaseERC721Checker`.
12+
/// - Main-check: Ensures a minimum token balance.
13+
/// - Post-check: Validates reward eligibility.
1414
contract AdvancedERC721Checker is AdvancedChecker {
15-
/// @notice External contracts used for verification.
16-
/// @dev Immutable references derived from verifier array positions:
17-
/// - Index 0: Signup NFT contract.
18-
/// - Index 1: Reward NFT contract.
19-
/// - Index 2: Base ERC721 checker contract.
15+
/// @notice External verification contracts and thresholds.
2016
IERC721 public signupNft;
2117
IERC721 public rewardNft;
2218
BaseERC721Checker public baseERC721Checker;
@@ -25,14 +21,13 @@ contract AdvancedERC721Checker is AdvancedChecker {
2521
uint256 public minTokenId;
2622
uint256 public maxTokenId;
2723

24+
/// @notice Initializes the checker with external contract references and thresholds.
25+
/// @dev Decodes appended bytes to set state variables.
2826
function _initialize() internal override {
29-
// 1. Call super to handle `_initialized` check.
3027
super._initialize();
3128

32-
// 2. Retrieve appended bytes from the clone.
3329
bytes memory data = _getAppendedBytes();
3430

35-
// 3. Decode everything in one shot:
3631
(
3732
address signupNftAddr,
3833
address rewardNftAddr,
@@ -42,7 +37,6 @@ contract AdvancedERC721Checker is AdvancedChecker {
4237
uint256 maxTokenId_
4338
) = abi.decode(data, (address, address, address, uint256, uint256, uint256));
4439

45-
// 4. Assign to storage variables.
4640
signupNft = IERC721(signupNftAddr);
4741
rewardNft = IERC721(rewardNftAddr);
4842
baseERC721Checker = BaseERC721Checker(baseCheckerAddr);
@@ -51,33 +45,33 @@ contract AdvancedERC721Checker is AdvancedChecker {
5145
maxTokenId = maxTokenId_;
5246
}
5347

54-
/// @notice Pre-check: Validates initial NFT ownership.
55-
/// @dev Delegates basic ownership check to BaseERC721Checker.
48+
/// @notice Pre-check: Validates ownership using the base checker.
5649
/// @param subject Address to validate.
57-
/// @param evidence Array containing encoded tokenId.
58-
/// @return Validation status from base checker.
50+
/// @param evidence Encoded tokenId.
51+
/// @return Boolean indicating validation success.
5952
function _checkPre(address subject, bytes[] calldata evidence) internal view override returns (bool) {
6053
super._checkPre(subject, evidence);
54+
6155
return baseERC721Checker.check(subject, evidence);
6256
}
6357

64-
/// @notice Main-check: Validates token balance requirements.
65-
/// @dev Ensures subject has exactly MIN_BALANCE tokens.
58+
/// @notice Main-check: Ensures token balance meets requirements.
6659
/// @param subject Address to validate.
67-
/// @param evidence Not used in balance check.
68-
/// @return True if balance meets requirements.
60+
/// @param evidence Not used in this validation.
61+
/// @return Boolean indicating validation success.
6962
function _checkMain(address subject, bytes[] calldata evidence) internal view override returns (bool) {
7063
super._checkMain(subject, evidence);
71-
return signupNft.balanceOf(subject) >= minBalance && signupNft.balanceOf(subject) <= minBalance;
64+
65+
return signupNft.balanceOf(subject) >= minBalance;
7266
}
7367

7468
/// @notice Post-check: Validates reward eligibility.
75-
/// @dev Ensures subject doesn't already have reward tokens.
7669
/// @param subject Address to validate.
77-
/// @param evidence Not used in reward check.
78-
/// @return True if subject eligible for rewards.
70+
/// @param evidence Not used in this validation.
71+
/// @return Boolean indicating validation success.
7972
function _checkPost(address subject, bytes[] calldata evidence) internal view override returns (bool) {
8073
super._checkPost(subject, evidence);
74+
8175
return rewardNft.balanceOf(subject) == 0;
8276
}
8377
}

packages/contracts/contracts/src/test/advanced/AdvancedERC721CheckerFactory.sol

+12-4
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,23 @@
22
pragma solidity ^0.8.20;
33

44
import {AdvancedERC721Checker} from "./AdvancedERC721Checker.sol";
5-
import {LibClone} from "solady/src/utils/LibClone.sol";
65
import {Factory} from "../../core/proxy/Factory.sol";
76

7+
/// @title AdvancedERC721CheckerFactory
8+
/// @notice Factory for deploying minimal proxy instances of AdvancedERC721Checker.
9+
/// @dev Encodes configuration data for each clone.
810
contract AdvancedERC721CheckerFactory is Factory {
11+
/// @notice Initializes the factory with the AdvancedERC721Checker implementation.
912
constructor() Factory(address(new AdvancedERC721Checker())) {}
1013

14+
/// @notice Deploys a new AdvancedERC721Checker clone.
15+
/// @dev Encodes and appends configuration data for the clone.
16+
/// @param _nftAddress Address of the signup NFT contract.
17+
/// @param _rewardNft Address of the reward NFT contract.
18+
/// @param _baseERC721Checker Address of the base checker contract.
19+
/// @param _minBalance Minimum balance required for validation.
20+
/// @param _minTokenId Minimum token ID for validation.
21+
/// @param _maxTokenId Maximum token ID for validation.
1122
function deploy(
1223
address _nftAddress,
1324
address _rewardNft,
@@ -16,7 +27,6 @@ contract AdvancedERC721CheckerFactory is Factory {
1627
uint256 _minTokenId,
1728
uint256 _maxTokenId
1829
) public {
19-
// 1. Encode.
2030
bytes memory data = abi.encode(
2131
_nftAddress,
2232
_rewardNft,
@@ -26,10 +36,8 @@ contract AdvancedERC721CheckerFactory is Factory {
2636
_maxTokenId
2737
);
2838

29-
// 2. Deploy.
3039
address clone = super._deploy(data);
3140

32-
// 3. Call initialize().
3341
AdvancedERC721Checker(clone).initialize();
3442
}
3543
}

packages/contracts/contracts/src/test/advanced/AdvancedERC721Policy.sol

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
pragma solidity ^0.8.20;
33

44
import {AdvancedPolicy} from "../../core/policy/AdvancedPolicy.sol";
5-
import {AdvancedERC721Checker} from "./AdvancedERC721Checker.sol";
65

7-
/// @title AdvancedERC721Policy.
8-
/// @notice Three-phase ERC721 validation policy.
9-
/// @dev Enforces multi-stage checks through AdvancedERC721Checker.
6+
/// @title AdvancedERC721Policy
7+
/// @notice Three-phase policy contract for ERC721 validation.
8+
/// @dev Leverages AdvancedChecker for pre, main, and post validation phases.
109
contract AdvancedERC721Policy is AdvancedPolicy {
11-
/// @notice Returns policy identifier.
10+
/// @notice Returns a unique identifier for the policy.
11+
/// @return The string identifier "AdvancedERC721".
1212
function trait() external pure returns (string memory) {
1313
return "AdvancedERC721";
1414
}
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.20;
33

4-
import {LibClone} from "solady/src/utils/LibClone.sol";
54
import {AdvancedERC721Policy} from "./AdvancedERC721Policy.sol";
65
import {Factory} from "../../core/proxy/Factory.sol";
76

8-
/**
9-
* @title AdvancedERC721PolicyFactory
10-
* @notice Example factory for deploying minimal proxies of `AdvancedERC721Policy`.
11-
*/
7+
/// @title AdvancedERC721PolicyFactory
8+
/// @notice Factory for deploying minimal proxy instances of AdvancedERC721Policy.
9+
/// @dev Encodes configuration data for multi-phase policy validation.
1210
contract AdvancedERC721PolicyFactory is Factory {
11+
/// @notice Initializes the factory with the AdvancedERC721Policy implementation.
1312
constructor() Factory(address(new AdvancedERC721Policy())) {}
1413

14+
/// @notice Deploys a new AdvancedERC721Policy clone.
15+
/// @param _checkerAddr Address of the associated checker contract.
16+
/// @param _skipPre Whether to skip pre-checks.
17+
/// @param _skipPost Whether to skip post-checks.
18+
/// @param _allowMultipleMain Whether multiple main checks are allowed.
1519
function deploy(address _checkerAddr, bool _skipPre, bool _skipPost, bool _allowMultipleMain) public {
16-
// 1. Encode.
1720
bytes memory data = abi.encode(msg.sender, _checkerAddr, _skipPre, _skipPost, _allowMultipleMain);
1821

19-
// 2. Deploy.
2022
address clone = super._deploy(data);
2123

22-
// 3. Call `initialize()`.
2324
AdvancedERC721Policy(clone).initialize();
2425
}
2526
}

packages/contracts/contracts/src/test/advanced/AdvancedVoting.sol

+58-47
Original file line numberDiff line numberDiff line change
@@ -4,102 +4,113 @@ pragma solidity ^0.8.20;
44
import {AdvancedPolicy} from "../../core/policy/AdvancedPolicy.sol";
55
import {Check} from "../../core/interfaces/IAdvancedPolicy.sol";
66

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.
1310
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.
1613
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).
1818
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.
2022
event Eligible(address voter);
2123

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();
2935

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.
3240
AdvancedPolicy public immutable POLICY;
3341

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).
3643
mapping(uint8 => uint256) public voteCounts;
3744

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.
4047
constructor(AdvancedPolicy _policy) {
4148
POLICY = _policy;
4249
}
4350

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.
5254
function register(uint256 tokenId) external {
55+
// Prepare evidence with the tokenId encoded as bytes.
5356
bytes[] memory _evidence = new bytes[](1);
5457
_evidence[0] = abi.encode(tokenId);
5558

59+
// Enforce the pre-check phase using the provided policy.
5660
POLICY.enforce(msg.sender, _evidence, Check.PRE);
5761

62+
// Emit an event to log the registration.
5863
emit Registered(msg.sender);
5964
}
6065

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).
6969
function vote(uint8 option) external {
70+
// Retrieve the enforcement status of the sender from the policy.
7071
(bool pre, , ) = POLICY.enforced(msg.sender);
72+
73+
// Ensure the user has registered before voting.
7174
if (!pre) revert NotRegistered();
75+
76+
// Validate that the voting option is within the allowed range.
7277
if (option >= 2) revert InvalidOption();
7378

79+
// Prepare evidence with the chosen option encoded as bytes.
7480
bytes[] memory _evidence = new bytes[](1);
7581
_evidence[0] = abi.encode(option);
7682

83+
// Enforce the main-check phase using the policy.
7784
POLICY.enforce(msg.sender, _evidence, Check.MAIN);
7885

86+
// Increment the vote count for the chosen option.
7987
unchecked {
8088
voteCounts[option]++;
8189
}
8290

91+
// Emit an event to log the voting action.
8392
emit Voted(msg.sender, option);
8493
}
8594

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.
9497
function eligible() external {
98+
// Retrieve the enforcement status for all phases.
9599
(bool pre, uint8 main, bool post) = POLICY.enforced(msg.sender);
96100

101+
// Ensure the user has completed the registration phase.
97102
if (!pre) revert NotRegistered();
103+
104+
// Ensure the user has cast at least one vote.
98105
if (main == 0) revert NotVoted();
106+
107+
// Ensure the user has not already been marked as eligible.
99108
if (post) revert AlreadyEligible();
100109

110+
// Enforce the post-check phase using the policy.
101111
POLICY.enforce(msg.sender, new bytes[](1), Check.POST);
102112

113+
// Emit an event to log the eligibility status.
103114
emit Eligible(msg.sender);
104115
}
105116
}

0 commit comments

Comments
 (0)