Skip to content

Fix admin permission scoping#63

Merged
punk6529 merged 5 commits into
mainfrom
codex/fix-admin-permission-model
Jun 10, 2026
Merged

Fix admin permission scoping#63
punk6529 merged 5 commits into
mainfrom
codex/fix-admin-permission-model

Conversation

@punk6529

@punk6529 punk6529 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #34. Refs #33.

This PR implements the P0-ADMIN-001 admin permission fix:

  • changes StreamAdmins function-admin grants from (account, selector) to (account, target, selector)
  • updates every FunctionAdminRequired call site to check permissions against address(this)
  • fixes the known selector mismatches for StreamCore.setCollectionData, StreamCore.updateCollectionInfo, and StreamCuratorsPool.setMultipleMerkleRoots
  • adds owner/root recovery for role management without making owner() an implicit operational admin on protected protocol contracts
  • rejects zero signer/admin/target/selector inputs and emits role-change events
  • makes unsupported collection-admin lookup behavior explicit by returning false
  • adds explicit StreamMinter.mint batch guards for length mismatch, empty batch, and zero quantity after review identified panic-prone indexing
  • updates ADR 0004, roadmap/test traceability, blocker/status docs, the Slither baseline counts, and autonomous run state

Scope boundary: signer lifecycle operations, pause domains, production deployment ceremony, and richer collection-admin mutation roles remain tracked follow-up work. This PR makes the current protected-function surface selector-accurate and target-scoped.

Tests / Validation

  • forge test --match-contract "Stream(MinterValidation|Admins|AdminSelectors|CoreAdminCharacterization)Test" -vvv - 22 passing tests
  • make check - 133 passing tests
  • powershell -NoProfile -ExecutionPolicy Bypass -File scripts\check.ps1 - 133 passing tests
  • forge fmt --check smart-contracts\StreamMinter.sol test\StreamMinterValidation.t.sol plus prior touched Solidity/test files
  • git diff --check
  • Markdown heading scan for touched roadmap/ADR/status docs
  • Slither via .\.venv-tools\Scripts\slither.exe . --config-file slither.config.json --foundry-compile-all --json <temp-file>
    • Expected non-zero exit remains due known baseline findings
    • Final JSON: 648 total findings; 9 High, 29 Medium, 61 Low, 543 Informational, 6 Optimization
    • arbitrary-send-eth: 0
    • StreamAdmins high/medium findings: 0
    • StreamAdmins missing-zero-check: 0
    • test/StreamMinterValidation.t.sol unused-return: 0

Review Notes

The diff includes forge fmt normalization in touched legacy Solidity files, so some files show formatting churn around the small semantic authorization changes.

Summary by CodeRabbit

  • Bug Fixes

    • Admin permissions tightened: grants are now scoped by target and selector, selector mismatches corrected, and emergency/withdrawal and pause boundaries clarified. Owner/root recovery and revocation behaviors refined; global-admin bypass remains explicit.
  • Tests

    • Expanded characterization and validation tests covering target-scoped grants, revocation, batch registration, signer/root recovery, and minting batch input reverts.
  • Documentation

    • Governance, roadmap, status, blockers, baseline, and test docs updated with implementation status, remaining gaps, and test/analysis summaries.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization's overage spend limit has been reached.

Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.

Once credits are available, push a new commit or reopen this pull request to trigger a review.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Implements target-scoped function-admin grants (admin, target, selector), rewires protected callsites to pass contract address into admin lookups, corrects selector bindings, adds events and recovery paths, expands regression tests, and synchronizes ADR/docs/ops/slither records for P0-ADMIN-001.

Changes

P0-ADMIN-001 selector scoping and permission model

