# EventlyMarketsV3.sol

**Version:** v3.2 (post-audit, pre-deployment) **Status:** Pending deployment (audit complete) **Dependencies:** OpenZeppelin ERC-1155, ERC-20 SafeERC20, PRBMath SD59x18

***

## Overview

EventlyMarketsV3 is the production prediction markets contract for evently. It combines:

* **ERC-1155 tradable positions** -- each trade mints/burns fungible shares per outcome
* **LMSR AMM** -- Logarithmic Market Scoring Rule for automated, manipulation-resistant pricing (b=200 USDm)
* **CLOB (Central Limit Order Book)** -- bids and asks with price-time priority, matched automatically on `placeOrder`
* **Creator economy** -- 1% creator fee on all volume, claimable after finalization

The LMSR mechanism eliminates the core flaw of parimutuel systems: being correct always yields a profit, regardless of how many people chose the same option.

***

## Key Parameters

| Parameter                  | Value                                                |
| -------------------------- | ---------------------------------------------------- |
| Creator collateral         | 50 USDm                                              |
| Dispute collateral         | 50 USDm                                              |
| Dispute window             | 24 hours                                             |
| Burn delay (losing shares) | 24 hours after finalization                          |
| Total fee (default)        | 2.5% (1% creator + 1% treasury + 0.5% resolver pool) |
| Fee hard cap               | 5%                                                   |
| Max options per market     | 4                                                    |
| Min options per market     | 2                                                    |
| Min trade                  | 0.001 shares (1e15)                                  |
| LMSR liquidity parameter b | 200 USDm (200e18)                                    |
| Max orders per book        | 200 per (market, option, side)                       |
| 1 winning share pays out   | 1 USDm exactly                                       |

***

## LMSR Pricing Mechanism

LMSR (Logarithmic Market Scoring Rule) is an automated market maker where price follows a mathematically sound cost function:

```
C(q) = b x ln( sum exp(q[i] / b) )
```

* `q[i]` = shares outstanding for option i
* `b` = liquidity parameter (200 USDm) -- controls price sensitivity
* Cost to buy shares of option i = C(q after) - C(q before)

**Implied probability of option i:**

```
P(i) = exp(q[i]/b) / sum exp(q[j]/b)
```

At initialization all quantities are 0, so each option starts at 1/n probability. Prices always sum to exactly 1.

**Market subsidy:** To bootstrap liquidity, the creator locks `b x ln(n)` USDm at market creation. This subsidy guarantees solvency: `poolBalance + subsidyDeposited >= total winning shares` at all times.

***

## Architecture

```
BUY order  -> CLOB ask orders filled first (price-time priority)
           -> Remaining budget routed to LMSR AMM

SELL order -> CLOB bid orders filled first (price-time priority)
           -> Unmatched remainder rests as limit ask in CLOB
           -> OR: sellToAMM() for instant AMM execution

Resolution -> Each winning share redeemable for exactly 1 USDm
Cancelled  -> All holders get pro-rata refund (poolBalance + subsidyDeposited)
```

***

## Market Lifecycle

1. **Created** -- creator locks 50 USDm collateral + LMSR subsidy (`b x ln(n)`)
2. **Active** -- users buy/sell shares via LMSR AMM and CLOB
3. **BettingClosed** -- after betting deadline, no new trades
4. **Resolved** -- creator declares winning option
5. **Dispute Window** (24h) -- any whitelisted user can dispute by locking 50 USDm
6. **Finalized** -- after dispute window closes or admin settles dispute
7. **Redemption** -- winning shareholders call `redeemWinnings()` for 1 USDm per share

***

## Fee Structure

| Recipient      | Default                      | Description                                                   |
| -------------- | ---------------------------- | ------------------------------------------------------------- |
| Market creator | 1% (`creatorFeeBps = 100`)   | Accrues in `creatorAccruedFees`, claimable after finalization |
| Treasury       | 1% (`treasuryFeeBps = 100`)  | Accumulates in `treasuryBalance`                              |
| Resolver pool  | 0.5% (`resolverFeeBps = 50`) | Initially = admin; redirected post-TGE to staking             |
| **Total**      | **2.5%**                     | Hard cap: 5% via `setFees()`                                  |

Admin markets (created by admin): creator cut goes to treasury instead.

***

## Audit Fixes Applied (v3.2)

