LogoLogo
  • Sign Protocol
    • Introduction
    • FAQ
  • For Hackers
    • Getting Started
  • For Builders
    • Getting Started
      • Fundamentals
      • Tutorials
        • Building a Simple Notary Platform
          • Schema Creation
          • Attestation Creation
          • Querying Attestations
          • Parsing Attestation Data
        • Delegate Attestation Creation
          • Express Backend
          • Solidity
      • Examples
        • Attestation Discord Bot
        • KYC-Gated Smart Contract Access Control
    • Supported Networks
    • Sign Developer Platform
    • Advanced Topics
      • Cross Chain Attestations
      • Hybrid Attestations
      • Schema Hooks
        • Tutorial: Checking Attestation Data
          • Schema Creation
          • Schema Hook
          • Creating an Attestation (Solidity)
      • ZK Attestations
        • Compile a Circuit
        • Create a Schema Hook
    • Querying Data
      • NPM SDK
        • Usage & Examples
      • REST APIs
        • Schemas
        • Attestations
      • GraphQL
        • Schemas
        • Attestations
    • Writing Data
      • NPM SDK
        • Installation
        • Usage
          • Schemas
          • Attestations
        • Examples
        • Changelog
      • Smart Contract
        • EVM
          • Interfaces
            • ISP
            • ISPHook
            • IVersionable
          • Data Models
            • Schema
            • Attestation
            • DataLocation
  • For Thinkers
    • A Future Of Verifiable Trust
    • Effective Attestations
    • Incentive-Aligned Public Good
    • Glossary
      • Attestations
      • Schema
      • Schema Registry
      • Attestation Repository
  • Case Study
    • EthSign
    • KYC-Gated Contract Calls
    • Proof of Audit
    • Developer Onchain Reputation
    • Onboarding Web2 Data
Powered by GitBook
LogoLogo

Copyright Sign 2021-2024

On this page
  • Interface
  • Example

Was this helpful?

  1. For Builders
  2. Advanced Topics

Schema Hooks

PreviousHybrid AttestationsNextTutorial: Checking Attestation Data

Last updated 8 months ago

Was this helpful?

To run custom Solidity code when an attestation is created or revoked, you will need to use a Schema Hook. Schema hooks enable schema creators to add whitelists, take payments, and write any custom application logic which will be called from Sign Protocol's smart contract. Any reverts in the schema hook will revert the entire call, allowing schema builders to control attestation creation and revocation logic.

Interface

Schema hooks must conform to the ISPHook interface, which can be found .

Example

The following example implements a basic whitelist schema hook. The owner of the WhitelistManager contract can add or remove user addresses on the whitelist. The WhitelistHook contract will be called when attestations are created and revoked.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
import { ISPHook } from "@ethsign/sign-protocol-evm/src/interfaces/ISPHook.sol";

// @dev This contract manages the whitelist. We are separating the whitelist logic from the hook to make things easier
// to read.
contract WhitelistMananger is Ownable {
    mapping(address attester => bool allowed) public whitelist;

    error UnauthorizedAttester();

    constructor() Ownable(_msgSender()) { }

    function setWhitelist(address attester, bool allowed) external onlyOwner {
        whitelist[attester] = allowed;
    }

    function _checkAttesterWhitelistStatus(address attester) internal view {
        // solhint-disable-next-line custom-errors
        require(whitelist[attester], UnauthorizedAttester());
    }
}

// @dev This contract implements the actual schema hook.
contract WhitelistHook is ISPHook, WhitelistMananger {
    function didReceiveAttestation(
        address attester,
        uint64, // schemaId
        uint64, // attestationId
        bytes calldata // extraData
    )
        external
        payable
    {
        _checkAttesterWhitelistStatus(attester);
    }

    function didReceiveAttestation(
        address attester,
        uint64, // schemaId
        uint64, // attestationId
        IERC20, // resolverFeeERC20Token
        uint256, // resolverFeeERC20Amount
        bytes calldata // extraData
    )
        external
        view
    {
        _checkAttesterWhitelistStatus(attester);
    }

    function didReceiveRevocation(
        address attester,
        uint64, // schemaId
        uint64, // attestationId
        bytes calldata // extraData
    )
        external
        payable
    {
        _checkAttesterWhitelistStatus(attester);
    }

    function didReceiveRevocation(
        address attester,
        uint64, // schemaId
        uint64, // attestationId
        IERC20, // resolverFeeERC20Token
        uint256, // resolverFeeERC20Amount
        bytes calldata // extraData
    )
        external
        view
    {
        _checkAttesterWhitelistStatus(attester);
    }
}
here