Off-Chain Injection
Pattern where compliance servers sign permission certificates off-chain that users pass into smart contracts for on-chain validation.
Off-Chain Injection is a smart contract design pattern where regulatory compliance decisions are made by trusted off-chain servers that sign cryptographic permission certificates, which users then submit as calldata when executing on-chain transactions. The smart contract validates the signature, extracts the permission parameters, and executes the operation only if the certificate is valid. This pattern balances the privacy requirements of sensitive compliance data (KYC documents, accreditation status) with the finality and auditability of on-chain execution.
The pattern is fundamental to ERC-1594 and the broader ERC-1400 security token standard, where the transferWithData function accepts a bytes data parameter specifically designed for injecting off-chain compliance proofs.
The Problem: On-Chain vs. Off-Chain Compliance
Regulated securities require compliance checks before transfers: Is the recipient KYC-verified? Are they an accredited investor? Are they in a sanctioned jurisdiction? Does this transfer violate daily volume limits?
Pure On-Chain Approach: Storing all compliance data on-chain (as in ERC-3643) provides maximum transparency and composability but raises privacy concerns. Personal identification data on a public blockchain violates GDPR and exposes users to identity theft risks.
Pure Off-Chain Approach: Keeping compliance entirely off-chain (traditional centralized systems) loses the benefits of blockchain: no atomic settlement, no transparent audit trail, counterparty risk with the compliance provider.
Off-Chain Injection: Combines both approaches. Compliance decisions happen off-chain with full access to private data, but the cryptographic proof of that decision is verified on-chain, creating an immutable record that compliance was checked without revealing the underlying data.
Technical Implementation
The pattern uses EIP-712 structured data signing for secure, human-readable permission certificates:
1// Permission certificate structure2struct TransferPermission {3 address from;4 address to;5 uint256 amount;6 bytes32 partition;7 uint256 nonce;8 uint256 expiry;9 bytes32 complianceHash; // Hash of compliance check results10}1112// Domain separator for EIP-71213bytes32 public DOMAIN_SEPARATOR;1415// Trusted compliance signer16address public complianceSigner;1718// Nonce tracking to prevent replay19mapping(address => uint256) public nonces;
Transfer with Off-Chain Permission:
1function transferWithData(2 address to,3 uint256 amount,4 bytes calldata data5) external returns (bool) {6 // Decode the permission certificate7 (TransferPermission memory permit, bytes memory signature) =8 abi.decode(data, (TransferPermission, bytes));910 // Validate certificate11 require(permit.from == msg.sender, "Invalid sender");12 require(permit.to == to, "Recipient mismatch");13 require(permit.amount == amount, "Amount mismatch");14 require(permit.expiry > block.timestamp, "Certificate expired");15 require(permit.nonce == nonces[msg.sender]++, "Invalid nonce");1617 // Verify signature from trusted compliance server18 bytes32 structHash = keccak256(abi.encode(19 TRANSFER_PERMIT_TYPEHASH,20 permit.from,21 permit.to,22 permit.amount,23 permit.partition,24 permit.nonce,25 permit.expiry,26 permit.complianceHash27 ));2829 bytes32 digest = keccak256(abi.encodePacked(30 "\x19\x01",31 DOMAIN_SEPARATOR,32 structHash33 ));3435 address signer = ECDSA.recover(digest, signature);36 require(signer == complianceSigner, "Invalid compliance signature");3738 // Execute transfer39 _transfer(msg.sender, to, amount);4041 emit TransferWithCompliance(msg.sender, to, amount, permit.complianceHash);42 return true;43}
Off-Chain Compliance Server Flow
-
User Requests Permission: User's wallet contacts the compliance API with transfer details (from, to, amount, partition).
-
Compliance Check: Server queries internal databases:
- Is sender verified (KYC complete)?
- Is recipient verified?
- Are both parties in allowed jurisdictions?
- Does transfer comply with volume limits?
- Is the partition transferable?
-
Certificate Generation: If checks pass, server generates an EIP-712 typed data structure and signs it with its private key.
-
Certificate Delivery: Signed certificate is returned to the user's wallet.
-
On-Chain Submission: User calls
transferWithDatawith the signed certificate as thedataparameter. -
On-Chain Validation: Contract verifies signature, checks expiry/nonce, and executes transfer.
Security Considerations
Compliance Server Compromise: If the signing key is compromised, attackers can forge permission certificates for any transfer. Mitigation:
- Use HSMs (Hardware Security Modules) for key storage
- Implement key rotation with on-chain signer updates
- Use multi-sig for the compliance signer role
- Monitor for unusual certificate patterns
Replay Attacks: Without proper nonce management, a valid certificate could be reused. Mitigation:
- Per-sender nonce tracking (as shown above)
- Short certificate expiry windows (minutes, not days)
- Include transfer-specific data in the signed message
Certificate Front-Running: An attacker observing the mempool could extract a valid certificate and use it before the legitimate user. Mitigation:
- Bind certificates to
msg.sender(already done above) - Use private mempools (Flashbots) for sensitive transfers
- Include transaction nonce in the certificate
Expired Certificate Attacks: If expiry checking is missing or flawed, old certificates remain valid. Mitigation:
- Always check
block.timestamp < permit.expiry - Use reasonable expiry windows (5-30 minutes)
- Consider block number instead of timestamp for precision
Signature Malleability: ECDSA signatures can be manipulated to produce different valid signatures for the same message. Mitigation:
- Use OpenZeppelin's ECDSA library which handles malleability
- Store used signatures to prevent reuse
Compliance Server Availability: If the compliance server is down, no transfers can occur. Mitigation:
- Redundant server infrastructure
- Emergency bypass mechanism (controller override)
- Clear SLAs and monitoring
Comparison with On-Chain Compliance
| Aspect | Off-Chain Injection | On-Chain (ERC-3643) |
|---|---|---|
| Privacy | High (data stays off-chain) | Lower (claims on-chain) |
| Composability | Limited (needs server) | High (contracts can verify) |
| Latency | Higher (server round-trip) | Lower (direct call) |
| Availability | Server-dependent | Always available |
| Audit Trail | Certificate hash only | Full claim history |
| Gas Cost | Higher (signature verification) | Lower (storage reads) |
Advanced Patterns
Batch Certificates: For high-volume operations, a single certificate can authorize multiple transfers:
1struct BatchPermission {2 TransferPermission[] permits;3 bytes32 batchHash;4 uint256 expiry;5}
Delegated Permissions: Allow authorized parties to request certificates on behalf of token holders:
1struct DelegatedPermission {2 address operator; // Who can use this certificate3 address owner; // Actual token holder4 // ... other fields5}
Conditional Certificates: Include conditions that must be true at execution time:
1struct ConditionalPermission {2 // ... standard fields3 uint256 minPrice; // Only valid if oracle price > minPrice4 address priceOracle;5}
Audit Checklist for Off-Chain Injection
- Signature Verification: Is ECDSA recovery implemented correctly?
- Nonce Management: Are nonces properly incremented and checked?
- Expiry Validation: Is certificate expiry enforced?
- Parameter Binding: Are all relevant parameters included in signed data?
- Signer Management: How is the compliance signer updated? Timelocks?
- Replay Prevention: Can certificates be reused across chains (chainId in domain)?
- Front-Running Protection: Is the certificate bound to msg.sender?
- Fallback Mechanism: What happens if the compliance server is unavailable?
Off-chain injection represents a pragmatic middle ground for regulated token transfers, preserving the privacy of sensitive compliance data while maintaining the auditability and finality of blockchain execution. The pattern requires careful implementation of cryptographic primitives and robust off-chain infrastructure, but enables security tokens to operate within regulatory frameworks that would be impossible with purely on-chain approaches.
Articles Using This Term
Learn more about Off-Chain Injection in these articles:
Related Terms
EIP-712
Ethereum standard for structured data hashing and signing enabling human-readable transaction signatures with domain separation.
Security Token
Blockchain-based representation of regulated securities (equity, debt, real estate) requiring transfer restrictions and investor verification under securities law.
Modular Compliance
Pluggable smart contract architecture allowing regulatory rules (country bans, holder limits) to be updated without redeploying the token contract.
On-Chain Identity
Decentralized identity system (ONCHAINID) based on ERC-734/735 that decouples user identity from wallet addresses, enabling key rotation and portable credentials.
Need expert guidance on Off-Chain Injection?
Our team at Zealynx has deep expertise in blockchain security and DeFi protocols. Whether you need an audit or consultation, we're here to help.
Get a Quote