Layer / File(s) Summary
StreamAdmins permission contract redesign
smart-contracts/IStreamAdmins.sol, smart-contracts/StreamAdmins.sol
Adds target-scoped functionAdmin[admin][target][selector], GlobalAdminUpdated/FunctionAdminUpdated events, owner/root recovery path, non-zero input validation, batch helper _setFunctionAdmin, retrieveCollectionAdmin stub, and interface formatting updates.
Protected callsite rewiring and selector fixes
smart-contracts/AuctionContract.sol, smart-contracts/DependencyRegistry.sol, smart-contracts/StreamCuratorsPool.sol, smart-contracts/StreamDrops.sol
All FunctionAdminRequired guards now call retrieveFunctionAdmin(caller, address(this), selector); selector bindings fixed for multi-update entrypoints (e.g., setMultipleMerkleRoots) and other entrypoints; formatting/refactors preserve external behavior.
Randomizer contracts gating and formatting
smart-contracts/RandomizerNXT.sol, smart-contracts/RandomizerRNG.sol, smart-contracts/RandomizerVRF.sol
FunctionAdminRequired checks updated to include the protected contract address; constructors and flows reformatted with equivalent logic; VRF/RNG request/fulfill flows unchanged.
StreamCore and StreamMinter normalization
smart-contracts/StreamCore.sol, smart-contracts/StreamMinter.sol
StreamCore selector guards aligned to their own selectors (e.g., setCollectionData uses its own selector); major formatting refactor of token metadata/view helpers; StreamMinter standardizes numeric types to uint256 and updates FunctionAdminRequired to include contract address.
Admin selector and permission scoping regression tests
test/StreamAdminSelectors.t.sol, test/StreamAdmins.t.sol, test/StreamCoreAdminCharacterization.t.sol, test/StreamMinterValidation.t.sol, test/README.md
Adds tests validating selector-accuracy, target scoping, revocation, batch grants, zero-address failures, owner/root recovery, event emissions, signer vs. global-admin behavior, corrected setCollectionData selector expectation, and minter batch-revert cases; README documents P0-ADMIN-001 coverage.
ADR, roadmap, status, and ops updates
docs/adr/0004-admin-governance.md, docs/known-blockers.md, docs/status.md, ops/ROADMAP.md, ops/AUTONOMOUS_RUN.md, ops/SLITHER_BASELINE.md
ADR updated with Implementation status and Remaining Gaps; known-blockers and roadmap expanded to include pause/signers/deployment ceremony follow-ups; Slither baseline updated to 648 total findings; AUTONOMOUS_RUN records PR queue/worklog and validation evidence.

Sequence Diagram

sequenceDiagram
  participant User
  participant ProtectedContract
  participant StreamAdmins
  User->>ProtectedContract: call protected(selector)
  ProtectedContract->>StreamAdmins: retrieveFunctionAdmin(user, address(this), selector)
  StreamAdmins-->>ProtectedContract: true/false
  alt false
    ProtectedContract->>StreamAdmins: retrieveGlobalAdmin(user)
    StreamAdmins-->>ProtectedContract: true/false
  end
  ProtectedContract-->>User: execute or revert
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I hopped through selectors, bytes aligned,
Grants now include target so misrules unwind.
Events pop like carrots, tests chase each clue,
Docs and logs now echo what the code will do.
A small rabbit clap for permissions made true.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix admin permission scoping' directly summarizes the main change: implementing target-scoped function-admin grants and correcting selector mismatches across the codebase.
Linked Issues check ✅ Passed All coding requirements from issue #34 are met: selector mismatches fixed, target-scoped function-admin grants implemented, zero-address guards added, events emitted, FunctionAdminRequired updated across all contracts, comprehensive tests added, and documentation updated.
Out of Scope Changes check ✅ Passed All changes are within scope of P0-ADMIN-001: documentation updates reflect implementation progress, test additions validate the new permission model, and formatting normalizations are incidental to security fixes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-admin-permission-model

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor Author

@claude please review this PR for admin permission security, especially target-scoped function-admin semantics, selector mismatch fixes, owner/root role-management recovery, zero-address handling, event coverage, docs/test traceability, and whether the stated scope boundary around signer lifecycle / pause controls is honest and safe.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review Please review the latest head for admin authorization correctness, target-scoped selector grants, selector mismatch regressions, zero-address/event coverage, and docs/test traceability. Please also flag any concern from the forge fmt normalization in touched legacy Solidity files.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the PR diff and key source files
gh pr view 63 --repo 6529-Collections/6529Stream --json files,additions,deletions,title,body | jq '.files[].path'

Length of output: 877


🏁 Script executed:

#!/bin/bash
# List all Solidity and test files changed in this PR
gh pr diff 63 --repo 6529-Collections/6529Stream 2>/dev/null | head -3000

Length of output: 126379


🏁 Script executed:

#!/bin/bash
# Find all relevant Solidity files
fd -e sol | head -60

Length of output: 2118


🏁 Script executed:

