Gating Smart Contracts

Gate on-chain actions behind verified agent identity

This guide shows how to use the SelfAgentRegistry from Solidity to gate smart contract functions by proof-of-human agent identity.

1. Import the Registry Interface

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

interface ISelfAgentRegistry {
    // Agent verification
    function isVerifiedAgent(bytes32 agentKey) external view returns (bool);
    function getAgentId(bytes32 agentKey) external view returns (uint256);
    function getAgentCredentials(uint256 agentId) external view returns (AgentCredentials memory);

    // Proof-of-human (IERC8004ProofOfHuman)
    function hasHumanProof(uint256 agentId) external view returns (bool);
    function isProofFresh(uint256 agentId) external view returns (bool);
    function proofExpiresAt(uint256 agentId) external view returns (uint256);
    function getProofProvider(uint256 agentId) external view returns (address);

    // Sybil detection
    function sameHuman(uint256 agentIdA, uint256 agentIdB) external view returns (bool);
    function getAgentCountForHuman(uint256 nullifier) external view returns (uint256);
    function getHumanNullifier(uint256 agentId) external view returns (uint256);

    // ERC-8004 metadata
    function setAgentURI(uint256 agentId, string calldata newURI) external;
    function getMetadata(uint256 agentId, string memory key) external view returns (bytes memory);
    function setMetadata(uint256 agentId, string calldata key, bytes calldata value) external;

    struct AgentCredentials {
        string issuingState;
        string[] name;
        string idNumber;
        string nationality;
        string dateOfBirth;
        string gender;
        string expiryDate;
        uint256 olderThan;
        bool[3] ofac;
    }
}

Or import from the contracts package:

2. onlyVerifiedAgent Modifier

The most common pattern — gate a function to verified agents only:

The agent key derivation: bytes32(uint256(uint160(address))) — pads the 20-byte address to 32 bytes.

3. Query Credentials On-Chain

4. Check Proof Freshness

Proofs expire. Always check freshness for security-critical operations:

circle-exclamation

5. Sybil Checks

Detect or prevent multiple agents from the same human:

6. EIP-712 Meta-Transaction Pattern

For gasless agent verification, use a relayer that submits EIP-712 typed data on behalf of the agent:

See AgentDemoVerifier.sol in the repo for a complete implementation.

7. Reference Contracts

The repo includes two demo contracts you can use as templates:

AgentDemoVerifier

EIP-712 meta-transaction verifier. Demonstrates gasless verification where a relayer submits on behalf of agents.

AgentGate

Access gate requiring age-verified agents. Demonstrates direct msg.sender verification with credential checks.

8. Contract Addresses

Celo Mainnet (Chain ID: 42220)

Contract
Address

SelfAgentRegistry (proxy)

0xaC3DF9ABf80d0F5c020C06B04Cced27763355944

SelfHumanProofProvider

0x4b036aFD959B457A208F676cf44Ea3ef73Ea3E3d

AgentDemoVerifier

0xD8ec054FD869A762bC977AC328385142303c7def

AgentGate

0x26e05bF632fb5bACB665ab014240EAC1413dAE35

Hub V2

0xe57F4773bd9c9d8b6Cd70431117d353298B9f5BF

Celo Sepolia Testnet (Chain ID: 11142220)

Contract
Address

SelfAgentRegistry (proxy)

0x043DaCac8b0771DD5b444bCC88f2f8BBDBEdd379

SelfHumanProofProvider

0x5E61c3051Bf4115F90AacEAE6212bc419f8aBB6c

AgentDemoVerifier

0xc31BAe8f2d7FCd19f737876892f05d9bDB294241

AgentGate

0x86Af07e30Aa42367cbcA7f2B1764Be346598bbc2

Hub V2

0x16ECBA51e18a4a7e61fdC417f0d47AFEeDfbed74

9. Foundry Setup

circle-exclamation

Or add to foundry.toml:

Next Steps

Last updated