IVerificationOracle

The Verification Oracle interface orchestrates identity verifications on Humanity Protocol, managing user consent, request processing, EAS attestations, fee handling, and DApp callbacks.


Contract Address

Testnet

0x67c0A5cA2Fb19E8E0Ff008d727aff5f128b00E09

Mainnet

0x8D71D8bD47860bd0381b272AE42162c3692c4F3a

Overview

IHumanityVerificationOracle provides the core verification functionality for Humanity Protocol. It enables DApps to request human verification for users, validates signatures, manages verification requests via EAS attestations, coordinates fee payments through FeeEscrow, and notifies DApps of results via callbacks.

Core Concepts

Concept
Description

Request Lifecycle

Each verification request transitions through states: PendingDone or Cancelled

EAS Integration

Requests and results are recorded as EAS attestations for auditability and on-chain proof

User Consent

Users must sign a permission message off-chain before verification can be requested

DApp Callback

Upon completion, the Oracle notifies the DApp via onVerificationComplete()

Request Status

enum RequestStatus {
    Pending,    // Verification in progress
    Done,       // Verification completed
    Cancelled   // Request cancelled or revoked
}

Verification Request Structure


Verification Flow

1. PREPARE

DApp determines the requiredClaims[] array and maxAge parameter for the verification request.

2. GET PERMISSION HASH

DApp calls getPermissionMessageHash(user, dapp, claims, maxAge, callbackContract) to generate the message hash that the user must sign.

3. USER SIGNS

User signs the messageHash off-chain using their wallet, producing userSignature.

4. REQUEST VERIFICATION

DApp calls requestVerification(dapp, user, claims, maxAge, callbackContract, signature). The Oracle validates the signature, reserves the fee via FeeEscrow.reserveForRequest(), and returns a requestId (bytes32).

5. ORACLE PROCESSES

The Oracle performs off-chain verification of the user's humanity credentials and creates an EAS attestation for the result.

6. SUBMIT RESULT

Oracle calls submitVerificationResult(requestUID, verified, ...). This settles fees via FeeEscrow.settleRequest() and emits a VerificationCompleted event.

7. CALLBACK

Oracle calls the DApp's onVerificationComplete(requestId, user, verified, attestationUID) callback. The DApp grants or denies access based on the verified boolean.


Interface


Functions

Request Management

requestVerification(...)

Request verification for a user. Requires a valid user signature.

Parameter
Type
Description

dapp

address

Address of the DApp requesting verification

user

address

Address of the user to verify

requiredClaims

string[]

Array of claim types required (e.g., ["humanity_identity"])

maxAge

uint256

Maximum age of verification data in seconds

callbackContract

address

Contract to receive verification callback

userSignature

bytes

User’s signature authorizing the verification

Returns: requestId - The unique identifier (bytes32) for this verification request

Reverts:

  • UnauthorizedRequest if signature is invalid

  • NoClaimsSpecified if requiredClaims is empty

  • InsufficientAvailableBalance (from FeeEscrow) if DApp hasn’t pre-funded

Emits: VerificationRequested(bytes32 indexed attestationUID, address indexed requester, address indexed user, string[] requiredClaims, uint256 fee)


submitVerificationResult(...)

Submit the result of a verification request. Called by the Oracle after processing.

Parameter
Type
Description

requestUID

bytes32

The request to submit results for

verified

bool

Whether verification succeeded

expiresAt

uint256

Timestamp when this verification expires

usedIssuers

string[]

DIDs of issuers whose credentials were used

usedCategories

string[]

Categories of claims that were verified

Emits: VerificationCompleted(bytes32 indexed requestUID, bool verified, bytes32 resultUID)


revokeVerificationRequest(bytes32 attestationUID)

Revoke a verification request or result.

Reverts:

  • RequestNotFound if request doesn’t exist

  • RequestAlreadyRevoked if already revoked

  • NotAuthorizedToRevoke if caller lacks permission

Emits: VerificationRequestRevoked(address indexed revoker, bytes32 indexed requestUID, uint256 revokedAt)


Verification Queries

isUserVerified(...)

Check if a user has a valid verification matching the specified criteria.

Parameter
Type
Description

user

address

Address of the user to check

requiredClaims

string[]

Claims that must be verified

maxAge

uint256

Maximum age of verification in seconds

Returns:

  • verified - Whether user has valid verification

  • attestationUID - UID of the verification attestation (if verified)

  • expiresAt - When the verification expires


getRequest(bytes32 requestUID)

Get full details of a verification request.


getResult(bytes32 resultUID)

Get details of a verification result.


getUserRequests(address user)

Get all verification request UIDs for a user.


resultToRequest(bytes32 resultUID)

Map a result UID back to its original request UID.


Signature Helpers

getPermissionMessageHash(...)

Get the message hash that a user must sign to authorize verification.

Important: The signature must be computed over the exact tuple (user, dapp, requiredClaims[], maxAge, callbackContract, currentUserNonce). Any mismatch causes UnauthorizedRequest.


getUserNonce(address user)

Get the current nonce for a user. The nonce is incremented after each verification request.


Attestation Decoders

decodeRequestAttestation(bytes memory attestationData)

Decode EAS-encoded request attestation data.


decodeResultAttestation(bytes memory attestationData)

Decode EAS-encoded result attestation data.


Admin Functions

updateVerificationFee(uint256 _newFee)

Update the fee required for verification requests.

Emits: VerificationFeeUpdated(uint256 newFee)


updateTreasuryAddress(address _newTreasury)

Update the treasury address for fee collection.

Emits: TreasuryAddressUpdated(address newTreasury)


updateEAS(address _newEAS)