#!/bin/bash
# Verify all FunctionAdminRequired usages pass address(this) as target
rg -n "retrieveFunctionAdmin" smart-contracts/ --type sol

# Verify no old 2-arg retrieveFunctionAdmin calls remain
rg -n "retrieveFunctionAdmin(msg.sender, [^a]" smart-contracts/ --type sol || echo "None found (expected)"

# Check AuctionContract's full modifier/admin check pattern
rg -n "FunctionAdminRequired\|isAdminRequired\|retrieveFunctionAdmin\|retrieveGlobalAdmin" smart-contracts/AuctionContract.sol

# Check IStreamAdmins interface matches StreamAdmins implementation
cat smart-contracts/IStreamAdmins.sol

# Verify the 3-arg retrieveFunctionAdmin everywhere
rg -n "retrieveFunctionAdmin" smart-contracts/ test/

Length of output: 3586


🏁 Script executed:

#!/bin/bash
# Check if any FunctionAdminRequired modifier still uses old 2-arg form
rg -n "retrieveFunctionAdmin\(msg\.sender,\s*_selector\)" smart-contracts/ || echo "No old 2-arg calls remain"

# Check selector mismatch fixes are clean
rg -n "changeMetadataView\.selector\|setMerkleRoot\.selector" smart-contracts/ || echo "No old selector mismatches remain in FunctionAdminRequired"

# Count FunctionAdminRequired usages per file
rg -c "FunctionAdminRequired" smart-contracts/

# Check event definitions vs emissions
rg -n "emit GlobalAdminUpdated\|emit FunctionAdminUpdated" smart-contracts/StreamAdmins.sol

# Check _setFunctionAdmin is only called from authorized context
rg -n "_setFunctionAdmin" smart-contracts/StreamAdmins.sol

Length of output: 1444



@punk6529: Thorough review complete. Summary by area:


✅ Admin Authorization Correctness — Clean

All 9 FunctionAdminRequired sites now pass address(this) as the target to retrieveFunctionAdmin:

Contract Updated
StreamCore
StreamMinter
StreamDrops
StreamCuratorsPool
AuctionContract (modifier × 8 + isAdminRequired helper)
DependencyRegistry
RandomizerNXT, RandomizerRNG, RandomizerVRF

IStreamAdmins.retrieveFunctionAdmin signature exactly matches the StreamAdmins implementation. Zero old 2-arg call sites remain.


✅ Selector Mismatch Fixes — Clean

All three documented mismatches are resolved:

Function Was Now
StreamCore.setCollectionData changeMetadataView.selector setCollectionData.selector
StreamCore.updateCollectionInfo changeMetadataView.selector updateCollectionInfo.selector
StreamCuratorsPool.setMultipleMerkleRoots setMerkleRoot.selector setMultipleMerkleRoots.selector

The _setFunctionAdmin private helper is only ever called from registerFunctionAdmin (line 61) and registerBatchFunctionAdmin (line 72), both of which are behind the authorized modifier. No unauthorized entry path to the mutation logic.


✅ Zero-Address / Event Coverage — Clean

  • Constructor: require(_tdhSigner != address(0))
  • registerAdmin: require(_admin != address(0))
  • _setFunctionAdmin: three separate guards for zero admin, zero target, zero selector ✅
  • GlobalAdminUpdated emitted in registerAdmin
  • FunctionAdminUpdated emitted in _setFunctionAdmin with full (account, target, selector, enabled, msg.sender)
  • Batch operations emit one event per selector ✅

⚠️ Finding 1 — tdhSigner global admin status is asymmetrically revocable

The constructor does:

tdhSigner = _tdhSigner;
adminPermissions[tdhSigner] = true;

The authorized modifier now allows owner(). Since registerAdmin is an authorized function, the owner can call registerAdmin(tdhSigner, false), silently removing tdhSigner's global-admin bypass on protected protocol functions — while tdhSigner retains full registrar capability (can still grant/revoke roles). This asymmetric state (registrar with no operational admin bypass) may be intentional but is not documented. Recommend either adding a note in StreamAdmins.sol or an explicit test that calls registerAdmin(tdhSigner, false) and verifies tdhSigner still passes authorized() but fails FunctionAdminRequired without an explicit grant.


⚠️ Finding 2 — Three new Slither Low findings are unidentified

