> For the complete documentation index, see [llms.txt](https://docs.evently.market/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.evently.market/smart-contracts/markets.md).

# EventlyMarkets.sol

**Status:** Pending deployment — pre-launch audit complete **Dependencies:** OpenZeppelin ERC-1155, ERC-20 SafeERC20, PRBMath SD59x18, Redstone EVM Connector

***

## Overview

EventlyMarkets 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 (b=200 USDm), permanent liquidity provider
* **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
* **Dual whitelist** — separate whitelists for market creators (always enforced) and traders (beta-only)
* **Dispute system** — any market participant can dispute; dedicated `disputeResolver` role settles; monthly VRF lottery for successful disputers
* **Oracle markets** — price-feed-based binary markets resolved automatically via Redstone Pull-model oracle
* **Lucky Trader raffle** — weekly VRF raffle over active traders; winner-takes-all bonus drawn by admin

***

## Key Parameters

| Parameter                       | Value                                                      |
| ------------------------------- | ---------------------------------------------------------- |
| Creator collateral              | 50 USDm                                                    |
| Import fee (Polymarket markets) | 10 USDm (one-time, goes to treasury)                       |
| Dispute collateral              | 50 USDm (waived for admin)                                 |
| Dispute window                  | 24 hours after resolution                                  |
| Finalization buffer             | +1 hour after dispute window (sequencer guard)             |
| Burn delay (losing shares)      | 24 hours after finalization                                |
| Total fee                       | 2.5% fixed (1% creator + 1% treasury + 0.5% resolver pool) |
| Max options per market          | 4                                                          |
| Min options per market          | 2                                                          |
| Min betting window              | 1 hour (prevents flash markets)                            |
| Min trade                       | 0.001 shares (1e15)                                        |
| Min order value                 | 1 USDm (anti-dust)                                         |
| LMSR liquidity parameter b      | 200 USDm                                                   |
| Max orders per book             | 200 per (market, option, side)                             |
| Max orders per user per market  | 10 (all options + sides combined)                          |
| Max pause duration              | 72 hours (auto-expiry)                                     |
| Treasury withdrawal delay       | 24 hours timelock                                          |
| Resolver pool change delay      | 24 hours timelock                                          |
| 1 winning share pays out        | 1 USDm exactly                                             |
| Dispute lottery share           | 30% of treasury gains from successful disputes             |
| Dispute lottery cycle           | 30 days                                                    |
| Dispute lottery style           | Winner-takes-all (VRF selected)                            |
| Max weekly lucky traders        | 500 per week                                               |
| Lucky trader week duration      | 7 days                                                     |

***

## LMSR Pricing Mechanism

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

```
C(q) = b × ln( Σ 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) / Σ 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 × 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 execution at AMM price

Resolution -> Creator calls resolveMarket() with evidence hash (admin only for imported markets)
           -> 24h dispute window opens
           -> disputeResolver settles if disputed, with evidence hash

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

***

## Market Lifecycle

```
Active → BettingClosed → Resolved → [Disputed] → Finalized
                                          |
                                    Cancelled / Slashed
```

1. **Created** — creator locks 50 USDm collateral + LMSR subsidy. `winningOption` initialized to `type(uint256).max` (sentinel: not yet resolved).
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 with a mandatory evidence hash. 24-hour dispute window opens.
5. **Disputed** — any market participant (trader or creator) can dispute by posting 50 USDm collateral. Admin disputes are free (security function). `disputeResolver` (not admin) adjudicates with evidence hash.
6. **Finalized** — dispute window closes without challenge, or `disputeResolver` settles. Winners redeem at 1 USDm/share.
7. **Cancelled** — only allowed before any trading activity, or after `resolutionDeadline` timeout. If timeout: creator's accrued fees are confiscated to treasury.
8. **Slashed** — admin can slash a market in `Active`, `BettingClosed`, `Resolved`, or `Disputed` status. Cannot slash `Finalized`, `Cancelled`, or already-`Slashed` markets. Creator collateral goes to treasury; shareholders get pro-rata refund.

**Mandatory resolution:** `cancelMarket` is blocked if `totalVolume > 0` or there are active resting orders, unless `resolutionDeadline` has passed. A market with any activity must be resolved (or time out) — it cannot be quietly cancelled.

***

## Access Control Roles

| Role               | Address                          | Capabilities                                                                                                               |
| ------------------ | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `admin`            | Multisig                         | Whitelist management, pause, ban, slash markets, admin markets, treasury (timelocked), admin cancel orders, transfer roles |
| `disputeResolver`  | Dedicated address                | `settleDispute()` only — cannot resolve markets or access treasury                                                         |
| Market creator     | `marketCreatorWhitelisted[addr]` | Create markets, resolve their own markets, cancel their own markets                                                        |
| Whitelisted trader | `whitelisted[addr]`              | Trade, dispute participated markets                                                                                        |

The `disputeResolver` and `admin` are separate roles. Admin cannot unilaterally settle disputes.

***

## Whitelist System

Two independent whitelists:

* **Trader whitelist** (`whitelisted`) — controls who can trade. Enforced during beta; disabled (`setWhitelistEnabled(false)`) at public launch.
* **Creator whitelist** (`marketCreatorWhitelisted`) — controls who can create markets. Always enforced.

Admin is implicitly a market creator. Admin also bypasses the trader whitelist — the `onlyWhitelisted` modifier always passes for admin, regardless of `whitelistEnabled`.

***

## 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`) | Redirected post-TGE to staking contract (24h timelock on changes) |
| **Total**      | **2.5% (fixed)**             | Not configurable                                                  |

