This repository was archived by the owner on Feb 5, 2026. It is now read-only.
generated from ScopeLift/foundry-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Implement Permitter hook contract for KYC auctions #1
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…tions Adds EIP-712 signed permits for enforcing KYC approvals and bid caps on Uniswap CCA auctions. Includes PermitterFactory for CREATE2 deployments, comprehensive validation logic, and 69 tests covering units, integration, and fuzz scenarios. All tests passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
| uint256 public totalEthRaised; | ||
|
|
||
| /// @notice Owner address that can update caps and pause. | ||
| address public owner; |
Check warning
Code scanning / Slither
State variables that could be declared immutable Warning
Permitter.owner should be immutable
Comment on lines
33
to
54
| function predictPermitterAddress( | ||
| address trustedSigner, | ||
| uint256 maxTotalEth, | ||
| uint256 maxTokensPerBidder, | ||
| address owner, | ||
| bytes32 salt | ||
| ) external view returns (address) { | ||
| // Compute the final salt the same way as in createPermitter | ||
| bytes32 finalSalt = keccak256(abi.encodePacked(msg.sender, salt)); | ||
|
|
||
| // Compute the init code hash | ||
| bytes memory initCode = abi.encodePacked( | ||
| type(Permitter).creationCode, | ||
| abi.encode(trustedSigner, maxTotalEth, maxTokensPerBidder, owner) | ||
| ); | ||
| bytes32 initCodeHash = keccak256(initCode); | ||
|
|
||
| // Compute the CREATE2 address | ||
| return address( | ||
| uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), finalSalt, initCodeHash)))) | ||
| ); | ||
| } |
Check warning
Code scanning / Slither
Too many digits Warning
Comment on lines
63
to
120
| function validateBid( | ||
| address bidder, | ||
| uint256 bidAmount, | ||
| uint256 ethValue, | ||
| bytes calldata permitData | ||
| ) external returns (bool valid) { | ||
| // 1. CHEAPEST: Check if paused | ||
| if (paused) revert ContractPaused(); | ||
|
|
||
| // 2. Decode permit data | ||
| (Permit memory permit, bytes memory signature) = abi.decode(permitData, (Permit, bytes)); | ||
|
|
||
| // 3. CHEAP: Check time window | ||
| if (block.timestamp > permit.expiry) { | ||
| revert SignatureExpired(permit.expiry, block.timestamp); | ||
| } | ||
|
|
||
| // 4. MODERATE: Verify EIP-712 signature | ||
| address recovered = _recoverSigner(permit, signature); | ||
| if (recovered != trustedSigner) { | ||
| revert InvalidSignature(trustedSigner, recovered); | ||
| } | ||
|
|
||
| // 5. Check permit is for this bidder | ||
| if (permit.bidder != bidder) { | ||
| revert InvalidSignature(bidder, permit.bidder); | ||
| } | ||
|
|
||
| // 6. STORAGE READ: Check individual cap | ||
| uint256 alreadyBid = cumulativeBids[bidder]; | ||
| uint256 newCumulative = alreadyBid + bidAmount; | ||
| if (newCumulative > permit.maxBidAmount) { | ||
| revert ExceedsPersonalCap(bidAmount, permit.maxBidAmount, alreadyBid); | ||
| } | ||
|
|
||
| // Also check against global maxTokensPerBidder if it's lower | ||
| if (newCumulative > maxTokensPerBidder) { | ||
| revert ExceedsPersonalCap(bidAmount, maxTokensPerBidder, alreadyBid); | ||
| } | ||
|
|
||
| // 7. STORAGE READ: Check global cap | ||
| uint256 alreadyRaised = totalEthRaised; | ||
| uint256 newTotalEth = alreadyRaised + ethValue; | ||
| if (newTotalEth > maxTotalEth) { | ||
| revert ExceedsTotalCap(ethValue, maxTotalEth, alreadyRaised); | ||
| } | ||
|
|
||
| // 8. STORAGE WRITE: Update state | ||
| cumulativeBids[bidder] = newCumulative; | ||
| totalEthRaised = newTotalEth; | ||
|
|
||
| // 9. Emit event for monitoring | ||
| emit PermitVerified( | ||
| bidder, bidAmount, permit.maxBidAmount - newCumulative, maxTotalEth - newTotalEth | ||
| ); | ||
|
|
||
| return true; | ||
| } |
Check notice
Code scanning / Slither
Block timestamp Low
Permitter.validateBid(address,uint256,uint256,bytes) uses timestamp for comparisons
Dangerous comparisons:
- block.timestamp > permit.expiry
Dangerous comparisons:
- block.timestamp > permit.expiry
- Rename test_Reverts* to test_RevertIf_* for scopelint compliance - Fix fuzz tests that used vm.assume on array lengths causing too many rejections - Replace array fuzz params with bound() on numBids/seed for deterministic random generation - Apply scopelint formatting 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The lcov-reporter-action requires write permission to post coverage comments on PRs. Added the permissions block to the coverage job. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Coverage after merging rsolari/permit-hook-contract into main will be
Coverage Report
|
|||||||||||||||||||||||||
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Implements the Permitter hook contract system for enforcing KYC-based permissions and bid caps on Uniswap CCA token auctions. Features EIP-712 signed permits, CREATE2 factory deployment, and comprehensive validation logic.
Changes
Test Plan
forge testto verify all 69 tests pass🤖 Generated with Claude Code