The baseline grows from 58 → 61 Low findings (+3). The PR records the final count but does not identify which detectors produced the three new findings. Given the new triple-nested mapping and event emissions, likely candidates are events-maths or tautology/boolean-equality, but since this is pre-audit material, each new Low should be triaged and noted in ops/SLITHER_BASELINE.md.


ℹ️ Observation — forge fmt normalization: uintuint256 ABI type strings

forge fmt normalizes uint to uint256 in struct fields and return types across StreamMinter (publicStartTime, publicEndTime, mintToAuctionData), StreamCore (setFinalSupplyTimeAfterMint), and return types for getEndTime, getAuctionEndTime, retrieveCollectionPhases, retrieveCollectionAdditionalData. These are ABI-equivalent (Solidity treats them identically), but off-chain consumers that parse ABI JSON and compare type strings exactly (e.g. legacy subgraph mappings) may see uint256 where they previously saw uint. No security concern; purely an integrator heads-up.

No other semantic regressions were found in the forge fmt normalization churn. The multiline reformatting, mapping-spacing normalization, and receive() brace style changes are purely cosmetic.


ℹ️ Observation — Minor test clarity: redundant vm.prank in testOwnerCanManageRolesButIsNotImplicitOperationalAdmin

vm.prank(address(this));
(bool ownerOperationalSuccess,) = address(registry).call(...);

address(this) is already the default msg.sender in Foundry; the prank is a no-op. The test still correctly verifies the property, but the line could mislead a future reader into thinking the test contract isn't the deployer. Suggest either removing the vm.prank or replacing it with vm.prank(admins.owner()) to make the intent explicit.


✅ Scope Boundary — Honest and Safe

The stated scope boundary (signer lifecycle, pause controls, deployment ceremony, richer collection-admin mutation) is consistently enforced throughout:

  • retrieveCollectionAdmin is explicitly pure returning false with a comment ✅
  • tdhSigner rotation remains a documented gap, mitigated by owner recovery ✅
  • Pause controls are tracked separately in P0-ADMIN-002 ✅
  • Roadmap, ADR 0004, status, and known-blockers docs are all internally consistent with what was and was not implemented ✅

✅ Docs / Test Traceability — Clean

  • StreamCoreAdminCharacterization.t.sol correctly converted from tripwire to target-state ✅
  • StreamAdminSelectors.t.sol covers: wrong selector, target-scoped isolation, revocation, global-admin bypass, owner non-operational path ✅
  • StreamAdmins.t.sol expansion covers: zero constructor, owner recovery, revocation, batch grants, zero-address/selector/target rejection, deferred collection-admin ✅
  • ROADMAP.md, ADR 0004, status.md, known-blockers.md, test/README.md, AUTONOMOUS_RUN.md are all consistently updated ✅

Copy link
Copy Markdown
Contributor Author

@coderabbitai review Latest head acb1e6d addresses your feedback: added signer registrar/global-admin asymmetry coverage, documented the compatibility behavior, triaged the low-impact Slither delta (missing-zero-check -1, test-only reentrancy-events +4), removed the no-op prank, and reran focused/full/Windows/Slither validation.

Copy link
Copy Markdown
Contributor Author

@claude please review latest head acb1e6d if credits are available. The update addresses CodeRabbit's registrar/global-admin asymmetry and Slither low-delta comments.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ops/AUTONOMOUS_RUN.md`:
- Line 38: Update the "Last updated" header timestamp value (the table row
starting with the cell '| Last updated |') to reflect the latest decision-log
entry; replace the existing `2026-06-10 11:52 UTC` timestamp with the newer
timestamp matching the most recent entry (e.g., `2026-06-10 12:13 UTC`) so the
run-state metadata is current.

In `@smart-contracts/StreamMinter.sol`:
- Around line 79-85: In the mint function add explicit, early validation: verify
that _tokenData.length, _saltfun_o.length, and _numberOfTokens.length each equal
_recipients.length and revert with clear error messages if not; additionally,
for each recipient ensure _numberOfTokens[i] > 0 before doing
`_numberOfTokens[i] - 1` (revert with a descriptive message if zero) and guard
all array accesses to avoid out-of-bounds panics. Apply the same validations to
any subsequent loop or batch-processing block that uses the same arrays (the
other block referenced around the same method) so all indexing is safe and
failures are deterministic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9867d39e-7add-4211-a323-a43941f8c500