Admin markets: creator cut goes to treasury.

**Dispute lottery allocation:** When a dispute is settled against the creator, 30% of the net treasury gain from that dispute (slashed collateral portion + slashed creator fees) is routed to the current month's dispute lottery pool instead of treasury. Distributed equally to all that month's successful disputers via `distributeMonthlyDisputeRewards()`.

***

## Dispute System

### Eligibility

Any address that has placed an order or sold to the AMM on the market (`hasParticipated[marketId][user] == true`) can dispute. Admin can always dispute (free of charge, security function).

Imported Polymarket markets can be disputed under the same rules.

### Collateral

* Regular disputer: posts 50 USDm. Returned + 25 USDm reward if right; forfeited to treasury if wrong.
* Admin disputer: no collateral posted. If right: nothing transferred. If wrong: 25 USDm reward added to treasury from creator collateral.

### Settlement

`disputeResolver` calls `settleDispute(marketId, creatorWasRight, finalOption, evidenceHash)`. Evidence hash is mandatory and emitted as `ResolutionEvidence` event.

**If creator was right (dispute rejected):**

* Disputer's 50 USDm collateral → treasury (if they paid it)

**If creator was wrong (dispute upheld):**

* Creator loses 50 USDm collateral:
  * Regular disputer: disputer receives back their 50 USDm + 25 USDm reward (75 USDm total). 25 USDm of creator collateral → treasury (after lottery deduction)
  * Admin disputer: full 50 USDm creator collateral → treasury (after lottery deduction)
* All creator accrued fees slashed to treasury (after lottery deduction)
* 30% of net treasury gain → current month's lottery pool (`monthlyDisputePool[month]`)
* Market finalized with `_finalOption`

***

## Monthly Dispute Lottery

Successful disputers accumulate entries in `_monthlyDisputers[month]` (one entry per won dispute). After month `M` ends, admin calls `distributeMonthlyDisputeRewards(M, vrfProof, vrfMessage)`:

* **Winner-takes-all** — one disputer is selected via Drand BLS12-381 VRF (MegaETH native precompile). `winnerIndex = uint256(keccak256(vrfProof)) % count`
* The full `monthlyDisputePool[M]` is transferred to the single winner
* VRF proof is verified on-chain before the winner is selected — invalid proof reverts
* Cannot be called again for the same month (idempotent guard)

**View:** `getMonthlyDisputers(month)` — returns disputer list for any past month.

***

## Oracle Markets

Oracle markets are binary prediction markets resolved automatically from a Redstone price feed, without requiring a human resolver.

### Creating an Oracle Market

