> ## Documentation Index
> Fetch the complete documentation index at: https://docs.predicate.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 3. Onchain Enforcement

> Deploy a Predicate-enabled smart contract

Onchain enforcement requires users to submit valid attestations to your smart contract. The contract verifies the attestation before executing protected business logic.

<Steps>
  <Step title="Deploy your contract">
    Inherit from `PredicateClient` and set your `verification_hash` as the `policyID`.
  </Step>

  <Step title="Add contract to dashboard">
    Register your contract address in the dashboard to link it to your project.
  </Step>
</Steps>

***

<Tabs>
  <Tab title="EVM">
    ## Installation

    <CodeGroup>
      ```bash Hardhat theme={null}
      npm i @predicate/contracts
      ```

      ```bash Foundry theme={null}
      forge install PredicateLabs/predicate-contracts
      ```
    </CodeGroup>

    ## Choose Your Client

    | Client                 | Use Case                                                                 |
    | ---------------------- | ------------------------------------------------------------------------ |
    | `BasicPredicateClient` | Who-based policies: AML/KYC, allowlist/denylist, geo-restrictions        |
    | `PredicateClient`      | Policies that validate function calls, parameters, or value-based limits |

    <Info>
      Both clients use ERC-7201 namespaced storage for upgrade safety and are audited.
    </Info>

    ## Example Contract

    Set your `verification_hash` from the dashboard as the `policyID` when deploying.

    <Tabs>
      <Tab title="BasicPredicateClient">
        ```solidity theme={null}
        // 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;

            constructor(
                address _owner,
                address _registry,
                string memory _policyID  // Use your verification_hash here
            ) Ownable(_owner) {
                _initPredicateClient(_registry, _policyID);
            }

            function deposit(Attestation calldata _attestation) external payable {
                require(_authorizeTransaction(_attestation, msg.sender), "Unauthorized");
                balances[msg.sender] += msg.value;
            }

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

            function setRegistry(address _registry) external onlyOwner {
                _setRegistry(_registry);
            }
        }
        ```
      </Tab>

      <Tab title="PredicateClient">
        ```solidity theme={null}
        // SPDX-License-Identifier: BUSL-1.1
        pragma solidity 0.8.28;

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

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

            constructor(
                address _owner,
                address _registry,
                string memory _policyID  // Use your verification_hash here
            ) Ownable(_owner) {
                _initPredicateClient(_registry, _policyID);
            }

            function deposit(
                uint256 _amount,
                Attestation calldata _attestation
            ) external payable {
                bytes memory encodedSigAndArgs = abi.encodeWithSignature(
                    "_deposit(uint256)",
                    _amount
                );

                require(
                    _authorizeTransaction(_attestation, encodedSigAndArgs, msg.sender, msg.value),
                    "Unauthorized"
                );

                require(msg.value == _amount, "Incorrect ETH amount");
                balances[msg.sender] += _amount;
            }

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

            function setRegistry(address _registry) external onlyOwner {
                _setRegistry(_registry);
            }
        }
        ```
      </Tab>
    </Tabs>

    ## Constructor Parameters

    | Parameter   | Description                                                                                                                |
    | ----------- | -------------------------------------------------------------------------------------------------------------------------- |
    | `_registry` | Predicate Registry address for your chain. See [Supported Blockchains](/v2/applications/quickstart#supported-blockchains). |
    | `_policyID` | Your `verification_hash` from the dashboard                                                                                |

    ***

    ## Add Contract to Dashboard

    After deploying, add your contract address to your project in the dashboard. This links your contract to your policy configuration.
  </Tab>

  <Tab title="SVM">
    ## Solana Program Integration

    Predicate provides an Anchor-based program for Solana that handles attestation validation onchain.

    ### Installation

    ```bash theme={null}
    git clone https://github.com/PredicateLabs/sol-contracts
    cd sol-contracts
    anchor build
    ```

    ### Integration Overview

    The Solana implementation uses Program Derived Addresses (PDAs) for:

    * **Policy Accounts**: Policies associated with program addresses
    * **Attestor Accounts**: Registered attestors who can sign attestations
    * **Used UUID Accounts**: Replay protection via PDA existence checks

    ### Example Usage

    ```rust theme={null}
    invoke(
        &validate_attestation(
            registry_pda,
            attestor_account,
            policy_account,
            target_program,
            msg_value,
            encoded_instruction_data,
            attestor_key,
            attestation,
        ),
        &[/* accounts */],
    )?;

    // If validation succeeds, execute business logic
    ```

    <Warning>
      The Solana implementation is in active development and has not yet been audited. Use with caution in production environments.
    </Warning>

    ### Resources

    * [sol-contracts Repository](https://github.com/PredicateLabs/sol-contracts)
    * [Architecture Documentation](https://github.com/PredicateLabs/sol-contracts/blob/main/ARCHITECTURE.md)
  </Tab>
</Tabs>

***

## Next Steps

Continue to [Onchain Integration](/v2/applications/onchain-integration) to update your offchain code.