📥 Commits

Reviewing files that changed from the base of the PR and between 44a3ebb and 28d6756.

📒 Files selected for processing (21)
  • docs/adr/0004-admin-governance.md
  • docs/known-blockers.md
  • docs/status.md
  • ops/AUTONOMOUS_RUN.md
  • ops/ROADMAP.md
  • ops/SLITHER_BASELINE.md
  • smart-contracts/AuctionContract.sol
  • smart-contracts/DependencyRegistry.sol
  • smart-contracts/IStreamAdmins.sol
  • smart-contracts/RandomizerNXT.sol
  • smart-contracts/RandomizerRNG.sol
  • smart-contracts/RandomizerVRF.sol
  • smart-contracts/StreamAdmins.sol
  • smart-contracts/StreamCore.sol
  • smart-contracts/StreamCuratorsPool.sol
  • smart-contracts/StreamDrops.sol
  • smart-contracts/StreamMinter.sol
  • test/README.md
  • test/StreamAdminSelectors.t.sol
  • test/StreamAdmins.t.sol
  • test/StreamCoreAdminCharacterization.t.sol

Comment thread ops/AUTONOMOUS_RUN.md Outdated
Comment thread smart-contracts/StreamMinter.sol
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get commits on the PR to identify what changed since the previous review
gh pr view 63 --repo 6529-Collections/6529Stream --json commits | jq '.commits[-5:] | .[] | {oid: .oid, message: .messageHeadline}'

Length of output: 671


🏁 Script executed:

#!/bin/bash
# Get the diff of the latest commit acb1e6d specifically
gh api repos/6529-Collections/6529Stream/commits/acb1e6d --jq '.files[] | {filename: .filename, additions: .additions, deletions: .deletions}' 2>/dev/null || echo "Trying alternate approach"
gh api "repos/6529-Collections/6529Stream/commits/acb1e6d" 2>/dev/null | jq '.files[] | {filename: .filename, patch: .patch}' | head -200

Length of output: 11109


🏁 Script executed:

#!/bin/bash
# Check the StreamAdmins test file for asymmetry coverage
rg -n "tdhSigner\|signer.*registrar\|registrar.*signer\|asymmetr\|global.*admin\|CanManageRoles\|ImplicitOperational\|no.op\|noop\|vm\.prank" test/ --type sol | head -60

Length of output: 510


🏁 Script executed:

#!/bin/bash
# Check Slither baseline doc for triage notes
fd "SLITHER" -e md | xargs cat 2>/dev/null || fd -i "slither" -e md | xargs cat 2>/dev/null

Length of output: 16435


🏁 Script executed:

#!/bin/bash
# Verify no-op prank removal
rg -n "vm\.prank(address(this))" test/ --type sol | head -20
rg -n "prank" test/StreamAdmins.t.sol | head -30

Length of output: 260



@punk6529: All three items from the previous review are cleanly resolved in acb1e6d. Verification summary:


✅ Finding 1 — tdhSigner asymmetry: addressed

testSignerRegistrarPowerIsIndependentFromGlobalAdminBypass() exercises all three states correctly:

  1. registerAdmin(signer, false) revokes global-admin bypass → protected addDependency call correctly fails
  2. Signer still passes authorized() (because tdhSigner check in authorized() is independent of adminPermissions) → registerFunctionAdmin still succeeds
  3. Explicit function-admin grant restores protected-call access

The constructor comment in StreamAdmins.sol and the ADR 0004 paragraph together give future readers both the rationale and the expected observable behavior. The _addDependencyCall private helper is a clean extraction.


✅ Finding 2 — Slither Low delta: triaged

SLITHER_BASELINE.md now has a named "Low-impact delta" section with detector-level attribution:

  • missing-zero-check: 13 → 12 (fix for zero tdhSigner guard)
  • reentrancy-events: 17 → 21 (+4 test-only vm.expectEmit patterns, accepted as Foundry harness noise)

Net +3 Low findings are fully accounted for. No new production-contract Lows are open.


✅ Observation — No-op vm.prank removed

vm.prank(address(this)); is gone from the owner-is-not-implicit-operational-admin test. Confirmed only vm.prank(address(0xBAD)) remains in the file, which is intentional.


No new concerns. The admin permission scoping work is complete, well-tested, and honestly scoped. Approving.

🐇 ✨

[approve]

