Skip to main content
On-chain verification is best for web3 apps that need proof checks enforced by smart contracts (for example gating mints, voting, or claims without backend trust assumptions). If you do not need contract-level enforcement, use POST /v4/verify instead.

1. Verifying Legacy proofs (World ID 3.0)

If you are integrating World ID on-chain, we strongly recommend deploying your contract behind an upgradable proxy (e.g. UUPS or Transparent Proxy). This allows you to upgrade your verification logic as new World ID versions are released. See the World ID 4.0 Migration guide for details.
For v3 proofs, verify against WorldIDRouter.verifyProof(...). Use the Router address for the chain you’re deploying to:
For legacy proofs, ensure groupId = 1 (Orb-only on-chain path). If your v3 proof arrives as ABI-encoded bytes, decode it to uint256[8] before calling verifyProof:

2. Verifying Uniqueness proofs in WorldIDVerifier.sol (World ID 4.0)

WorldIDVerifier is deployed on World Chain Mainnet as an upgradeable proxy. Use the proxy address for your environment: For v4 uniqueness proofs, call verify(...) on the WorldIDVerifier proxy and store used nullifiers to enforce one-human-one-action semantics in your contract.
Minimal mapping from IDKit result:
  • nullifier = responses[i].nullifier
  • action = keccak256(action) as uint256
  • rpId = numeric form of your rp_context.rp_id (the rp_-prefixed string from your RP context, not the result)
  • nonce = top-level nonce
  • signalHash = responses[i].signal_hash
  • expiresAtMin = responses[i].expires_at_min
  • issuerSchemaId = responses[i].issuer_schema_id
  • credentialGenesisIssuedAtMin = the request’s genesis_issued_at_min constraint (0 if unconstrained) — not returned in responses[i]
  • proof = responses[i].proof (uint256[5])