WorldCoin Integration (Proof of Personhood)
WorldCoin solves one of the fundamental problems of Web3: how to prove that a unique live person is behind an address, without revealing identity. Standard KYC systems require passport and bind address to real person. WorldCoin uses iris-scanning and zero-knowledge proof to confirm humanness without deanonymization.
How World ID Works
Iris-based Biometry and ZK-proof
User undergoes iris scan through Orb device. From scan forms IrisCode — 2048-bit hash of biometric data. IrisCode not stored openly: in Semaphore-tree (Merkle tree) adds leaf with user commitment.
When user proves uniqueness to application, generates ZK-SNARK proof proving:
- User's commitment is in tree (passed Orb verification)
- User has not yet used World ID for given
action(nullifier unique)
Proof doesn't reveal address, IrisCode or connection between different applications. This is selective disclosure in pure form.
Nullifier and Double-spend Protection
Key cryptographic primitive: nullifier_hash = hash(identity_secret, app_id, action_id). One person for one action in one application always generates same nullifier. Only need to store already used nullifiers — check none exists, add, cannot use again.
This analogue of serial number in physical cash — upon cancellation of note number recorded as "used". Without revealing who exactly cancelled it.
Technical Integration
On-chain Verification via WorldID Contract
import { IWorldID } from "@worldcoin/world-id-contracts/src/interfaces/IWorldID.sol";
contract MyApp {
IWorldID internal immutable worldId;
uint256 internal immutable groupId = 1; // Orb-verified
uint256 internal immutable externalNullifier;
mapping(uint256 => bool) internal nullifierHashes;
constructor(IWorldID _worldId, string memory appId, string memory actionId) {
worldId = _worldId;
externalNullifier = abi.encodePacked(
abi.encodePacked(appId).hashToField(),
abi.encodePacked(actionId).hashToField()
).hashToField();
}
function verifyAndExecute(
address signal,
uint256 root,
uint256 nullifierHash,
uint256[8] calldata proof
) public {
require(!nullifierHashes[nullifierHash], "Already used");
worldId.verifyProof(
root,
groupId,
abi.encodePacked(signal).hashToField(),
nullifierHash,
externalNullifier,
proof
);
nullifierHashes[nullifierHash] = true;
// further logic
}
}
Off-chain Verification via Developer Portal
For Web2 backend — lightweight variant without on-chain transaction:
import { verifyCloudProof } from "@worldcoin/idkit";
const result = await verifyCloudProof(
proof, // from IDKit widget
app_id,
action,
signal // optional
);
if (result.success) {
// user verified, nullifier already marked
}
Cloud verification simpler, but centralized — Developer Portal Worldcoin sees all verifications of your application. For privacy-critical use cases — on-chain only.
IDKit React Widget
import { IDKitWidget, VerificationLevel } from "@worldcoin/idkit";
<IDKitWidget
app_id="app_staging_..."
action="vote_proposal_123"
verification_level={VerificationLevel.Orb}
onSuccess={(proof) => sendToContract(proof)}
>
{({ open }) => <button onClick={open}>Verify with World ID</button>}
</IDKitWidget>
VerificationLevel.Device — lower level (no Orb, phone verification only), suitable for less critical actions. VerificationLevel.Orb — full biometric verification.
Use Cases and Limitations
Where Applicable
Airdrop protection from sybil: instead of "1 address = 1 allocation" → "1 person = 1 allocation". Nullifier bound to action (e.g., claim_airdrop_season1) — re-registering with another address won't help.
Governance: "1 person = 1 vote" in DAO without trust in token-weighted voting.
Rate limiting: limiting actions (free trial, faucet) per-person, not per-address.
Certificate/credential systems: issuing credential to unique user with ability to present without revealing identity.
Limitations
Geographic Orb coverage: Orb devices unevenly distributed. In regions with low coverage users cannot verify — real UX limitation.
World App dependency: ZK proof generated in World App (mobile application). User without smartphone or unwilling to install app — cannot verify. For B2B and enterprise scenarios this problem.
Device verification: less strict level, but phone uniqueness — weaker than iris uniqueness.
Integration Process
| Stage | Content | Time |
|---|---|---|
| Registration in Developer Portal | Creating app_id, configuring actions | 1 day |
| Smart contract | WorldID verifier + nullifier storage | 2-3 days |
| Frontend | IDKit widget, proof handling | 1-2 days |
| Testing | Staging environment, testnet deploy | 1-2 days |
Basic integration with on-chain verification — 5-7 working days. Cost calculated individually.







