If you’re interested in using World ID and verifying proofs on-chain, see our
On-Chain Verification guide.
Supported Chains
Chain | Testnet | Role | Identity Availability |
---|---|---|---|
World Chain | Bridged | ~5 Minutes after Ethereum | |
Sepolia | Canonical | ~60 minutes after verification | |
Optimism Sepolia | Bridged | ~5 Minutes after Ethereum | |
Polygon | Bridged | ~40 Minutes after Ethereum | |
Base Sepolia | Bridged | ~5 Minutes after Ethereum Sepolia |
Find our smart contract address book
here.
Architecture
This section offers a high-level overview of the various smart contracts that make up World ID. This structure (including state bridging) is replicated on testnets — currently Sepolia, Optimism Sepolia, and Base Sepolia.Identity Managers: WorldIdIdentityManager
Identity Managers are only deployed on Ethereum. The Identity Manager contracts are responsible for managing the Semaphore instance. Worldcoin’s signup sequencers call the Identity Manager contracts to add or remove identities from the merkle tree.
State Bridges: OpStateBridge
/PolygonStateBridge
One State Bridge contract is deployed on Ethereum for each bridged chain. It publishes the root of the merkle tree to its configured chain’s World ID contract, allowing proofs to be verified on that chain.
Bridged World ID: OpWorldId
/PolygonWorldId
One World ID contract is deployed on each bridged chain, with an associated State Bridge contract on Ethereum. It is responsible for receiving merkle roots from its State Bridge contract, and verifying World ID proofs against those roots.
You can deploy your own State Bridge contract on Ethereum and Bridged World ID
contract to any chain to bridge World ID to that chain permissionlessly.
World ID Router: WorldIdRouter
This is the contract you should interact with.
The World ID Router will route your call to the correct Identity Manager contract (Ethereum) or World ID contract (L2 Chains) based on the groupId
argument. This contract is proxied, so you will not need to update your code if the underlying contracts are upgraded.
Only Orb credentials are supported on-chain, so the
groupId
must be 1
.Usage
TheverifyProof
method of the World ID Router is used to verify proofs on-chain.
Arguments
Parameter | Type | Required | Description |
---|---|---|---|
root | uint256 | The World ID root to verify against. | |
groupId | uint256 | Determines which Credential Type to verify against. As only Orb
credentials are supported on-chain, this must be 1 . | |
signalHash | uint256 | The keccak256 hash of the signal to verify. | |
nullifierHash | uint256 | The root of the merkle tree to verify against. This is obtained from the
IDKit widget as a hex string nullifier_hash , and must be
converted to a uint256 before passing it to the
verifyProof method. | |
externalNullifierHash | uint256 | The keccak256 hash of the externalNullifier to
verify. The externalNullifier is computed from the
app_id and action . | |
proof | uint256[8] | The zero-knowledge proof to verify. This is obtained from the IDKit
widget as a hex string proof , and must be converted to a
uint256[8] before passing it to the
verifyProof method. |
Example: groupId
Orb-Only groupId
Example: signalHash
signalHash
Example: externalNullifierHash
externalNullifierHash
Read more about the External Nullifier in Protocol Internals.
Example: Unpacking Proof
Sybil resistance
While the World ID protocol makes it very easy to make your contracts sybil resistant, this takes a little more than just calling theverifyProof
function. To make your contract sybil-resistant, you’ll need to do the following:
- Store the
nullifierHash
of each user that has successfully verified a proof. - When a user attempts to verify a proof, check that the
nullifierHash
is not already in the list of usednullifierHash
es.