Skip to main content

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

  1. Setup Phase: Depositor sets authorized signer for their deposit
  2. 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 in SignalIntentParams.preIntentHookData:
Fields:
  • signature: EIP-191 signed message hash from the authorized signer
  • signatureExpiration: Timestamp after which signature is invalid

Storage

Deposit Signer Mapping

Each deposit can have one authorized signer. Set to address(0) to disable gating.

Functions

setDepositSigner

Sets or clears the authorized signer for a deposit.
Parameters:
  • _escrow: Escrow contract address
  • _depositId: Deposit ID
  • _signer: Authorized signer address (use address(0) to remove)
Authorization: Only callable by deposit owner or delegate Events:
Example:

getDepositSigner

Returns the authorized signer for a deposit.

validateSignalIntent

Validates the signature when taker signals intent (called by orchestrator).
Validation Steps:
  1. Verify caller is authorized orchestrator
  2. Retrieve authorized signer for deposit
  3. Decode signature and expiration from _ctx.preIntentHookData
  4. Verify signature has not expired
  5. Reconstruct signed message from context
  6. Verify signature is from authorized signer
Reverts:
  • UnauthorizedOrchestratorCaller: Caller is not an authorized orchestrator
  • SignerNotSet: No signer configured for this deposit
  • SignatureExpired: Signature timestamp has passed
  • InvalidSignature: Signature verification failed

Usage

Setup: Deploy and Configure

1. Deploy Hook:
2. Set Signer for Deposit:
3. Configure Deposit to Use Hook:

Off-Chain: Generate Signature

The authorized signer generates signatures off-chain: TypeScript/JavaScript Example:
Python Example:

On-Chain: Signal Intent with Signature

Taker calls signalIntent with signature:

Execution Flow

Events

DepositSignerSet

Emitted when signer is set or updated:
Parameters:
  • escrow: Escrow contract address
  • depositId: Deposit ID
  • signer: 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
Example:

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
For production:

Signature Verification

The hook uses OpenZeppelin’s SignatureChecker which supports:
  • EOA signatures (ECDSA)
  • Smart contract signatures (EIP-1271)
This allows both externally owned accounts and smart contracts to act as signers.

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)
Attack mitigation:
  • 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:
Off-chain KYC Service:

Example 2: Rate Limiting

Off-chain Rate Limiter:

Example 3: Time-Based Access

Comparison with Whitelist Hook