Skip to main content

Smart Contracts

1

Select client contract

Choose between BasicPredicateClient or the default PredicateClient based on your policy needs
2

Inherit and implement

Your contract will inherit the selected client contract and implement the protected functions
3

Deploy your contract

Include the PredicateRegistry address and PolicyID in your deployment

Mental model

  • Predicated functions on your contract require an Attestation, produced by the Predicate API.
  • The contract, via PredicateClient or BasicPredicateClient, verifies the attestation onchain before executing business logic.
  • If the attestation is valid and unexpired, execution proceeds; otherwise the transaction reverts.
Both PredicateClient and BasicPredicateClient contracts leverage ERC-7201 namespaced storage for upgrade safety and are audited.

Installation

npm i @predicate/contracts

Examples

Recommended for simpler who-based policies. Some examples include AML/KYC, allowlist/denylist, and geo-restrictions.
Vault Example
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {BasicPredicateClient} from "@predicate/contracts/src/mixins/BasicPredicateClient.sol";
import {Attestation} from "@predicate/contracts/src/interfaces/IPredicateRegistry.sol";

contract Vault is BasicPredicateClient, Ownable {
    mapping(address => uint256) public balances;

    event Deposit(address indexed user, uint256 amount);

    constructor(
        address _owner,
        address _registry,
        string memory _policyID
    ) Ownable(_owner) {
        _initPredicateClient(_registry, _policyID);
    }

    function deposit(
        Attestation calldata _attestation
    ) external payable {
        // Basic authorization
        require(_authorizeTransaction(_attestation, msg.sender), "Unauthorized");

        balances[msg.sender] += msg.value;
        emit Deposit(msg.sender, msg.value);
    }

    // Admin functions
    function setPolicyID(string memory _policyID) external onlyOwner {
        _setPolicyID(_policyID);
    }

    function setRegistry(address _registry) external onlyOwner {
        _setRegistry(_registry);
    }
}

Deployment

After implementing the Predicate Client, you’ll need to set the Registry address and PolicyID.
  • _registry: The Predicate Registry address. See Supported Chains.
  • _policyID: The policy identifier generated from the predicate dashboard - you’ll get this in the next step.

Next Step: Dashboard Setup to configure your organization and policies.