Skip to content
P

Proof of Human — End to End Plan

Proof of Human — End to End Plan

Created on 21st February 2026

•

P

Proof of Human — End to End Plan

Proof of Human — End to End Plan

The problem Proof of Human — End to End Plan solves

The internet does not know who is human anymore.

Bots farm airdrops. Scripts manipulate governance votes. Sybil accounts drain incentives. AI agents generate fake engagement at scale. Platforms either:

Require invasive identity checks (KYC, biometrics, passports)

Rely on weak signals like CAPTCHAs

Accept being exploited by automated actors

Today, you must choose between privacy and proof.

If you prove you are human, you usually reveal:

Your legal identity

Your location

Your device fingerprint

Your behavioral data

If you protect your privacy, you cannot reliably prove you are a unique human.

There is no native, privacy-preserving, reusable “human layer” for crypto and the internet.

Proof of Human solves this by allowing someone to prove they are a real, unique human without revealing who they are, where they were, or any raw personal data.

Challenges we ran into

Challenges I Ran Into

  1. Running ZK proofs natively on iOS
    Integrating mopro (a Rust-based ZK prover) into an iOS app was non-trivial. The circuit had to be transpiled from WASM to Rust using rust-witness, compiled to a static .a library for both aarch64-apple-ios and aarch64-apple-ios-sim, then packaged into an XCFramework. Any change to the circuit meant rebuilding the entire xcframework from scratch.

  2. Swift Package Manager conflicts
    We initially used WalletConnect (reown-swift) for wallet signing. It pulled in swift-crypto 2.x, which silently broke secp256k1.swift 0.12.2 - the library relied on internal types (DigestSigner, SecureBytes) that were removed in the newer version. The error messages were cryptic and pointed nowhere near the real cause. We resolved it by removing the WalletConnect dependency entirely and routing transaction signing through the Node.js backend using ethers.js.

  3. Poseidon hash consistency across stacks
    The ZK circuit uses Poseidon hashing (BN254 field). We needed the same hash values produced by the circuit, the on-chain verifier, and the iOS app. Getting circomlibjs, snarkjs, and the Rust poseidon-bn128 FFI to agree on field representation took significant debugging - one wrong BigInt encoding produces a completely wrong hash with no obvious error.

  4. ERC-7702 transaction signing on iOS
    The original plan was to use ERC-7702 (type-0x04 transactions) so a relayer could submit the proof while msg.sender appeared as the user's own
    EOA - enabling gasless UX. However, implementing raw EIP-7702 transaction signing in Swift turned out to be a deep rabbit hole: the secp256k1
    Swift package conflicts, no native RLP encoder for type-0x04 transactions, and the recoverable ECDSA signature (needed for the recovery ID v)
    not being cleanly exposed by any Swift library we could use without pulling in conflicting dependencies.

Use of AI tools and agents

Claude Code (Anthropic) was used as the primary development agent throughout this project — not just for code generation, but as an active pair
programmer managing the full stack across iOS (Swift), Rust (mopro/FFI), Solidity (Foundry), and Node.js simultaneously.

Specific contributions:

  • Circuit design — Iterated on the Circom ZK circuit structure, deciding which signals should be public vs private and how to encode the
    deviceCommitment = Poseidon(device_attest_key, walletAddress) binding
  • Smart contract development — Wrote and deployed HumanityVerifier, HumanityToken, Groth16Verifier, and ProofDelegator to Sepolia via Foundry
  • iOS app architecture — Designed the full Swift service layer (ProverService, ChainService, StampService, PoseidonBridge) and wired them
    together with SwiftUI views
  • Debugging SPM conflicts — Diagnosed and resolved the secp256k1.swift vs swift-crypto 2.x conflict that blocked the entire iOS build
  • mopro integration — Managed the circuit compilation pipeline: WASM → Rust witness → static library → XCFramework, and debugged the proof
    format differences between mopro's output and snarkjs's Solidity ABI encoding convention
  • Backend API — Built the Node.js proof server with Poseidon hashing, proof generation, verification, and on-chain submission endpoints

The project itself also explores a future where AI agents will consume this proof — using the on-chain soulbound token as a trust signal to
distinguish human users from autonomous agents in smart contract interactions.

Tracks Applied (1)

Devtopia

Proof of Human — End to End Plan

Discussion

Builders also viewed

See more projects on Devfolio