```solidity
createOracleMarket(
    string  question,
    string[] options,         // exactly 2: e.g. ["Yes", "No"]
    Category category,
    string  resolutionCriteria,
    string  imageURI,
    uint256 bettingDeadline,
    uint256 resolutionDeadline,
    bytes32 priceFeedId,      // e.g. bytes32("ETH")
    uint256 strikePrice,      // in feed decimals (8 dp) — e.g. 3000_00000000 = $3,000
    bool    strikeAbove       // true: option 0 wins if price >= strike; false: wins if price <= strike
)
```

Constraints:

* Must have exactly **2 options** (binary market)
* `priceFeedId` must be non-zero (`bytes32("ETH")`, `bytes32("BTC")`, `bytes32("SOL")`, `bytes32("MEGA")`, etc.)
* `strikePrice` must be non-zero

### Supported Price Feeds

Feeds are sourced from the `redstone-primary-prod` data service (5-signer threshold). The `priceFeedId` is a right-padded `bytes32` encoding of the ticker string:

| Asset      | priceFeedId (bytes32 of ASCII) |
| ---------- | ------------------------------ |
| ETH / USD  | `bytes32("ETH")`               |
| BTC / USD  | `bytes32("BTC")`               |
| SOL / USD  | `bytes32("SOL")`               |
| MEGA / USD | `bytes32("MEGA")`              |

### Resolving an Oracle Market

```solidity
resolveMarketWithOracle(uint256 marketId, bytes32 evidenceHash)
```

* Permissionless — anyone can call it (typically a keeper script)
* Reads the Redstone price injected in calldata by the keeper
* `conditionMet = strikeAbove ? price >= strike : price <= strike`
* `winningOption = conditionMet ? 0 : 1`
* Requires: betting deadline passed, resolution deadline not expired, evidence hash provided
* Verifies Redstone data freshness and signature count (≥3 signers from `redstone-primary-prod`)

**View:** `getOracleConfig(marketId)` — returns `(priceFeedId, strikePrice, strikeAbove)`.

### Keeper Script

`scripts/resolve-oracle.js` scans all markets, identifies eligible oracle markets, wraps the call with `WrapperBuilder` (injects Redstone price calldata), and calls `resolveMarketWithOracle`. Configure with:

```
REDSTONE_DATA_SERVICE=redstone-primary-prod
DRY_RUN=true  # set to false to send actual transactions
```

***

## Lucky Trader Weekly Raffle

Every week, one active trader wins a USDm bonus drawn by VRF.

### Eligibility

Any address that calls `placeOrder` or `sellToAMM` is automatically entered into the current week's raffle — at most once per address per week (`hasEnteredWeek[week][addr]`). The raffle tracks up to 500 addresses per week (`MAX_WEEKLY_TRADERS`).

### Drawing the Winner

```solidity
drawLuckyTrader(
    uint256 week,
    bytes   vrfProof,
    bytes   vrfMessage,
    uint256 bonusAmount   // in USDm (18 decimals)
)
```

* Admin only; callable once per week (`weeklyLuckyDrawn[week]`)
* VRF verified on-chain via the Drand BLS12-381 precompile at `drandVerifier`
* `winnerIndex = uint256(keccak256(vrfProof)) % traderCount`
* `bonusAmount` is debited from `treasuryBalance` — reverts if treasury insufficient
* Emits `LuckyTraderWinner(week, winner, bonusAmount)`

**Views:**

* `getWeeklyTraders(week)` — returns all entered addresses for that week
* `getCurrentWeek()` — returns the active week number (`block.timestamp / WEEK_DURATION`)

### Admin Setup

`setDrandVerifier(address)` — set the Drand precompile address (admin only). The precompile address is network-specific; confirm via MegaETH documentation before deployment.

***

## Emergency Controls

### Pause

`pause()` — admin only. Blocks all trading and market creation. Auto-expires after 72 hours (`MAX_PAUSE_DURATION`). Anyone can call `unpause()` after 72h have elapsed; admin can unpause at any time.

### Ban

`banAddress(addr)` / `unbanAddress(addr)` — admin only. Banned addresses cannot interact with any market function.

### Admin Cancel Orders

`adminCancelOrders(orderIds[])` — admin only. Force-cancels resting orders and returns escrowed funds to order owners. Used to remediate griefing or banned-address orders.

### Timelocked Admin Operations