Update the EAS contract address.

Emits: EASAddressUpdated(address newEAS)


updateSchemas(bytes32 _newRequestSchemaUID, bytes32 _newResultSchemaUID)

Update the EAS schema UIDs for requests and results.

Emits: SchemasUpdated(bytes32 oldRequestSchemaUID, bytes32 newRequestSchemaUID, bytes32 oldResultSchemaUID, bytes32 newResultSchemaUID)


pause() / unpause()

Pause or unpause contract operations.


DApp Callback Interface

DApps must implement IHumanityVerificationCallback to receive verification results.

Parameter
Type
Description

requestId

bytes32

The verification request ID

user

address

The user who was verified

verified

bool

Whether verification succeeded

attestationUID

bytes32

EAS attestation UID for the result


Events

Lifecycle Events

Event
Description

VerificationRequested(bytes32 indexed attestationUID, address indexed requester, address indexed user, string[] requiredClaims, uint256 fee)

New verification request created

VerificationCompleted(bytes32 indexed requestUID, bool verified, bytes32 resultUID)

Verification completed

VerificationRequestRevoked(address indexed revoker, bytes32 indexed requestUID, uint256 revokedAt)

Request revoked

VerificationResultRevoked(address indexed revoker, bytes32 indexed resultUID, uint256 revokedAt)

Result revoked

Callback Events

Event
Description

CallbackErrorString(bytes32 indexed requestUID, address callbackContract, string reason)

Callback failed with revert string

CallbackErrorPanic(bytes32 indexed requestUID, address callbackContract, uint256 errorCode)

Callback failed with panic

CallbackErrorLowLevel(bytes32 indexed requestUID, address callbackContract, bytes lowLevelData)

Callback failed with low-level error

Fee Events

Event
Description

FeeCollected(address indexed dapp, uint256 feePaid, uint256 debtPaid)

Fee collected from DApp

FeesDistributed(address dapp, bytes32 verificationUID, address[] issuerAddresses, uint256[] issuersFee, uint256 stakingFee, uint256 proofFee, uint256 totalFee)

Fees distributed to stakeholders

FeeVerifierPaid(address indexed dapp, uint256 fee, uint256 debt)

Verifier paid

FeesWithdrawn(address indexed recipient, uint256 amount)

Fees withdrawn

DebtUpdated(address indexed dapp, uint256 oldDebt, uint256 newDebt)

DApp debt updated

Configuration Events

Event
Description

VerificationFeeUpdated(uint256 newFee)

Fee amount changed

TreasuryAddressUpdated(address newTreasury)

Treasury address changed

EASAddressUpdated(address newEAS)

EAS contract address changed

FeeEscrowUpdated(address indexed oldEscrow, address indexed newEscrow)

FeeEscrow address changed

SchemasUpdated(...)

EAS schemas changed


Errors

Configuration Errors

Error
Description

AlreadyProcessing()

Request is already being processed

InvalidAddress(string param)

Provided address is invalid

SchemasAlreadyInitialized()

Schemas already set

SchemasNotInitialized()

Schemas not yet configured

InvalidSchema(string schemaType)

Invalid schema provided

Request Errors

Error
Description

InvalidUser()

User address is invalid

InvalidRequest()

Request data is invalid

InvalidValue(string param)

Parameter value is invalid

NoClaimsSpecified()

Required claims array is empty

InsufficientVerificationFee(uint256 required, uint256 provided)

Fee provided is insufficient

RequestNotFound(bytes32 requestUID)

Request doesn’t exist

RequestExpired(bytes32 requestUID)

Request has expired

RequestAlreadyRevoked(bytes32 requestUID)

Request was already revoked

BatchSizeExceedsLimit(uint256 size, uint256 maxSize)

Batch too large

MismatchedArrayLengths()

Array parameters have different lengths

DebtLimitExceeded(uint256 newDebt, uint256 maxDebtAllowance)

DApp debt would exceed limit

Authorization Errors

Error
Description

NotAuthorizedToRevoke(address caller)

Caller cannot revoke this request

UnauthorizedUpgrade(address caller)

Caller cannot upgrade contract

UnauthorizedRequest(address expectedSigner, address actualSigner)

Signature doesn’t match expected signer

Transfer Errors

Error
Description

NoFeesToWithdraw()

No fees available for withdrawal

RefundFailed(address recipient, uint256 amount)

Refund transfer failed

TreasuryTransferFailed(address treasury, uint256 amount)

Treasury transfer failed

LockFeeFailed(address issuer)

Failed to lock fee for issuer

Integration Example


Integration Tips

  1. Signature Validation: The userSignature must be computed over the exact tuple (user, dapp, requiredClaims[], maxAge, callbackContract, currentUserNonce). Any mismatch causes UnauthorizedRequest and reverts.

  2. FeeEscrow Configuration: Ensure FeeEscrow.verificationOracle is configured to this Oracle instance. Otherwise, reserveForRequest/settleRequest will revert with UnauthorizedCaller.

  3. Insufficient Balance Error: If you see a revert with data starting 0x6701c6f6, it decodes to InsufficientAvailableBalance(dapp, required, available) from IFeeEscrow. Pre-fund FeeEscrow via deposit or lower the verificationFee (admin).

  4. Callback Handling: Treat callback execution as untrusted. Handle errors gracefully and consider timeouts/compensation logic if callbacks revert.

  5. Upgrades (UUPS): Always append new state variables at the end when upgrading. Do not increase __gap; reduce it by the number of slots you add.

  6. Nonce Management: Each verification request increments the user’s nonce. If a signature fails, check that you’re using the current nonce from getUserNonce(user).


Last updated