|
| 1 | +# Prediction Market Contract |
| 2 | + |
| 3 | +A prediction market implementation on Aztec using a **Constant Sum Market Maker (CSMM)** for binary outcomes with **full identity privacy**. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +This contract allows users to: |
| 8 | +- **Bet on binary outcomes** (YES/NO) **anonymously** - no one knows WHO placed a bet |
| 9 | +- **Hold fully private balances** - collateral and share holdings are all hidden |
| 10 | +- **Experience dynamic pricing** that adjusts based on market sentiment |
| 11 | +- **Get slippage protection** to prevent adverse price movements |
| 12 | +- **Single-transaction betting** using partial notes pattern |
| 13 | + |
| 14 | +## Privacy Model |
| 15 | + |
| 16 | +### What's Private |
| 17 | + |
| 18 | +| Data | Privacy | Notes | |
| 19 | +|------|---------|-------| |
| 20 | +| Bettor identity | **PRIVATE** | Public function doesn't receive sender address | |
| 21 | +| Collateral balances | **PRIVATE** | Stored as private notes (UintNote) | |
| 22 | +| Share balances | **PRIVATE** | Stored as private notes (UintNote) | |
| 23 | +| Your bet (YES/NO) | **PRIVATE** | Hidden via partial notes | |
| 24 | + |
| 25 | +### What's Public |
| 26 | + |
| 27 | +| Data | Visibility | Why | |
| 28 | +|------|------------|-----| |
| 29 | +| Price changes | PUBLIC | Necessary for AMM pricing | |
| 30 | +| Trade amounts | PUBLIC | Affects price movement | |
| 31 | +| That someone bought YES/NO | PUBLIC | Observable from price changes | |
| 32 | + |
| 33 | +### Privacy Architecture |
| 34 | + |
| 35 | +The contract uses **partial notes** for private betting (like the [AMM contract](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts/amm_contract)): |
| 36 | + |
| 37 | +``` |
| 38 | +1. buy_outcome() [PRIVATE] |
| 39 | + | |
| 40 | + +-- Consumes private collateral notes |
| 41 | + +-- Creates change note if needed |
| 42 | + +-- Creates partial note commitment (hides owner) |
| 43 | + +-- Enqueues public call WITHOUT sender address |
| 44 | + v |
| 45 | +2. _process_buy() [PUBLIC] |
| 46 | + | |
| 47 | + +-- Calculates shares based on CSMM pricing |
| 48 | + +-- Updates YES/NO supplies (price changes) |
| 49 | + +-- Completes partial note with share amount |
| 50 | + v |
| 51 | + Shares appear in user's private balance (single tx!) |
| 52 | +``` |
| 53 | + |
| 54 | +Key privacy feature: The public `_process_buy()` function **does not receive the sender address**. It only knows WHAT was traded, not WHO traded. |
| 55 | + |
| 56 | +## Usage |
| 57 | + |
| 58 | +### Betting Flow (Single Transaction) |
| 59 | + |
| 60 | +```typescript |
| 61 | +// Deposit collateral privately |
| 62 | +await market.methods.deposit(1000n).send({ from: myAddress }).wait() |
| 63 | + |
| 64 | +// Buy outcome privately - single transaction! |
| 65 | +await market.methods.buy_outcome( |
| 66 | + true, // is_yes |
| 67 | + 500n, // collateral_amount |
| 68 | + 900n, // min_shares_out (slippage protection) |
| 69 | +).send({ from: myAddress }).wait() |
| 70 | + |
| 71 | +// Your shares are immediately in your private balance! |
| 72 | +const myBalance = await market.methods.get_yes_balance(myAddress).simulate({ from: myAddress }) |
| 73 | +``` |
| 74 | + |
| 75 | +### Collateral Management (All Private) |
| 76 | + |
| 77 | +```typescript |
| 78 | +// Deposit collateral (private) |
| 79 | +await market.methods.deposit(1000n).send({ from: myAddress }).wait() |
| 80 | + |
| 81 | +// Withdraw collateral (private) |
| 82 | +await market.methods.withdraw(500n).send({ from: myAddress }).wait() |
| 83 | + |
| 84 | +// Check balance (view private notes) |
| 85 | +const balance = await market.methods.get_collateral_balance(myAddress).simulate({ from: myAddress }) |
| 86 | +``` |
| 87 | + |
| 88 | +## Development |
| 89 | + |
| 90 | +### Prerequisites |
| 91 | + |
| 92 | +```bash |
| 93 | +# Install Aztec tools |
| 94 | +bash -i <(curl -s https://install.aztec.network) |
| 95 | +aztec-up 3.0.0-devnet.5 |
| 96 | + |
| 97 | +# Install dependencies |
| 98 | +yarn install |
| 99 | +``` |
| 100 | + |
| 101 | +### Building |
| 102 | + |
| 103 | +```bash |
| 104 | +# Compile the contract |
| 105 | +aztec-nargo compile |
| 106 | + |
| 107 | +# Post-process and generate TypeScript bindings |
| 108 | +aztec-postprocess-contract |
| 109 | +aztec codegen target -o artifacts |
| 110 | +``` |
| 111 | + |
| 112 | +### Testing |
| 113 | + |
| 114 | +#### Noir Unit Tests |
| 115 | + |
| 116 | +```bash |
| 117 | +aztec test |
| 118 | +``` |
| 119 | + |
| 120 | +Tests the CSMM pricing functions: |
| 121 | +- Share calculations at various price points |
| 122 | +- Price calculations and invariants |
| 123 | +- Edge cases |
| 124 | + |
| 125 | +#### End-to-End Tests |
| 126 | + |
| 127 | +```bash |
| 128 | +# Start Aztec sandbox (in separate terminal) |
| 129 | +aztec start --sandbox |
| 130 | + |
| 131 | +# Run tests |
| 132 | +yarn test |
| 133 | +``` |
| 134 | + |
| 135 | +Tests the full private betting flow: |
| 136 | +- Contract deployment |
| 137 | +- Private deposit/withdraw |
| 138 | +- Private buy_outcome (single tx with partial notes) |
| 139 | +- Price movements |
| 140 | +- Balance privacy |
| 141 | + |
| 142 | +## Constant Sum Market Maker (CSMM) |
| 143 | + |
| 144 | +### Core Invariant |
| 145 | +``` |
| 146 | +price_YES + price_NO = 1 |
| 147 | +``` |
| 148 | + |
| 149 | +### Pricing Formula |
| 150 | +``` |
| 151 | +price_YES = yes_supply / (yes_supply + no_supply) |
| 152 | +shares_out = collateral_in / current_price |
| 153 | +``` |
| 154 | + |
| 155 | +### Example |
| 156 | + |
| 157 | +``` |
| 158 | +Initial: YES=5000, NO=5000, price_YES=50% |
| 159 | +
|
| 160 | +Alice buys 1000 collateral of YES: |
| 161 | +- Shares received: 1000 / 0.50 = 2000 YES |
| 162 | +- New YES supply: 7000 |
| 163 | +- New price_YES: 7000 / 12000 = 58.3% |
| 164 | +``` |
0 commit comments