Justify

Creator-based prediction market powered by AI agents and social distribution

Justify

Created At

ETHGlobal New York 2026

Winner of

World

World - Track C (Existing Projects integrating World ID) 1st place

Project Description

Justify is a creator-based prediction platform where creators launch markets for their communities, users trade on outcomes, and AI agents help users analyze markets and make smarter decisions. Creators bring traders, traders bring liquidity, and AI agents make prediction markets easier for normal users. We use World for human and agent verification, Blink for shareable market actions and passkey UX, ARC as our compliance-first network for the European market, Dynamic for wallet login and onboarding, and Chainlink CRE to verify offchain AI logic and external data before writing trusted signals onchain.

How it's Made

Justify is a prediction market on Arc testnet where humans and AI agents trade binary YES/NO markets. Contracts (Foundry / Solidity 0.8.24) are Gnosis-style FPMMs with a MarketFactory and conditional Resolver, collateralized in Arc's native USDC. Buys round up, so k never decreases and the pool can't be drained by rounding. Backend is Fastify + viem with file-backed stores, a nonce-safe signer queue, and an event indexer feeding the price chart. The oracle is the part we put the most thought into. Claude (Haiku 4.5) classifies each market: price questions resolve straight from a Chainlink Data Feed (latestRoundData on Sepolia), with a link to the aggregator on Etherscan so judges can verify it; subjective ones fall through to Claude (Sonnet 4.6), which makes the call and writes out its reasoning. One router, two sources of truth. Partner stack: Chainlink Data Feeds for price resolution, World ID 4.0 for a proof-of-human gate (plus a country gate for politics markets), Circle CCTP V2 for a burn-and-mint bridge from Base Sepolia, and Blink/Swype + Dynamic for embedded-wallet deposits. Frontend is React 18 + Vite on Hetzner behind nginx. One workaround: depositForBurn kept reverting on a stale allowance after approve, so we used a MAX_UINT approve plus an allowance re-read loop.

background image mobile

Join the mailing list

Get the latest news and updates