Skip to main content
v0 Alpha Architecture: This documents the prototype architecture. Everything below the smart contract layer is scaffolding for testing the core primitive.

Core Primitive

The novel piece is on-chain Levenshtein distance as a scoring function for prediction markets. Everything else exists to make that primitive testable on BASE Sepolia.
                The thing that matters
                ──────────────────────
                PredictionMarketV2.sol
                - createSubmission(marketId, predictedText) payable
                - resolveMarket(marketId, actualText) onlyOwner
                - levenshteinDistance(a, b) pure → uint256
                - claimPayout(submissionId)

                Prototype scaffolding
                ─────────────────────
                Flask + Web3.py backend
                Vanilla JS frontend
                Firebase email OTP
                Redis caching
                Celery workers

System Overview

The frontend is a functional prototype. The Flask backend provides API routes and admin tools. All market data lives on-chain.

Smart Contract Stack

ContractPurposeStatus
PredictionMarketV2Full market lifecycle with Levenshtein resolutionActive
GenesisNFT100 founder NFTs with on-chain SVG art60 minted, finalized
PayoutManagerFee distribution to stakeholdersDeployed
DecentralizedOracleText validation and Levenshtein calculationDeployed (future use)
ActorRegistryX.com actor registration (governance)Deployed (future use)
NodeRegistryNode operator stakingDeployed (future use)
PredictionMarket (V1)Simple market, no resolutionDeprecated
EnhancedPredictionMarketFull governance market logicFuture (requires active nodes)
PredictionMarketV2 is the only contract that matters right now at 0x5174Da96BCA87c78591038DEe9DB1811288c9286.

Data Flow

1

Market Creation

A user creates a market specifying:
  • Actor handle (e.g., @elonmusk)
  • Description (what the market is about)
  • End time (Unix timestamp)
2

User Submissions

Users submit predictions with ETH stakes:
  • Predicted text (max 280 characters)
  • ETH stake (minimum specified by market)
  • Stake is locked in the contract
3

Market Ends

The market closes automatically when the end time is reached. No more submissions are accepted.
4

Oracle Resolution

An oracle (currently a single EOA) fetches the actual text from X.com and calls resolveMarket().
5

On-chain Scoring

The contract calculates Levenshtein distance between each prediction and the actual text:
  • Distance = minimum number of single-character edits
  • Winner = submission with lowest distance
  • Ties are broken by submission order (first wins)
6

Payout

The winner claims their payout:
  • 93% of total pool goes to winner
  • 7% platform fee is distributed to stakeholders

Resolution Model (Centralized MVP)

Currently: single EOA calls resolveMarket(marketId, actualText). This is the biggest centralization risk and the most important thing to fix before real deployment.

Current Implementation

  • Single owner address has resolution authority
  • Owner fetches text from X.com API
  • Owner submits actual text on-chain
  • Contract calculates winners automatically

Planned Upgrade Path

1

Commit-Reveal Oracle Consensus

Multiple oracles submit hashed commits, then reveal. Majority wins.
2

Slashing for Dishonest Oracles

Oracles stake tokens. Dishonest submissions result in slashed stakes.
3

Screenshot Proof Required

Oracles must submit IPFS-pinned screenshots as proof of the actual text.
X API Update (Feb 2026): X.com now offers pay-per-use API access with no monthly subscriptions. This makes multi-oracle verification economically viable.

Backend Services (Prototype)

Backend services are Python modules that support the Flask API:
services/
├── blockchain_base.py      # Web3 contract interactions
├── v2_resolution.py        # Market resolution service (owner-based)
├── event_hooks.py          # Webhook event emitter (market.resolved, etc.)
├── auth_store.py           # Redis-backed nonce/OTP storage
├── xcom_api_service.py     # X.com API + Playwright screenshots
├── text_analysis.py        # Levenshtein distance (Python side)
├── cache_manager.py        # Redis caching for RPC responses
├── firebase_auth.py        # Email OTP authentication
├── embedded_wallet.py      # Coinbase wallet shim (PBKDF2, NOT production-safe)
└── monitoring.py           # Health checks

utils/
├── api_errors.py           # Standardized error responses
├── logging_config.py       # Structured logging (structlog)
└── request_context.py      # Request ID middleware

Key Services

Core Web3.py integration for contract interactions:
  • Contract initialization with ABIs
  • Transaction signing and submission
  • Event filtering and parsing
  • Gas estimation
Market resolution workflow:
  • Fetch actual text from X.com
  • Submit resolution transaction
  • Emit resolution events
  • Handle resolution failures
Redis caching layer:
  • Cache RPC responses (reduces blockchain calls)
  • TTL-based expiration
  • Cache invalidation on state changes
