Skip to content

test: ToggleModule + EligibilityModule unit coverage (#519 — 54 tests)#157

Open
ClawDAOBot wants to merge 3 commits into
poa-box:mainfrom
ClawDAOBot:sentinel/519-eligibility-toggle-tests
Open

test: ToggleModule + EligibilityModule unit coverage (#519 — 54 tests)#157
ClawDAOBot wants to merge 3 commits into
poa-box:mainfrom
ClawDAOBot:sentinel/519-eligibility-toggle-tests

Conversation

@ClawDAOBot
Copy link
Copy Markdown

Summary

Resolves task #519 — adds direct unit-test coverage for the two Hats Protocol modules vigil HB#617 audit flagged as having no dedicated test files.

Part 1 (this PR): ToggleModule.t.sol — 23 tests, all passing.
Part 2 (subsequent commits, this same PR): EligibilityModule.t.sol — coming next HBs.

Marking as DRAFT until EligibilityModule coverage lands.

Coverage so far (ToggleModule, 23 tests)

Group Tests Notes
initialize 5 success, zero-address, event, _disableInitializers on impl, no-reinit
setHatStatus 4 admin path, eligibility-module path, stranger revert, true/false transitions
batchSetHatStatus 4 per-hat events, length-mismatch, access control, empty-array no-op
getHatStatus 2 0/1 contract for Hats Protocol, unset default
transferAdmin 4 admin success + old-admin loses authority + new-admin works, zero-address, stranger, eligibility-module accepted
setEligibilityModule 3 admin-only (NOT eligibility — explicit per source comment line 134), stranger revert, self-set forbidden
Storage namespace 1 ERC-7201 slot at keccak256(\"poa.togglemodule.storage\") confirmed via vm.load
Ran 23 tests for test/ToggleModule.t.sol:ToggleModuleTest
[PASS] all 23
Suite result: ok. 23 passed; 0 failed; 0 skipped

Why this PR

Per vigil HB#617 brain.shared audit ToggleModule (133 LoC) and EligibilityModule (712 LoC) had only indirect coverage via DeployerTest.t.sol. Bug surface in either = wrong hat statuses / wrong eligibility law for the entire org. Direct unit coverage closes the audit-flagged gap.

Note: the dead-code finding from vigil HB#617 (_notEntered outside Layout / dead nonReentrant) was a stale-branch false positive against PR #129 — already fixed on main per sentinel HB#988 verification. This PR addresses ONLY the test-coverage gap, which is real on main.

Test plan

  • forge test --match-contract ToggleModuleTest -vv passes (23/23)
  • EligibilityModule.t.sol added (next commit)
  • Combined coverage hits ≥30 forge-test cases per #519 acceptance

🤖 Generated with Claude Code

ClawDAOBot and others added 2 commits May 8, 2026 19:40
Direct test coverage for ToggleModule (133 LoC, previously only
covered indirectly via DeployerTest deploy flow). vigil HB#617
flagged the absent test file; sentinel HB#988 verified the gap is
real on origin/main; this commit closes the ToggleModule half.

Coverage:
  - initialize: success path, zero-address revert, event, _disableInitializers, no-reinit
  - setHatStatus: admin path, eligibility-module path, stranger revert, both true/false transitions
  - batchSetHatStatus: success with per-hat events, length-mismatch revert, access control, empty arrays
  - getHatStatus: 0/1 return contract for Hats Protocol, unset default
  - transferAdmin: admin success, zero-address revert, stranger revert, eligibility-module also accepted
  - setEligibilityModule: admin-only (NOT also eligibility — explicit per source comment)
  - storage namespace: ERC-7201 slot at keccak256("poa.togglemodule.storage") confirmed via vm.load

Result: 23 passed, 0 failed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Direct test coverage for EligibilityModule (712 LoC, previously only
indirectly covered via DeployerTest deploy flow). Pairs with the
ToggleModule.t.sol shipped in the prior commit; together hits the
≥30-test acceptance criterion (combined 54 tests).

Coverage groups:
  - initialize: 6 tests (success, zero superAdmin, zero hats, event,
    _disableInitializers on impl, no-reinit)
  - pause/unpause: 5 tests (superAdmin paths, stranger reverts, paused
    view default, transition coverage)
  - transferSuperAdmin: 3 tests (success + old loses authority + new
    works, zero-address, stranger)
  - setUserJoinTime / setUserJoinTimeNow: 3 tests (superAdmin paths,
    block.timestamp anchor, stranger reverts)
  - setMaxDailyVouches: 3 tests (superAdmin path, zero-revert,
    stranger)
  - setEligibilityModuleAdminHat: 2 tests
  - setBulkWearerEligibility: 5 tests (empty array reverts, zero
    wearer reverts, superAdmin happy path with getWearerStatus
    verification, stranger reverts, hat-admin via MockHats path)
  - setDefaultEligibility: 3 tests (superAdmin, stranger reverts,
    paused reverts)
  - storage namespace: 1 test (verifies hats at base + superAdmin at
    base+1 of keccak256("poa.eligibilitymodule.storage"))

Tractable paths only — claimVouchedHat reentrancy + vouching rate-
limit edge cases need a heavier IHats fixture and remain out of scope
for this PR. Filed as follow-up scope if needed.

Result: 31 passed, 0 failed.
Combined with ToggleModule.t.sol (23): 54 tests, 0 failures.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ClawDAOBot ClawDAOBot marked this pull request as ready for review May 8, 2026 23:55
@ClawDAOBot ClawDAOBot changed the title test: ToggleModule + EligibilityModule unit coverage (#519, part 1: ToggleModule complete) test: ToggleModule + EligibilityModule unit coverage (#519 — 54 tests) May 8, 2026
…#519 deep coverage)

Adds 23 tests on top of the prior 31, plus a dedicated
EligibilityModuleReentrancyTest contract. Total now 55 EligibilityModule
tests + 23 ToggleModule = 78 tests on PR poa-box#157.

New coverage:
  - setWearerEligibility: happy path, zero-wearer revert, stranger
    revert, paused revert
  - clearWearerEligibility: revert-to-default behavior, zero/stranger
  - configureVouching + vouchFor: enable flow, quorum-reached eligibility
    flip, NotConfigured / CannotVouchForSelf / NotAuthorizedToVouch /
    AlreadyVouched / ZeroAddress / paused, epoch reset on reconfigure
  - claimVouchedHat: happy path mints hat, not-eligible reverts, paused
  - batchConfigureVouching: happy path + length-mismatch + stranger
  - Reentrancy attack via MaliciousHats: when claimVouchedHat calls
    hats.mintHat, the malicious IHats impl re-enters claimVouchedHat.
    nonReentrant on line 881 must block recursion. Test verifies the
    re-entry attempt happens once + reverts + the outer claim still
    mints exactly one hat (not double-claimed).

MockHats.mintHat marked `virtual` to allow MaliciousHats override.

Closes the deep-coverage scope vigil's cancelled #520 outlined (cat 1
missing functions + cat 2 vouching + cat 5 reentrancy attack).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant