Solidity library for creating compliant smart contracts application (e.g. Uniswap V4 hooks) using the Predicate network.
Predicate Contracts v2 provides a simplified, production-ready implementation for on-chain compliance verification through attestation-based validation. This version features:
- Simplified Architecture: Single
PredicateRegistrycontract replacing complex ServiceManager - Easy Integration:
PredicateClientmixin for seamless integration into your contracts - Multiple Patterns: Inheritance and Proxy patterns for different use cases
- Enhanced Security: ERC-7201 namespaced storage and statement-based validation
- Production Ready: Comprehensive test coverage and audit-ready code
See OVERVIEW.md for detailed technical documentation.
Integrate Predicate validation into your contract in 3 steps:
// 1. Import and inherit PredicateClient
import {PredicateClient} from "@predicate/mixins/PredicateClient.sol";
import {Attestation} from "@predicate/interfaces/IPredicateRegistry.sol";
contract MyContract is PredicateClient {
// 2. Initialize in constructor
constructor(address _registry, string memory _policy) {
_initPredicateClient(_registry, _policy);
}
// 3. Add attestation parameter and validate
function protectedFunction(
address recipient,
uint256 amount,
Attestation calldata _attestation // Add this
) external payable {
// Encode the internal function call
bytes memory encodedSigAndArgs = abi.encodeWithSignature(
"_internalFunction(address,uint256)",
recipient,
amount
);
// Validate the attestation
require(
_authorizeTransaction(_attestation, encodedSigAndArgs, msg.sender, msg.value),
"MyContract: unauthorized transaction"
);
// Execute business logic
_internalFunction(recipient, amount);
}
function _internalFunction(address recipient, uint256 amount) internal {
// Your business logic here
}
}See src/examples/ for complete working examples.
Predicate v2 supports multiple integration patterns:
- Location:
src/examples/inheritance/ - Best for: Direct control, minimal dependencies
- Contract directly inherits
PredicateClient - Lowest gas cost, most straightforward
- Location:
src/examples/proxy/ - Best for: Clean separation, upgradeability
- Separate proxy contract handles validation
- Business logic contract remains simple
See src/examples/README.md for detailed pattern documentation.
- PredicateRegistry: Core registry managing attesters, policies, and validation
- PredicateClient: Mixin contract for customer integration
- Statement: Data structure representing a transaction to be validated
- Attestation: Signed approval from an authorized attester
User Transaction
↓
Your Contract (with PredicateClient)
↓
_authorizeTransaction()
↓
PredicateRegistry.validateAttestation()
↓
Verify signature & policy
↓
Execute business logic
A Statement represents a claim about a transaction to be executed:
- UUID for replay protection
- Transaction parameters (sender, target, value, encoded function call)
- Policy identifier
- Expiration timestamp
An Attestation is a signed approval from an authorized attester:
- Matching UUID from the statement
- Attester address
- ECDSA signature over the statement hash
- Expiration timestamp
Predicate v2 emits comprehensive events for off-chain monitoring:
PredicateRegistry events:
AttesterRegistered/AttesterDeregistered- Attester managementPolicySet- Policy changes (emitted when client callssetPolicyID())StatementValidated- Successful attestation validations
PredicateClient events (from your contract):
PredicatePolicyIDUpdated- Track policy changes in your contractPredicateRegistryUpdated- Alert on registry address changes (security-critical)
Note: Transaction authorization is tracked via StatementValidated from PredicateRegistry (no duplicate event needed).
These events enable:
- 📊 Analytics and usage tracking
- 🔍 Audit trails and compliance monitoring
⚠️ Security alerts (unexpected policy/registry changes)- 🐛 Debugging and transaction analysis
v2 introduces several improvements over v1:
| Feature | v1 | v2 |
|---|---|---|
| Architecture | Multiple ServiceManager components | Single PredicateRegistry |
| Validation | Quorum-based | Single attester signature |
| Policies | Complex objects | Simple string identifiers |
| Replay Protection | Block-based nonces | UUID-based with expiration |
| Client Integration | Direct calls | PredicateClient mixin |
See OVERVIEW.md for detailed migration guide.
This repository depends on some submodules. Please run the following command before testing.
git submodule update --init --recursive$ forge install PredicateLabs/predicate-contracts npm install @predicate/predicate-contracts$ forge build$ forge test$ forge fmt$ forge snapshot$ anvil$ cast <subcommand>- OVERVIEW.md - Complete technical overview of v2 architecture
- PLAN.md - Pre-deployment checklist and task tracking
- src/examples/README.md - Integration patterns guide
- src/examples/ - Working code examples
Contributions are welcome! Please ensure:
- All tests pass:
forge test - Code is formatted:
forge fmt - Changes are documented
See LICENSE for details.
This library is provided as-is, without any guarantees or warranties. Use at your own risk.