| Operation                    | Delay    | Request                                 | Execute                       | Cancel                       |
| ---------------------------- | -------- | --------------------------------------- | ----------------------------- | ---------------------------- |
| Treasury withdrawal          | 24 hours | `requestTreasuryWithdrawal(to, amount)` | `executeTreasuryWithdrawal()` | `cancelTreasuryWithdrawal()` |
| Resolver pool address change | 24 hours | `requestResolverPoolChange(addr)`       | `executeResolverPoolChange()` | `cancelResolverPoolChange()` |

***

## Security Properties Implemented

| ID            | Property                                                                                            |
| ------------- | --------------------------------------------------------------------------------------------------- |
| F-02          | `claimCancelRefund` — pre-burn snapshot prevents sequential claim insolvency                        |
| A-03          | `MAX_ORDERS_PER_BOOK = 200` per (market, option, side) — prevents O(n) DoS                          |
| F-DS-M02      | `_cleanBook()` called on `cancelOrder` — dead CLOB entries removed immediately                      |
| R2-2          | `claimCreatorFees` requires `Finalized` status — blocked while Disputed                             |
| L-01          | `nonReentrant` on all fund-moving external functions; custom inline mutex (not OZ)                  |
| GROK-M01      | `subsidyDeposited` included in cancel refund pool — recoverable by shareholders                     |
| GPT-R3-3      | `slashMarket` handles `Disputed` status — no funds stranded                                         |
| GROK-L02      | `createdAt != 0` guard on all view functions                                                        |
| BIZ-06        | `MIN_BETTING_WINDOW = 1 hour` — prevents flash markets                                              |
| ATCK-06       | `MIN_ORDER_VALUE = 1 USDm` per order — prevents dust griefing                                       |
| ATCK-07       | `FINALIZE_BUFFER = 1 hour` — sequencer timestamp manipulation guard                                 |
| AC-03         | Treasury withdrawal 24h timelock                                                                    |
| INV-06        | `winningOption` sentinel = `type(uint256).max` — prevents accidental option-0 resolution            |
| INV-08        | `_cleanBook` called before length check in `_restOrder`                                             |
| MATH-10       | Last claimer receives full `effectivePool` — dust prevention                                        |
| SEC-PAUSE     | Emergency pause with 72h auto-expiry; force-unpause by anyone after expiry                          |
| SEC-BAN       | Address ban + `adminCancelOrders` for targeted remediation                                          |
| SEC-SLIPPAGE  | `minUsdmOut` mandatory in `sellToAMM` — sandwich attack prevention                                  |
| SEC-ORDERCAP  | `MAX_ORDERS_PER_USER = 10` per market per address                                                   |
| SEC-TIMELOCK  | Resolver pool address change 24h timelock                                                           |
| SEC-RESOLVER  | Separate `disputeResolver` role — admin cannot settle disputes unilaterally                         |
| SEC-EVIDENCE  | Mandatory evidence hash on `resolveMarket` and `settleDispute`                                      |
| SEC-DISPUTE   | Disputes open to all participants; imported markets disputable; admin free                          |
| SEC-MANDATORY | `cancelMarket` blocked on active markets — mandatory resolution                                     |
| SEC-CREATORS  | Separate `marketCreatorWhitelisted` mapping                                                         |
| SEC-LOTTERY   | 30% of treasury gains from successful disputes → monthly lottery pool                               |
| Q7-CONDID     | `_validateConditionId`: 66-char, `0x`-prefix, lowercase hex only — prevents case-aliased duplicates |

***

