WorldIDRouter
smart contract
to verify the ZK proofs of personhood.
Prerequisites
Before we start, make sure you have the following tools installed:- Git (usually pre-installed on most systems)
- Node.js
- pnpm (or equivalent like npm, yarn or bun)
- Foundry CLI
Clone template
First, clone the World ID template app repository from GitHub:Install dependencies
Next, install the dependencies for the World ID template app:Build the smart contracts
Next we are going to compile the smart contracts for the World ID template app:Understanding World ID
Before we deploy the World ID template app, let’s take a look at the smart contracts that are part of the app:- The
Contract
contract is the main contract that will be deployed to World Chain Sepolia. It has a constructor that takes theIWorldID
interface, the app ID and the action ID as parameters. TheIWorldID
interface is the World ID router that will verify the proofs, the app ID is the ID of the app can be created by the developer using the World ID Developer Portal and that the action ID is the ID of the action that the user is performing which will be generated automatically by the IDKit SDK and derived fromaction
string defined in the Developer Portal. - The
nullifierHashes
mapping is used to keep track of the nullifier hashes that have been used already. This is used to guarantee that an action is only performed once by a single person in order to achieve sybil resistance. - The
verifyAndExecute
function is the main function that will be called by the user to verify their proof of personhood. It takes the user’s wallet address, the root of the Merkle tree, the nullifier hash, and the proof as parameters. - The function first checks if the nullifier hash has been used already and reverts if it has.
- It then verifies the proof using the
worldId.verifyProof
function which is part of theIWorldID
interface. - If the proof is valid, the function records the nullifier hash and executes the logic of the app. In this case, it emits
the
Verified
event.
RecurringGrantDrop.sol
contract which uses the World ID protocol to verify that the user is a unique human before they can claim a grant.
Deploy template app
First, you have to go to a node provider that supports World Chain Sepolia. You can use Alchemy or any of the other providers listed in the World Chain documentation. Once you have a node provider account, you need to get an RPC URL for the World Chain Sepolia network. For a simple deployment, the public RPC URL is sufficient. However, for doing a fork deployment, you will need to run a local fork of World Chain Sepolia using anvil which requires higher requirements on the RPC provider for forking the network. First, we will fork the World Chain Sepolia network using anvil:WORLD_ID_ROUTER
: The address of the World ID router contract that will verify the proofs (can be found in the World ID documentation)NEXT_PUBLIC_APP_ID
: The app ID that was generated in the Developer PortalNEXT_PUBLIC_ACTION
: The action ID as configured in the Developer Portal
Contract
contract to the World Chain Sepolia network using the provided RPC URL and private key.
Local Web Setup
Set up your environment variables in the.env
file. You will need to set the following variables:
NEXT_PUBLIC_APP_ID
: The app ID as configured in the Worldcoin Developer Portal.NEXT_PUBLIC_ACTION
: The action ID as configured in the Worldcoin Developer Portal.NEXT_PUBLIC_WALLETCONNECT_ID
: Your WalletConnect ID.NEXT_PUBLIC_CONTRACT_ADDRESS
: The address of the contract deployed in the previous step.
src/abi/ContractAbi.json
on each run of pnpm dev
.
Iterating
After making changes to the contract, you should:- re-run the
forge create
command from above - replace the
NEXT_PUBLIC_CONTRACT_ADDRESS
environment variable with the new contract address - if your contract ABI has changed, restart the local web server
Testing
You’ll need to import the private keys on the local testnet into your wallet used for local development. The default development seed phrase istest test test test test test test test test test test junk
.
This is only for local development. Do not use this seed phrase on mainnet or
any public testnet.