Overview
SignatureGatingPreIntentHook is a pre-intent hook that validates taker eligibility using off-chain signatures. It enables depositors to control who can signal intents against their deposits without maintaining on-chain whitelists.
Contract Location: contracts/hooks/SignatureGatingPreIntentHook.sol
Interface: IPreIntentHook
Compatible With: OrchestratorV2 (pre-intent hooks only supported in V2)
Use Cases
Dynamic Access Control
Allow takers based on off-chain criteria:- KYC/AML compliance checks
- Credit scoring
- Rate limiting
- Time-based access
- Custom business logic
Selective Liquidity Provision
Depositors can:- Gate intents to verified users only
- Implement per-taker limits
- Control access without gas costs for whitelist updates
- Revoke access instantly by not signing new requests
Privacy-Preserving Gating
Off-chain signatures enable:- Private eligibility criteria (not visible on-chain)
- Dynamic policy changes without transactions
- Reduced on-chain footprint
Architecture
Two-Phase Authorization
- Setup Phase: Depositor sets authorized signer for their deposit
- Signal Phase: Taker obtains signature from signer and includes it in
signalIntent
Signature Payload
The signature commits to:- Orchestrator address (prevents cross-orchestrator replay)
- Escrow and deposit ID (binds to specific deposit)
- Intent amount (prevents amount manipulation)
- Taker address (binds signature to specific user)
- Recipient address (prevents redirection)
- Payment method and fiat currency
- Conversion rate (prevents rate manipulation)
- Referrer and fees
- Signature expiration (time-bound validity)
- Chain ID (prevents cross-chain replay)
Data Structures
PreIntentHookData
Passed inSignalIntentParams.preIntentHookData:
signature: EIP-191 signed message hash from the authorized signersignatureExpiration: Timestamp after which signature is invalid
Storage
Deposit Signer Mapping
address(0) to disable gating.
Functions
setDepositSigner
Sets or clears the authorized signer for a deposit._escrow: Escrow contract address_depositId: Deposit ID_signer: Authorized signer address (useaddress(0)to remove)
getDepositSigner
Returns the authorized signer for a deposit.validateSignalIntent
Validates the signature when taker signals intent (called by orchestrator).- Verify caller is authorized orchestrator
- Retrieve authorized signer for deposit
- Decode signature and expiration from
_ctx.preIntentHookData - Verify signature has not expired
- Reconstruct signed message from context
- Verify signature is from authorized signer
UnauthorizedOrchestratorCaller: Caller is not an authorized orchestratorSignerNotSet: No signer configured for this depositSignatureExpired: Signature timestamp has passedInvalidSignature: Signature verification failed
Usage
Setup: Deploy and Configure
1. Deploy Hook:Off-Chain: Generate Signature
The authorized signer generates signatures off-chain: TypeScript/JavaScript Example:On-Chain: Signal Intent with Signature
Taker calls signalIntent with signature:Execution Flow
Events
DepositSignerSet
Emitted when signer is set or updated:escrow: Escrow contract addressdepositId: Deposit IDsigner: New signer address (or address(0) if removed)setter: Address that called setDepositSigner (owner or delegate)
Errors
Security Considerations
Signature Expiration
Always set reasonable expiration times:- Too short: Taker may not have time to submit transaction
- Too long: Increases replay window if conditions change
- Recommended: 5-60 minutes depending on use case
Replay Protection
Signature commits to:- Chain ID: Prevents cross-chain replay
- Orchestrator address: Prevents cross-orchestrator replay
- Deposit ID: Binds to specific deposit
- Taker address: Binds to specific user
- All intent parameters: Prevents parameter manipulation
Signer Key Security
Signer private key should:- Be stored securely (HSM, secure enclave, or encrypted storage)
- Not be reused for other purposes
- Have revocation mechanism (change signer via
setDepositSigner) - Be rotated periodically
Signature Verification
The hook uses OpenZeppelin’sSignatureChecker which supports:
- EOA signatures (ECDSA)
- Smart contract signatures (EIP-1271)
DoS Considerations
Preventing DoS:- Signatures expire automatically (no need to revoke)
- Signer can be changed instantly by depositor
- No on-chain storage per signature (gas-efficient)
- Rate limit signature generation off-chain
- Monitor for signature request abuse
- Implement IP-based or account-based throttling in signer service
Implementation Examples
Example 1: KYC Gating
Setup:Example 2: Rate Limiting
Off-chain Rate Limiter:Example 3: Time-Based Access
Comparison with Whitelist Hook
| Feature | SignatureGatingHook | WhitelistHook |
|---|---|---|
| Gas Cost | No gas for eligibility changes | Gas required to add/remove addresses |
| Privacy | Criteria can be off-chain | All addresses visible on-chain |
| Flexibility | Dynamic, per-request validation | Static list |
| Revocation | Automatic via expiration | Requires transaction |
| Scalability | Unlimited users | Limited by gas costs |
| Complexity | Requires off-chain signer service | Pure on-chain |
| Best For | Dynamic criteria, KYC, rate limiting | Small, stable user sets |
Related Contracts
- Hooks Overview - Hook system architecture
- WhitelistPreIntentHook - Alternative on-chain whitelist
- OrchestratorV2 - V2 orchestrator with pre-intent hooks
- OrchestratorRegistry - Authorized orchestrator registry