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
Request Lifecycle
Each verification request transitions through states: Pending → Done 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(...)
requestVerification(...)Request verification for a user. Requires a valid user signature.
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:
UnauthorizedRequestif signature is invalidNoClaimsSpecifiedifrequiredClaimsis emptyInsufficientAvailableBalance(from FeeEscrow) if DApp hasn’t pre-funded
Emits: VerificationRequested(bytes32 indexed attestationUID, address indexed requester, address indexed user, string[] requiredClaims, uint256 fee)
submitVerificationResult(...)
submitVerificationResult(...)Submit the result of a verification request. Called by the Oracle after processing.
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)
revokeVerificationRequest(bytes32 attestationUID)Revoke a verification request or result.
Reverts:
RequestNotFoundif request doesn’t existRequestAlreadyRevokedif already revokedNotAuthorizedToRevokeif caller lacks permission
Emits: VerificationRequestRevoked(address indexed revoker, bytes32 indexed requestUID, uint256 revokedAt)
Verification Queries
isUserVerified(...)
isUserVerified(...)Check if a user has a valid verification matching the specified criteria.
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 verificationattestationUID- UID of the verification attestation (if verified)expiresAt- When the verification expires
getRequest(bytes32 requestUID)
getRequest(bytes32 requestUID)Get full details of a verification request.
getResult(bytes32 resultUID)
getResult(bytes32 resultUID)Get details of a verification result.
getUserRequests(address user)
getUserRequests(address user)Get all verification request UIDs for a user.
resultToRequest(bytes32 resultUID)
resultToRequest(bytes32 resultUID)Map a result UID back to its original request UID.
Signature Helpers
getPermissionMessageHash(...)
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)
getUserNonce(address user)Get the current nonce for a user. The nonce is incremented after each verification request.
Attestation Decoders
decodeRequestAttestation(bytes memory attestationData)
decodeRequestAttestation(bytes memory attestationData)Decode EAS-encoded request attestation data.
decodeResultAttestation(bytes memory attestationData)
decodeResultAttestation(bytes memory attestationData)Decode EAS-encoded result attestation data.
Admin Functions
updateVerificationFee(uint256 _newFee)
updateVerificationFee(uint256 _newFee)Update the fee required for verification requests.
Emits: VerificationFeeUpdated(uint256 newFee)
updateTreasuryAddress(address _newTreasury)
updateTreasuryAddress(address _newTreasury)Update the treasury address for fee collection.
Emits: TreasuryAddressUpdated(address newTreasury)
updateEAS(address _newEAS)
updateEAS(address _newEAS)Update the EAS contract address.
Emits: EASAddressUpdated(address newEAS)
updateSchemas(bytes32 _newRequestSchemaUID, bytes32 _newResultSchemaUID)
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() / unpause()Pause or unpause contract operations.
DApp Callback Interface
DApps must implement IHumanityVerificationCallback to receive verification results.
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
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
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
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
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
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
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
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
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
Signature Validation: The
userSignaturemust be computed over the exact tuple(user, dapp, requiredClaims[], maxAge, callbackContract, currentUserNonce). Any mismatch causesUnauthorizedRequestand reverts.FeeEscrow Configuration: Ensure
FeeEscrow.verificationOracleis configured to this Oracle instance. Otherwise,reserveForRequest/settleRequestwill revert withUnauthorizedCaller.Insufficient Balance Error: If you see a revert with data starting
0x6701c6f6, it decodes toInsufficientAvailableBalance(dapp, required, available)from IFeeEscrow. Pre-fund FeeEscrow viadepositor lower theverificationFee(admin).Callback Handling: Treat callback execution as untrusted. Handle errors gracefully and consider timeouts/compensation logic if callbacks revert.
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.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