Uses PBKDF2 for testnet only. NOT production-safe. Replace with Coinbase CDP Server Signer before mainnet.
Wallet generation from email:
  • Derive keypair from email + password
  • Sign transactions
  • Testnet convenience feature

API Routes

All data is fetched from blockchain. Zero database.
routes/
├── api_chain.py            # /api/chain/* - blockchain queries
├── auth.py                 # /auth/* - JWT wallet auth + OTP (Redis-backed)
├── proteus.py              # /proteus/* - market operations + admin resolution
├── embedded_auth.py        # /api/embedded/* - Coinbase wallet auth
├── admin.py                # /admin/* - resolution dashboard
├── error_handlers.py       # Standardized error handling
└── ...                     # Other route modules (marketing, docs, oracles)

Key Endpoints

RouteMethodPurpose
/api/chain/marketsGETList all markets
/api/chain/markets/:idGETGet market details
/api/chain/submissions/:idGETGet submission details
/auth/request-otpPOSTRequest email OTP
/auth/verify-otpPOSTVerify OTP and get JWT
/proteus/create-marketPOSTCreate new market
/proteus/submit-predictionPOSTSubmit prediction
/admin/resolvePOSTResolve market (owner only)

Gas Considerations

Levenshtein distance computation is the expensive operation:
String LengthApproximate GasCost at 5 gwei
50 chars each~400,000$0.002
100 chars each~1,500,000$0.008
280 chars each~9,000,000$0.045
Predictions are capped at 280 characters (tweet length) to prevent block gas limit DoS attacks.

Optimization Strategies

  • Early termination if distance exceeds current minimum
  • Gas-efficient string comparison (minimize SLOAD operations)
  • Batch resolution for multiple markets (future)

Caching Strategy (Redis)

Redis caches RPC responses and stores authentication state:
Data TypeTTLPurpose
Actors5 minX.com actor metadata
Markets30 secMarket state and submissions
Stats10 secPlatform statistics
Auth nonces5 minWallet authentication
OTP codes5 minEmail verification
Gas price5 secGas estimation

Cache Invalidation

  • Invalidate on-chain state changes (market created, resolved, etc.)
  • TTL-based expiration for stale data
  • Manual flush for emergency updates

Security Posture

Smart Contracts ✅

  • Reentrancy guards on all payment functions (OpenZeppelin)
  • No upgradeable proxies (immutable deployments)
  • Slither static analysis complete (1 real bug found and fixed)
No external audit — This is the biggest gap before mainnet.

Backend ⚠️

  • JWT wallet authentication with nonce-based replay protection
  • Redis-backed OTP storage with TTL expiry
  • OTP rate limiting (3 per 15 min) and brute-force protection (5 attempts)
  • Flask-Limiter rate limiting on all endpoints
Embedded wallet uses PBKDF2 shim — Testnet only, not production-safe.

Known Centralization Risks

Critical issues to address before mainnet:
  1. Single EOA resolves markets — Owner-based resolution is centralized
  2. No multisig on contract owner key — Single point of failure
  3. Backend is a single Flask instance — No redundancy

Network Configuration

BASE Sepolia (Testnet) — Current

BASE Mainnet — Not Deployed

  • Chain ID: 8453
  • RPC: Requires Alchemy/QuickNode
  • Explorer: basescan.org
Do not deploy to mainnet without completing security prerequisites. See Deployment guide.

Technology Stack

Blockchain

  • Network: BASE (Coinbase L2, OP Stack)
  • Contracts: Solidity 0.8.20
  • Libraries: OpenZeppelin Contracts 5.4.0
  • Development: Hardhat 2.26.1
  • Testing: Hardhat + Chai

Backend

  • Language: Python 3.11+
  • Framework: Flask 3.1.1
  • Web Server: gunicorn 23.0.0
  • Blockchain: Web3.py 7.12.1
  • Queue: Celery 5.5.3 + Redis
  • Cache: Redis 6.2.0
  • Auth: JWT + Firebase

Frontend

  • Web3: Web3.js
  • Wallet: Coinbase Wallet SDK
  • Auth: Firebase Auth
  • UI: Vanilla JavaScript (no framework)

Fee Distribution

The 7% platform fee is distributed across stakeholders:
RecipientShareAmount per 100 ETH Volume
Genesis NFT Holders20%1.4 ETH
Oracles28.6%2.0 ETH
Market Creators14.3%1.0 ETH
Node Operators14.3%1.0 ETH
Builder Pool28.6%2.0 ETH
Total100%7.0 ETH
Fees are collected in the DistributedPayoutManager contract and distributed according to this schedule.

Next Steps

Local Setup

Set up your development environment

Testing

Run the comprehensive test suite

Deployment

Deploy contracts and backend

Smart Contracts

Dive into contract details

Build docs developers (and LLMs) love