| ID       | Fix                                                                                                                      |
| -------- | ------------------------------------------------------------------------------------------------------------------------ |
| F-02     | `claimCancelRefund` -- snapshot total supply before burning; prevents insolvency on sequential claims                    |
| A-03     | `MAX_ORDERS_PER_BOOK = 200` per (market, option, side) -- prevents O(n) DoS griefing                                     |
| F-DS-M02 | `_cleanBook()` called immediately in `cancelOrder` -- dead CLOB entries removed, book never fills up with ghosts         |
| R2-2     | `claimCreatorFees` requires `Finalized` status -- blocks creator fee claim while market is Disputed                      |
| L-01     | `nonReentrant` added to `resolveMarket`, `cancelMarket`, `slashMarket`                                                   |
| GROK-M01 | `subsidyDeposited` included in `claimCancelRefund` effective pool -- subsidy recoverable by shareholders on cancel/slash |
| GPT-R3-3 | `slashMarket` handles `Disputed` status -- dispute collateral swept to treasury, nothing stranded                        |
| GROK-L02 | `createdAt != 0` guard added to all view functions -- prevents silent zero returns for nonexistent markets               |
| QWEN-I03 | `BettingClosed` event emitted by `closeBetting`                                                                          |

***

## Functions

### Trading

* `placeOrder(marketId, optionIndex, side, quantity, pricePerShare, minFill)` -- BUY or SELL limit order; CLOB matched first, remainder to AMM for BUY
* `sellToAMM(marketId, optionIndex, shares, minUsdmOut)` -- instant sell to LMSR AMM at current price
* `cancelOrder(orderId)` -- cancel resting order; escrowed USDm or shares returned immediately

### Pricing (view)

* `getPrice(marketId, optionIndex)` -- LMSR implied probability (0 to 1e18)
* `getImpliedPrices(marketId)` -- array of all option probabilities
* `quoteBuy(marketId, optionIndex, usdmNet)` -- shares out for a given net USDm (binary search)
* `quoteSell(marketId, optionIndex, shares)` -- gross USDm out for a given share quantity
* `getQuantities(marketId)` -- outstanding shares per option
* `getSubsidy(marketId)` -- subsidy deposited and b parameter
* `getBidBook(marketId, optionIndex)` -- resting bid order IDs
* `getAskBook(marketId, optionIndex)` -- resting ask order IDs
* `getOrderInfo(orderId)` -- full order struct

### Market Management

* `createMarket(...)` -- locks 50 USDm collateral + LMSR subsidy
* `createAdminMarket(...)` -- admin pays subsidy only (no creator collateral)
* `resolveMarket(marketId, winningOption)` -- creator resolves after betting deadline
* `closeBetting(marketId)` -- permissionless; callable by anyone after bettingDeadline
* `disputeMarket(marketId, proposedOption)` -- dispute with 50 USDm collateral
* `settleDispute(marketId, creatorWasRight, finalOption)` -- admin settles
* `finalizeMarket(marketId)` -- callable by anyone after dispute window closes
* `cancelMarket(marketId)` -- creator, admin, or anyone after resolutionDeadline
* `slashMarket(marketId, reason)` -- admin; works on Active, BettingClosed, Resolved, Disputed

### Claims

* `redeemWinnings(marketId)` -- burn winning shares for 1 USDm each
* `claimCancelRefund(marketId)` -- pro-rata refund on cancelled/slashed markets
* `claimCreatorFees(marketId)` -- creator withdraws accrued fees (post-finalization only)
* `burnLosingShares(marketId, holders[])` -- admin keeper; burns losing shares 24h after finalization

### Admin

* `setFees(creatorBps, treasuryBps, resolverBps)` -- adjust fee split (<=5% total)
* `setResolverPoolAddress(addr)` -- redirect resolver fees
* `withdrawTreasury(to, amount)` -- pull accumulated treasury fees
* `withdrawResolverPool(to, amount)` -- pull accumulated resolver fees
* `transferAdmin(newAdmin)` -- transfer admin role
* `addToWhitelist(wallet)` / `batchWhitelist(wallets[])` / `removeFromWhitelist(wallet)` -- whitelist management
* `setWhitelistEnabled(bool)` -- toggle whitelist enforcement
* `createInviteCode(codeHash)` / `redeemInviteCode(code)` -- invite system

***

## Token ID Encoding

```
tokenId = marketId * MAX_OPTIONS + optionIndex
```

`MAX_OPTIONS = 4`, so each market occupies token IDs `[marketId*4, marketId*4+3]`.

***

## CLOB Design

| Property           | Value                                                      |
| ------------------ | ---------------------------------------------------------- |
| Order types        | BUY and SELL                                               |
| Matching           | Automatic on `placeOrder`                                  |
| Price priority     | Best price first (ascending for asks, descending for bids) |
| Time priority      | FIFO within same price level                               |
| Dead entry cleanup | Immediately on `cancelOrder` (`_cleanBook` -- F-DS-M02)    |
| Book cap           | 200 orders per (market, option, side)                      |