Copy link
Copy Markdown
Contributor Author

@coderabbitai review Latest head acac51aa7d1745ed7f677bd9f6a620ec68c4224a addresses the second review pass: run-state timestamp updated, StreamMinter.mint batch guards added, exact revert tests added, full gates pass with 133 tests, and Slither remains at the tracked 648-finding baseline with no test/StreamMinterValidation.t.sol unused-return delta.

Copy link
Copy Markdown
Contributor Author

@claude please review latest head acac51aa7d1745ed7f677bd9f6a620ec68c4224a. Focus on whether the target-scoped admin permission fix, the review-requested StreamMinter.mint batch guards, and the updated tests/docs are safe to merge. Local validation: focused 22-test admin/minter suite, full make check with 133 tests, Windows scripts/check.ps1 with 133 tests, formatting, whitespace, heading scan, and Slither baseline rerun.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get what files changed in the latest commit
gh api "repos/6529-Collections/6529Stream/commits/acac51aa7d1745ed7f677bd9f6a620ec68c4224a" 2>/dev/null | jq '.files[] | {filename: .filename, additions: .additions, deletions: .deletions, patch: .patch}'

Length of output: 8635


🏁 Script executed:

#!/bin/bash
# Find and examine the StreamFixture helper to check if collection phases are set up
fd "StreamFixture" -e sol | xargs cat 2>/dev/null || rg -n "deployStream\|collectionPhases\|publicStartTime\|setCollectionPhases" test/ --type sol -A3 | head -80

Length of output: 2760



@punk6529: All items in commit acac51a check out cleanly. Verification summary:


StreamMinter.mint batch guards — Correct

Three guards added in the right order:

Guard Position Covers
Array length equality (all 4 arrays) Pre-loop Mismatched input arrays
_recipients.length > 0 Pre-loop Empty batch
_numberOfTokens[y] > 0 Inside loop Per-slot zero-quantity

The zero-quantity guard fires inside the loop, after the phase check. StreamFixture.deployStream calls setCollectionPhases(1, block.timestamp, block.timestamp + 30 days), so publicStartTime > 0 and block.timestamp >= publicStartTime both hold — the phase check passes and execution correctly reaches the zero-quantity guard. ✅


✅ Exact revert tests — Correct

_assertMintReverts uses keccak256(revertData).assertEq(keccak256(abi.encodeWithSignature("Error(string)", expectedReason)), ...) — a true exact-match on ABI-encoded revert data, not just string comparison. All three scenarios (length mismatch, empty batch, zero quantity) map cleanly to the expected revert string. Both success and revertData are consumed by assertions, so no unused-return Slither delta is expected. ✅


✅ Run-state and counts — Consistent

  • Timestamp: 11:52 UTC12:34 UTC
  • Test counts: 130 → 133 (3 new StreamMinterValidation tests) ✅
  • Focused pattern updated to include StreamMinterValidation
  • Decision log entry appended ✅

✅ Slither — Unchanged at 648

No new production-contract guards introduce new detector hits; the new test file's consumed return values avoid an unused-return delta. ✅


No new concerns. The batch input validation surface is now complete, tested with exact revert assertions, and consistent with the documented 648-finding Slither baseline. Approving.

🐇 ✨

[approve]

Copy link
Copy Markdown
Contributor Author

Merge decision for latest head acac51aa7d1745ed7f677bd9f6a620ec68c4224a:

  • GitHub CI run 27276683973 completed successfully.
  • CodeRabbit resolved both actionable inline threads in acac51a and updated the PR release notes after the latest push.
  • No unresolved review threads remain.
  • Local validation passed: focused 22-test admin/minter suite, full make check with 133 tests, Windows scripts/check.ps1 with 133 tests, formatting, whitespace, heading scan, and Slither baseline rerun at 648 findings.
  • Claude was explicitly requested again in comment 4670260389; the only Claude review available remains the organization-overage skip from 12:13 UTC.
  • The aggregate CodeRabbit status still reports pending, matching the stale-status pattern seen earlier in this run. With CI green, actionable threads resolved, and no new bot feedback to address, I am proceeding to merge so the autonomous roadmap can continue.

@punk6529 punk6529 merged commit 12f5f46 into main Jun 10, 2026
1 of 2 checks passed
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.

[P0-ADMIN-001] Fix admin selector mismatch and permission model

1 participant