## 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; `minUsdmOut` required
* `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
* `getPoolBalance(marketId)` — pool balance + subsidy deposited
* `getMarketInfo(marketId)` — full market struct
* `getCreatorFees(marketId)` — accrued creator fees + claimed flag
* `getBidBook(marketId, optionIndex)` — resting bid order IDs
* `getAskBook(marketId, optionIndex)` — resting ask order IDs
* `getOrderInfo(orderId)` — full order struct
* `isDisputeWindowOpen(marketId)` — true if 24h dispute window is still open
* `isBurnReady(marketId)` — true if losing shares can be burned (24h after finalization)
* `getMonthlyDisputers(month)` — disputer addresses for a given 30-day lottery month
* `getOracleConfig(marketId)` — returns `(priceFeedId, strikePrice, strikeAbove)` for oracle markets
* `getWeeklyTraders(week)` — addresses entered in the weekly lucky trader raffle
* `getCurrentWeek()` — active week number (`block.timestamp / WEEK_DURATION`)

### Market Management

* `createMarket(...)` — `onlyMarketCreator` + `onlyWhitelisted`; locks 50 USDm collateral + LMSR subsidy
* `createAdminMarket(...)` — `onlyAdmin`; pays subsidy only (no collateral)
* `createImportedMarket(...)` — `onlyMarketCreator`; pays 10 USDm import fee + subsidy; conditionId validated
* `createOracleMarket(question, options, category, criteria, imageURI, bettingDeadline, resolutionDeadline, priceFeedId, strikePrice, strikeAbove)` — `onlyMarketCreator`; exactly 2 options; locks collateral + subsidy; feeds via Redstone
* `resolveMarket(marketId, winningOption, evidenceHash)` — creator resolves after betting deadline; evidence hash required. For imported Polymarket markets: admin only (creator cannot resolve)
* `resolveMarketWithOracle(marketId, evidenceHash)` — permissionless; reads Redstone price from calldata; resolves oracle market automatically
* `closeBetting(marketId)` — permissionless; callable by anyone after `bettingDeadline`
* `disputeMarket(marketId, proposedOption)` — any participant; 50 USDm collateral (waived for admin)
* `settleDispute(marketId, creatorWasRight, finalOption, evidenceHash)` — `onlyDisputeResolver`; evidence hash required
* `finalizeMarket(marketId)` — permissionless; callable by anyone after dispute window + buffer
* `cancelMarket(marketId)` — blocked on active markets (mandatory resolution); allowed after timeout or if no activity
* `slashMarket(marketId, reason)` — `onlyAdmin`; 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; last claimer gets full remaining pool
* `claimCreatorFees(marketId)` — creator withdraws accrued fees (post-finalization only)
* `burnLosingShares(marketId, holders[])` — admin keeper; burns losing shares 24h after finalization
* `reclaimCancelledOrder(orderId)` — claim escrowed funds from a cancelled order (lazy refund pattern)

### Admin

* `distributeMonthlyDisputeRewards(month, vrfProof, vrfMessage)` — draw VRF winner-takes-all from monthly dispute lottery pool
* `drawLuckyTrader(week, vrfProof, vrfMessage, bonusAmount)` — draw weekly lucky trader winner via VRF; debits treasury
* `setDrandVerifier(addr)` — set Drand BLS12-381 precompile address
* `requestTreasuryWithdrawal(to, amount)` / `executeTreasuryWithdrawal()` / `cancelTreasuryWithdrawal()` — 24h timelocked withdrawal
* `requestResolverPoolChange(addr)` / `executeResolverPoolChange()` / `cancelResolverPoolChange()` — 24h timelocked resolver update
* `withdrawResolverPool(amount)` — pull accumulated resolver fees
* `setDisputeResolver(addr)` — assign the `disputeResolver` role
* `transferAdmin(newAdmin)` / `acceptAdmin()` — two-step admin transfer
* `addToWhitelist(wallet)` / `batchWhitelist(wallets[])` / `removeFromWhitelist(wallet)` — trader whitelist
* `batchAddMarketCreators(accounts[])` — bulk add to creator whitelist
* `setWhitelistEnabled(bool)` — toggle trader whitelist enforcement
* `addMarketCreator(addr)` / `removeMarketCreator(addr)` — creator whitelist
* `banAddress(addr)` / `unbanAddress(addr)` — block address from all functions
* `adminCancelOrders(orderIds[])` — force-cancel resting orders (returns funds to owners)
* `pause()` / `unpause()` — emergency pause (72h auto-expiry; anyone can force-unpause after)
* `upvoteMarket(marketId)` — community upvote (whitelisted traders); emits `MarketUpvoted`
* `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); also before length check in `_restOrder` (INV-08) |
| Book cap           | 200 orders per (market, option, side) — griefing cap                                                      |
| Per-user cap       | 10 active orders per market per address — per-user saturation cap                                         |
| Min order value    | 1 USDm — prevents dust order griefing                                                                     |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.evently.market/smart-contracts/markets.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
