HashX
⏳ HashX: A permissionless Optimistic Oracle on Hedera built using Timelocked puzzles.
Problem Statement
HashX is an app for creating and resolving prediction markets with accuracy with the help of privacy-preserving voting on Hedera EVM. Votes are encrypted using BabyJubJub-based ECDH and AES-256-CTR, then revealed via a timelock puzzle or automatically by a server-held key. Rewards are distributed using Merkle proofs.FeaturesVerifier Secret Key is generated upon Oracle Creation, Public Parameters for solving the SK is published Onchain (RSA modulus $N$, base $a$, iterations $t$)Encrypted voting with EIP‑712 typed signatures → ephemeral keys → AES-encrypted ballotVotes are calculated per user basis, Rewards are calculated as per amount staked.Voters can not prove what they have voted until the vote is resolved.Hedera EVM integration (Testnet) with RainbowKit.HBAR staking viaHBARLockingContractto obtain voting power. This converts HBAR to WHBAR utilizing WHBAR.sol contract.Solver gets certain percentage (default $5%$) of the Oracle value.Oracle rewards among voters are distributed via Merkle proofs.Postgres DB for fetching markets metadata and serving proofs.Contracts (addresses on Hedera Testnet)HBAR_LOCKING_CONTRACT_ADDRESS:0xde368C3DCac4E5096f2D2b8AF7Be70277c43b144CREATEVOTE_FACTORY_ADDRESS:0x90Fe5e610A12D2Aa0374e5CEA373bc4CdC103CbcPREDICT_MARKET_FACTORY_ADDRESS:0x0118250132B55af4Ca1659dA51Bf7430245C1A03ABIs: seeABI/Factory contracts are verified on Hashscan.Tech stackApp: Next.js (app router), React 19, Tailwind, Zustand, TanStack QueryWeb3: wagmi v2, viem, RainbowKit, SIWECrypto: @zk-kit/baby-jubjub, AES-256-CTR, bigint-mod-arithDB: Postgres (Neon)Using the appConnect wallet. The UI will prompt to add/switch to Hedera Testnet if needed.Stake HBAR (Stake tab) to gain voting power.Create Oracle (Start Creating):Set rewards, start/end time, and choose resolution mode (auto vs manual puzzle).The app recordsmarketIdand oraclecontractAddress.Create Market: Provide initial liquidity and parameters, then submit.Vote: Pick option, Generate Signature, then Submit Vote.Resolve: After end, click Verify Result (runs decrypt + finalize) and then Claim Rewards.
Solution
• Tech stackApp: Next.js (App Router) 16, React 19 (React Compiler), Tailwind v4, Radix UI, Lucide, Sonner, Next Themes, TanStack Query, Zustand.Wallet/Web3: wagmi v2, viem, RainbowKit (SSR), SIWE.Crypto:@zk-kit/baby-jubjub(ECDH), AES‑256‑CTR,bigint-mod-arith.Contracts: Solidity (OpenZeppelin), Hedera EVM (Testnet).Data/Infra: Postgres (Neon serverless), Drizzle ORM, Hedera Mirror Node API.Build: Turbopack, TypeScript, ESLint 9.• High-level architectureSmart contracts:HBARLockingContractstakes HBAR and wraps to WHBAR, tracks deposits, transfers stake to protocol and back for rewards.CreateVoteoracle: stores public parameters for the timelock puzzle, accepts encrypted votes (userPublicKey,bytes option,amount), verifies solver secret, finalizes with a Merkle root, and enablesclaimRewards.PredictionMarket+PredictionMarketToken: AMM-like market with YES/NO tokens, initial liquidity, probability-based pricing, and settlement driven by theCreateVoteoracle outcome. Factories deploy both oracle and market.Server “actions”(Next.js server components):DB via Neon + Drizzle stores oracle public params, optional server-held secret, market metadata, and Merkle proofs.Finalization flow decrypts votes off-chain (after end), builds Merkle trees, simulates, then sends on-chainfinalizeVotewith a server wallet (envPRIVATE_KEY).Frontend:RainbowKit + wagmi configure Hedera Testnet, SIWE auth; EIP‑712 typed message signing for vote attestations.Zustand stores reflect balances, transaction hashes; TanStack Query for async data.• Privacy-preserving vote encryptionUsers generate an ephemeral BabyJubJub key by hashing their EIP‑712 vote signature + fresh randomness, mod curve order.ECDH with the oracle’s BabyJubJub public key derives a shared secret; votes are encrypted with AES‑256‑CTR (constant IV is acceptable here because keys are per‑vote and unique).On-chain, the vote is stored asbytesmapped to the ephemeral public key, keeping the voter’s choice hidden.• Timelock puzzle (delayed reveal)On oracle creation, server generates an RSA modulus N (JWK), sets basea=2and difficultyt. Computeb = a^(2^t mod φ(N)) mod N, hashband XOR with the secret key to publishskLocked.Anyone can later recover the secret via repeated squaring (computinga^(2^t) mod N), unmaskskLocked, and submit it on-chain; or in “server mode” the backend reveals SK after end.Contract double-hashes the expected secret to prevent preimages and rewards the solver (~10%) via the locking contract.• Finalization and distributionBackend queries Mirror Node for blocks bracketing start/end timestamps; fetchesVoteCastlogs via viem.Decrypts each vote with the recovered (or server-held) SK; tallies options; adds losing-side stake to rewards.Uses@openzeppelin/merkle-treeto build Standard Merkle Trees for winners; stores proofs in Postgres.SimulatesfinalizeVote, then sends it withwinnerMerkleTreeRootand added rewards. Users claim on-chain by submitting their Merkle proof.• Partner tech and how it helpedHedera EVM + Mirror Node: fast finality and easy block range lookup by timestamp for off-chain log collection.Neon Postgres + Drizzle: serverless, simple schema-first DX; storing oracle params and Merkle proofs for the UI.RainbowKit + wagmi + viem: reliable multi-wallet UX, typed EIP‑712 flows, and robust simulation/tx sending.• Notable hacky bitsEphemeral JJJ keys derived from typed signatures + randomness for unlinkable, per‑vote encryption.RSA timelock via repeated squaring implemented in both server action and CLI scripts (src/scripts/solve_puzzle.ts), with XOR masking of SK.Using Mirror Node timestamps → block numbers to bound event fetching precisely.Hard-coded on-chain operator for oracle admin actions inCreateVoteto simplify hackathon operations.AES‑CTR with a fixed IV is safe here due to per‑vote one‑time keys; simpler than managing nonces while preserving privacy.
Hackathon
ETHOnline 2025
2025
Contributors
- aritradhabal
57 contributions