Skip to main content

Market Mechanics

In CLUE, users create markets for events, trade outcomes and receive a settlement on the final result. The protocol does two things at once: ensures liquid trading (through AMM pricing) and ensures the quality/fairness of markets (through moderation and arbitration).

Key principle - execution of on-chain rules. Smart contracts record market statuses, role rights, fees and final payments. The interface and indexers are only a “showcase” for reading data: they have no privileges and cannot manage the funds (see protocol/interface legal separation).

Parameters (fees, limits, appeal windows, module addresses, pause/protection modes) are controlled by DAO governance delays (grace + executionWindow) (see governance flow and DAO mechanics). The team does not have a separate “admin bypass”: critical changes are possible only through on-chain decisions.

How the market works

In CLUE, the market follows a clear path: creation → verification → trading → filing → (if necessary) appeal/arbitration → final payout. At every step, participants have economic incentives, and the protocol has safeguards against abuse from the risk framework.

End-to-end flow: DAOrolesgrowth → traders → AMM → fees → resolution → rewards → DAO feedback

Simplified protocol flow
Governance stakeDAO Pool feeds DAO Registry control over parameters and modules.
Market publicationMarkets Registry records a creator market and opens the moderation path.
Listing reviewModerators apply quality checks and risk flags before trading activity matters.
Trading inputsDiscount stakers and referral partners shape fee economics around the market.
MarketAMMTraders buy and sell outcomes directly on-chain.
Outcome submissionMarketsLifecycle records the outcome and opens the appeal window when needed.
No disputeFinalization or auto-resolve closes the market without escalation.
Dispute pathAppeals escalate into arbitration backed by staked moderators and arbitrators.
Fee settlementMarketAMMFees split value between creator, referral, moderators, DAO, and burn.

Flywheel: More markets → more trades → more fees → more burn and rewards → more referrals → more markets

Types of markets

Cross-context: creator-driven content economy, market listing economics, risk labels quality layer.

All CLUE markets use a Multi-Outcome model: an event is formalized as a set of discrete outcomes. The Yes/No format is a special case of the same model with two outcomes (Yes and No).

At the contract level, this means that the market is always described by a finite set of alternatives, and the outcome is fixed by choosing one of them (or canceling in the provided lifecycle scenarios). This approach makes the system machine verifiable: each outcome has a unique index, trading liquidity is taken into account using the q[] vector, and payments after resolution are calculated deterministically. Important point: the protocol works with discrete outcomes, so complex “continuous” events (for example, the price of an asset as a number) must be broken down into understandable intervals/categories in advance.

  • Binary markets (2 outcomes): classic format Yes/No for questions with a clear fork (“will happen / will not happen”). This is the easiest type to understand and usually the most liquid at the start.
  • Categorical markets (N selections): one market contains several mutually exclusive options (for example, “who will win”, “which scenario will be realized”). All selections are traded on the same AMM curve, maintaining consistent pricing between options.
  • Range/Scenario Markets via Discretization: Custom logic can define a “basket” of ranges (e.g. A/B/C/D), but for the protocol it is still a categorical market with a fixed number of discrete outcomes.
  • Model limitations: the number of outcomes is limited by the protocol parameters (maxOutcomesCount), and each outcome must be determined in advance and unambiguously. This reduces ambiguity in resolution and simplifies the appeal circuit.

Market resolution types (Standard Resolve, Self Resolve)

Related rails: appeal opening, fee/stake escalation threshold, auto-resolve branch, arbitration consensus, governance-set parameters.

The resolution type is set when creating a market using the arbitrationMode parameter in addMarket(...): Standard (0) or Self (1). The current market register uses only statuses Approved, AwaitingAppeals, Finished.

  • Standard Resolve (ArbitrationMode.Standard): after submitOutcome the market goes into AwaitingAppeals. During the appealPeriod period, participants can submit an appeal through makeAppeal; When the threshold is reached, the dispute is escalated to arbitration. If there are no appeals/escalations, the market is closed via markFinished followed by resolve/cancel in AMM and finalizeFees.
  • Fallback in Standard mode: If the selection is not submitted to resolveAt + outcomeSubmissionGrace, any participant can call sendToResolve (auto-resolve with bond), which triggers the arbitrage circuit and prevents the market from hanging.
  • Self Resolve (ArbitrationMode.Self): only the creator can submit the outcome, and with submitOutcome the market is immediately transferred to Finished no appeal window and no arbitration; then AMM performs resolve/cancel and finalizeFees.
  • Key Difference: Appeals and arbitration are only available to Standard; for Self these branches are disabled at the contract logic level.

Market moderation

See also: moderation model, flags bit semantics, moderator/arbitrator staking pool.

In the current version of the protocol, moderation is implemented as flag-based on-chain quality control through cases in ModerationRegistry. This is important: moderation sets risk flags, but does not introduce a separate pre-trade status like Pending/Declined.

  • Case creation and financing: when the market is published, marketFee is transferred to the moderation circuit, after which a moderation case is created with a committee of moderators and a reward pool (economic source: market publication fee).
  • Committee vote: moderators vote with a bitmask of flags (vote(..., flags)). After a full set of committee votes, the case is finalized on-chain (quorum logic: moderation consensus).
  • How flags are formed: Weighted majority rule (>50% committee weight) is applied for each bit. The number of supported flags is specified by the moderationFlagsCount parameter (default 5, maximum 8), governed through DAO mechanics.
  • Flag specification (current profile at moderationFlagsCount = 5):
    • adultbit0 (mask 0x01, value 1)
    • violencebit1 (mask 0x02, value 2)
    • restricted_sensitive (restricted_sensetive) → bit2 (mask 0x04, value 4)
    • scam_risk (scam-risk) → bit3 (mask 0x08, value 8)
    • low_quality (low-quality) → bit4 (mask 0x10, value 16)At the contract level, only the uint8 bitmask and majority bit logic are stored; semantic names are a catalog/indexer specification on top of on-chain bits.
  • What's changing in the market: in MarketsRegistry only the field moderationFlags is updated through setModerationFlags; the trading status remains within the framework of the main lifecycle model.
  • Economics and responsibility: the reward of the case is distributed among moderators according to weights; Missing rounds and incorrect decisions reduce score/slashing metrics, while correct ones restore them (distribution logic: moderation rewards and penalties; weight/penalty model: moderators effective weight, token slashing).

How the price is formed (AMM)

Cross-context: liquidity and competitive positioning, economic split and fee incentives, market/economic risks.

In CLUE, the price is formed through the LMSR model. The quote is calculated on-chain from the current liquidity vector q[] and the liquidity parameter b, so buying/selling is always determined by the code and does not depend on the order book.

Basic formulas of the model

  • Cost function: C(q,b)=bln(ieqi/b)C(\mathbf{q}, b) = b \cdot \ln\big(\sum_i e^{q_i / b}\big).
  • Margin price of outcome i: pi=eqi/bjeqj/bp_i = \frac{e^{q_i/b}}{\sum_j e^{q_j/b}}.
  • Buying delta Δ\Delta: cost = C(q + Δ_i, b) − C(q, b).
  • Selling delta Δ\Delta: rebate = C(q, b) − C(q − Δ_i, b).

Dynamic parameter b

In the contract b is not fixed “once and for all”. The dynamics used are: b = max(baseB, alpha × liquidityProxyShares), where alpha = (1 + overround) / (n × ln(n)).

  • baseB — lower threshold of curve sensitivity.
  • liquidityProxyShares — a proxy for market depth associated with the current treasury and payout parameters.
  • bBoostShares sets a virtual liquidity floor so that the curve does not become too “sharp” on small volumes.

How does a trader feel?

  • The more you buy one outcome, the higher the next price the same outcome (classic LMSR curve effect).
  • With increasing market depth (via dynamic b) the curve becomes smoother, and slippage by the same amount is usually lower.
  • The commission is calculated separately from the LMSR price. For buy, the gross formula is used: fee = cost × rate / (1 − rate), for sell: fee = rebate × rate. The base rate is set on-chain (3% by default) and is reduced by a personal discount from Fee Discount pool.
  • Quote protected by limits: The user specifies maxCost/minOut, and the contract additionally checks the exponential bound (EXP_INPUT_LIMIT) for the numerical stability of the model (risk perimeter: technical risks).

Fairness and payments

Related references: token utility and settlement role, regulatory perimeter of protocol operations, regulatory risks, operational fail-safe risk controls.

In CLUE, payout fairness is ensured not by verbal promises, but by a sequence of on-chain invariants: the market must first be finalized, then AMM performs a deterministic resolve (resolve/cancel), and only after that fees are distributed.

  • Finalization only in correct state: finalizeFees is allowed only when the market has already settled (resolved or cancelled) and has the final status Finished. This prevents early payouts during the dispute phase.
  • Payments in a resolved market: The user redeems only winning tokens. The amount is calculated as payout = amountWinTokens × winPayoutPerToken, where the coefficient is derived from the current treasury and the balance of winning balls (treasury / q[winner]). Thus, payments are distributed in proportion to the real winner balance.
  • Payments in a canceled market: the return is based on the share of all the user’s balls relative to the total volume: payout = treasuryBefore × userShares / outstandingShares. To eliminate rounding tails, the last redeem receives the remaining treasury balance in its entirety.
  • Impossibility of “double output”: before sending funds, positions are burned, internal stake/balance records are cleared, and the treasury is reduced by the calculated amount. This blocks repeated redemptions of the same position.
  • Disputes do not block honest redeem: with redeem() AMM tries to automatically take away the available arbitration bond and appeal refund for the user. If according to the rules they are not required, the call does not fail and the usual redeem is still executed.
  • FX-backed payout continuity: if local AMM treasury is insufficient for a sell payout, the core module can unhedge through MarketAMMFXTreasury.redeemTradingToken; payout still remains bounded by slippage controls and on-chain balances.
  • Synthetic NO settlement determinism: MarketAMMNoAggregator snapshots exposures and processes resolved/cancelled claims pro-rata, including tail handling on the last claim, so NO-side payouts stay mechanically auditable.
  • Fair distribution of fees: the collected fee is divided on-chain into shares into buyback/treasury, creator, moderation, referral/DAO. If the amount is not divided without a remainder, the remainder is added to the buyback part (nothing is “lost”). If the appeal is confirmed, the creator's share is redirected to arbitration (redirectCreatorShare; payout path: arbitration payouts).
  • Fail-safe payments: if the transfer to any recipient does not go through, the amount is not burned, but remains in the pending pool of the corresponding category and can be sent again through retry functions. This reduces the operational risk of stuck distributions.
  • Burn mechanics: a share of fees is sent to the buyback/burn circuit, forming deflationary pressure on CLUE in the parameters approved by the DAO.

Referral model and growth

Linked domains: creator/referral incentives, ecosystem growth flywheel, DAO rewards flow.

The CLUE referral model works directly at the level of AMM trading fees: in each transaction you can transfer the address referral, and then a share of the fee is accumulated for this partner. If referral is not specified, the corresponding share goes to DAO rewards. The model parameters are configured by the DAO (parameter path: DAO mechanics), but current contract defaults use the values below.

  • Basic figures (default): trading fee 3% (ammTradeFeeBps = 3000 bps), referral share - 25% from the collected fee (_ammFeeShareReferralBps = 25000 from 100000 bps). Equivalent to 0.75% from trading volume at 3% fee.
  • Calculation formula: refReward = tradeFeePaid × referralShare. Important: reward is calculated from actually paid fee, and not on the nominal volume of the transaction.
  • Discount Compatible: if a trader has a fee-discount, the effective fee is lower, which means that the absolute referral payout is also lower, but the referral share (as a percentage of the collected fee) remains unchanged (discount model: fee-discount entry and slots).
  • Example 1 (without discount): transaction volume 10 000 CLUE, fee 3% = 300 CLUE, referral-share 25% ⇒ partner receives 75 CLUE.
  • Example 2 (base 3% and discount 50%): volume 10 000 CLUE, base fee 3%, discount 50% ⇒ effective fee 1.5% = 150 CLUE, referral-share 25% ⇒ partner receives 37.5 CLUE. The trader's saving relative to the base fee is 150 CLUE, and the partner’s reward, as before, is calculated from the fee actually paid.
  • When and how to receive the reward: referral amounts are accumulated in the fee module of a specific market and become available for the mark after the finalization of market commissions (claimReferralReward at feesFinalized).
  • If there is no referral: the referral part is not lost, but goes into the DAO rewards circuit, which maintains the economic balance of the split and maintains the overall incentive pool of the ecosystem (distribution process: DAO governance flow).
  • Key growth metrics: trading volume, number of unique traders, retention, burn share and quality of the market catalog (moderation invariants; appeal rate and share of correctly finalized markets), aligned with ecosystem growth mechanics.

Technical Specification

Cross-doc context: technical contract wiring, token contract layer, staking role interplay, regulatory protocol framing.

The technical specification fixes the design of the protocol: layers of the system, key invariants, security prerequisites, basic data flows and component connections that ensure the implementation of the rules in practice. All formulations below are based on current smart contracts from the repository (Markets/AMM/Appeals/Moderation/DAO/Discounts/Accounts) and do not assume the presence of external privileged oracles: the outcome is submitted by the market creator, disputed through appeals and, if necessary, escalated to arbitration.

In this section, the protocol is treated as a connected set of on-chain state machines, where each critical action is validated by contracts against roles, statuses, deadlines, and module configuration. In practical terms, this means the creation → moderation → trading → outcome submission → appeals/arbitration → finalization → payouts path cannot skip required steps without revert. The trust boundary is strict: off-chain components (indexers, UI) improve read performance and UX, but they cannot change market state, move funds, or override outcomes.

Architecturally, the protocol is divided into: market life cycle orchestration (Markets/MarketsLifecycle/MarketsRegistry), trading mathematics and AMM calculations (MarketAMM, MarketAMMMath, MarketAMMFees), dispute and quality contour (Moderation, MarketsAppeals, ModerationRegistry, Arbitration), as well as governance/parameters (ClueManager, module managers, DAOs and timelock). This decomposition reduces coupling, simplifies auditing, and allows the DAO to change parameters and module addresses without manual intervention in user positions.

  • Execution determinism: prices, commissions, splits and payments are calculated on-chain according to fixed formulas and bps parameters of managers.
  • Explicit Lifecycle Invariants: trading is allowed only in valid statuses; commissions are finalized only after the market has settled; appeals are limited by time windows and escalation thresholds.
  • Fail-safe behavior: for unsuccessful payments, pending pools and retry mechanisms are used so that funds are not “lost” due to operational failures of the recipient.
  • Manageability without hidden privileges: critical changes are made through the DAO/timelock and on-chain calls set* in managers, with a transparent history of events.

Binding to contracts (core mechanics)

See adjacent specs: moderation core flow, appeals escalation rail, DAO execution rail.

  • Market creation: Markets.addMarket (delegated to MarketsLifecycle.addMarket) validates closeAt/resolveAt/outcomesCount, translates marketFee to moderationRegistry, creates an entry in MarketsRegistry and right away sets the status Approved (there is no Pending/Declined in the current enum), after which it deploys AMM via _deployApprovedMarketAMM. Then a moderation-case is created via IModerationCaseFactory.createCaseFromRegistry and linked to the market.
  • Moderation and flags: in the current version Moderation/ModerationRegistry are finalized moderationFlags (bitmask) and written to MarketsRegistry.setModerationFlags. That is, moderation affects the risk profile of the market, but does not switch it to separate pre-trade statuses.
  • Trade: allowed as long as the market is Approved, not resolved/cancelled and the current time is less than closeAt. buyDelta/sellDelta use LMSR (MarketAMMMath), update q[], totalRealShares, stake accounting and participant registration in MarketAMMRegistry. Checks include EXP_INPUT_LIMIT, deadline/slippage, same-block guard and correct configuration of fee/resolution modules.
  • FX-enabled trade path: in FX mode buyDeltaWithFx/sellDeltaWithFx are used; buy-side net flow can be hedged via MarketAMMFXTreasury.hedgeToStable, and sell-side can unhedge via redeemTradingToken when local treasury is short.
  • Synthetic NO path: MarketAMMNoAggregator composes NO from YES legs across all outcomes except excluded one, with strict coverage, dedupe and slippage guards; in core trading, manager.ammNoAggregator() is the only same-block guard exception.
  • Outcome submission and resolution: submitOutcome is available after resolveAt. In Standard mode, only the creator submits in the grace window; After grace, the market participant can also submit the outcome. The status is changed to AwaitingAppeals. In the Self mode, only the creator submits the outcome, and the market is immediately transferred to Finished (without an appeal window).
  • Appeals/escalation: makeAppeal works only for Standard with status AwaitingAppeals and within appealPeriod. The first appeal records targetOutcome, and the escalation is triggered by the stake threshold (via appealEscalationThresholdBps) and creates an arbitration case. If the selection is not given before resolveAt + outcomeSubmissionGrace, anyone can call sendToResolve with a bond.
  • Completion and Settlement: the final settle goes through resolveFromRegistry/cancelFromRegistry. In a resolved market, redeem burns winner-tokens, and winPayoutPerToken is calculated from the current treasury and the balance of winner-shares. In a canceled market, payout is calculated according to the proportion treasury × userShares / outstandingShares; The last one to redeem receives the remainder of the treasury. Appeal returns are available via claimAppealRefund only with refundMode.
  • Commissions: MarketAMMFees.recordFee accumulates fee, divides it into shares from MarketsManager.ammFeeDistributionBps (buyback/creator/moderation/referral) and sends the referral share either to the referral or to the DAO circuit if there is zero referral. finalizeFees is allowed only after settle and status Finished. With redirectCreatorShare the creator's share goes to the arbitration module.
  • Discounts: FeeDiscountPool + FeeDiscountRegistry.currentDiscountBps reduce the trader’s effective commission; the proportions of the split do not change. The savings are recorded in ClueAccounts as RewardKind.FeeDiscount (discount slot logic: fee-discount model).
  • Referrals: in the current core stream, referral amounts are stored in MarketAMM (referralRewards) and are branded via claimReferralReward(). If there is no referral, the corresponding share goes to feeDaoRewardsTokens and then to the DAO distributor.
  • Security: reentrancy guards in critical paths, module connectivity checks via manager/registry, strict roles for admin calls, ClueERC20 with pause/unpause owner (DAO). The score/weight of moderators is automatically reduced (activityBps/slashingBps), and direct token slashing is done with a separate DAO call slashStake(...).

System levels

Layer references: ecosystem architecture positioning, legal layer separation, risk controls by domain.

  • On-chain: routing and config via ClueManager + managers; market and lifecycle via Markets/MarketsLifecycle/MarketsAppeals/MarketsRegistry; AMM clones MarketAMM with Core/Fee/Resolution modules; optional FX lane via MarketAMMFXTreasury + ammFxPoolManager; synthetic NO lane via MarketAMMNoAggregator; moderation/arbitration via Moderation/ModerationRegistry/Arbitration; DAO circuit via DAORegistry/DAOPool/DAOManager (optional DAOExecutor, treasury DAOTreasury); discounts via FeeDiscountPool/FeeDiscountRegistry; user account via ClueAccounts.
  • Off-chain: indexers (event aggregation, cache for UI) and frontend (SPA). These components are not privileged: they speed up data access and improve UX, but cannot change on-chain state or manage funds (same boundary in legal structure).
  • Resolution & disputes: in the Standard mode, the outcome in the grace window is submitted by the creator, after grace - also by the market participant; in the Self mode, only the creator gives the outcome and the market is immediately finalized. Dissenters initiate appeals via MarketsAppeals; When the stake threshold is reached, an arbitration case is created, and the final decision is recorded on-chain via ModerationRegistry/Arbitration.
  • Governance lane: governance proposals and execution go through DAORegistry (voting deadline, resolve-grace, execution-window from DAOManager). Changes to parameters/addresses are made on-chain calls to ClueManager and managers; can be executed directly from the DAO registry or through the optional DAOExecutor. There are no off-chain privileged control paths in the core logic.

FX hedging lane (AMM ↔ stable)

Risk context: technical dependency risks, economic drift risks.

  • Purpose: isolate part of AMM trading-token inflow into a stable lane and restore it on demand for payouts, reducing treasury shock during high volatility.
  • Execution module: MarketAMMFXTreasury performs hedge/unhedge through an external Uniswap-v4-compatible PoolManager ( unlock/swap/sync/settle/take flow).
  • Safety gates: registry-bound AMM validation, pool defaults from technical wiring, non-zero pool params, and slippage controls via minOut/maxIn.
  • Upgrade continuity: on AMM replacement, MarketsLifecycle.updateMarketAMM migrates stable balance via migrateStableBalance(oldAmm,newAmm,marketId).

Synthetic NO lane (MarketAMMNoAggregator)

Risk context: synthetic NO complexity risk, slippage compounding risk.

  • Purpose: provide synthetic NO exposure for multi-outcome markets by buying/selling the full YES basket except excluded outcome.
  • Entry constraints: full coverage required (legs = N-1), duplicate outcomes are rejected, and per-leg deltas must be equal; partial or malformed baskets revert.
  • Exit logic: unwind is pro-rata by recorded leg exposure, with per-leg min-out allocation and final aggregate slippage check (payoutTokens >= minPayoutTokens).
  • Settlement: resolved/cancelled redemption is snapshot-based, with deterministic pro-rata accounting and tail-safe final claim handling.

Slippage, execution and abuse guards

Related controls: technical risk mitigations, operational abuse controls, anti-concentration guardrails.

  • User-side price guards: buy path is bounded by maxCostTokens, sell path by minOutTokens, and both are additionally bounded by deadline.
  • Math/overflow guards: AMM enforces LMSR exponent bound EXP_INPUT_LIMIT and liquidity checks to prevent unstable deltas.
  • Execution-pattern guard: same-block repeat trading is blocked by default; only configured synthetic NO aggregator has exception scope for bundled synthetic-NO operations.
  • FX guardrail: FX lane unhedge calls are constrained by minOut/maxIn and treasury shortfall checks before payout, preventing silent underfill.

Architectural diagram (contracts and connections)

Key protocol domains (high-level):

  • Markets and AMM: creating a market via MarketsLifecycle, recording in MarketsRegistry, deploying an AMM clone and trading; accounting of outcome positions is maintained in the AMM state and participates in settle/redeem (execution details: binding to contracts).
  • Moderation and disputes: moderation fixes risk flags (moderationFlags), then the appeal circuit and (in case of escalation) arbitration operate, after which the final on-chain decision is fixed (see moderation core and arbitration core).
  • Accounting and parameters: ClueManager and address/parameter managers, discounts and accounting, accounting of actions and charges (wiring: technical contract map, discounts: fee-discount model).
  • DAO: voting and execution via DAORegistry (and optionally DAOExecutor), changing parameters/addresses, treasury and distribution management.

Contract connections:

  • Global wiring and parameters
    • ClueManager → stores module addresses: marketsContract, marketsLifecycleContract, marketsAppealsContract, marketsRegistry, ammRegistry, moderationContract, moderationRegistry, arbitrationContract, daoRegistry, daoPool, daoExecutor, feeDiscountRegistry, clueAccounts, ammContract, ammFeesContract, ammResolutionModule, ammTradingToken, ammFxTreasury, buybackTreasury, feeTreasury.
    • ClueManager ⇄ parameter managers: MarketsManager, ModeratorsManager, DAOManager, FeeDiscountManager.
  • Markets and AMM
    • Markets (router) → delegatecall to MarketsLifecycle and MarketsAppeals.
    • MarketsLifecycle.addMarketMarketsRegistry.createMarket; marketFee (CLUE) translates to ModerationRegistry; a moderation case is created via Moderation.createCaseFromRegistry.
    • MarketsLifecycle → clones MarketAMM (template from MarketsManager.ammContract()) and links via MarketAMMRegistry.setMarketAMM.
    • MarketAMM.initialize → validates the market ↔ registry ↔ manager bundle, pulls up core/fees/resolution modules and the trading token from the manager circuit.
    • OutcomeToken (contract in the project) - minimal ERC1155-like outcome balance module with lifecycle/controller access; in the current core thread, AMM uses internal outcomeBalances, so OutcomeToken is not a required calculation route in the main branch 6.2.
    • MarketAMMCoreModuleMarketAMMMath: buy/sell, update q[], stake and positions; participant registration via MarketAMMRegistry.registerParticipant.
    • MarketAMMNoAggregator - aggregator of synthetic NO position for multi-outcome markets; in core trading, AMM is used as a permitted exception for the same-block guard (address manager.ammNoAggregator()).
    • MarketAMMQuoterMarketAMM (via IMarketAMMState/IMarketAMMFeesProbe) gives view quotes buy/sell/price; complex quote-by-spend/quote-by-payout calculations are delegated to MarketAMMQuoteHelper.
    • MarketAMMCoreModuleFeeDiscountRegistry.currentDiscountBps and recordFeeSavings (commission saving counter).
    • MarketAMMFees.recordFee → split by buyback / creator / moderators / referral|dao; finalizeFees is executed only after Finished.
    • MarketAMMFees → payouts: buybackTreasury (fallback in feeTreasury), moderationContract, creator/submitter, or Arbitration.distributeCreatorShare with redirectCreatorShare; The DAO share leaves via DAORewardsDistributor.forwardReward.
    • MarketAMMResolutionModule ← calls from Markets/MarketsLifecycle and Arbitration (resolve/cancel/redeem).
    • MarketAMMFXTreasuryMarketAMMCoreModule/ResolutionModule: hedge trading-token → stable and reverse unhedge; migration of stable balance at MarketsLifecycle.updateMarketAMM.
  • Moderation, appeals, arbitration
    • ModeratorsPool - staking/weights/score/slashing for moderators and arbitrators; ModerationRegistry is used for selecting committees, as well as Moderation/Arbitration for reward/penalty paths.
    • Moderation and Arbitration work through the common ModerationRegistry (cases, committees, weights, vote-records).
    • ModerationRegistry deploys the read-only module ModerationRegistryView (via ModerationRegistryViewProxy) for deterministic view operations on cases/committees without changing state.
    • Moderation.vote*ModerationRegistry.voteFlagsFromModule; finalizing the case puts moderationFlags into MarketsRegistry through Markets.setModerationFlags.
    • MarketsAppeals.makeAppeal → checking stake by AMM positions, lock via MarketAMM.lockAppealStake, accumulation rewardPool/bondPool.
    • Escalation of appeals → Arbitration.createArbitrationCaseFromRegistry through the case factory; the case is linked to MarketsRegistry.setArbitrationCase.
    • ModerationRegistry after the final of the arbitration case calls Arbitration.onArbitrationFinalized and then Markets.resolveByArbitration.
    • MarketsLifecycle.resolveByArbitration → records the outcome in the registry, completes the AMM, distributes the appeal-bond circuit and opens the claim/sweep for arbitrators.
  • Accounting and discounts
    • ClueAccounts - a single ledger of counters and rewards; writers are limited to roles from the manager circuit (DAO/Markets/Moderation/Arbitration/FeeDiscount).
    • FeeDiscountPoolFeeDiscountRegistry.notifyStakeChanged when stake changes.
    • FeeDiscountRegistry calculates leaderboard, assigns slots/seats and writes state/indexes back to ClueAccounts.
    • FeeDiscountRegistry.recordFeeSavings accepts calls only from a valid AMM (ammRegistry.marketAMM(marketId)) and writes a reward RewardKind.FeeDiscount to ClueAccounts.
  • DAO and treasury
    • ClueERC20 — basic token-layer of the protocol; its address is stored in ClueManager.clueToken() and is used by markets/pools/treasuries in fee/reward/staking streams; The burn path is implemented via AutoBurnTreasury.
    • DAORegistryDAOManager/DAOPool: creates proposals, calculates quorum/snapshot, finalizes and executes target.call(actionCalldata).
    • DAOExecutor - optional execution module; authorized via daoRegistry (or owner if registry is not specified).
    • DAORewardsDistributor.forwardReward → transfers tokens to DAORegistry and calls distributeDaoRewards.
    • DAORegistry.distributeDaoRewards → distribution by daoPool.eligibleTop/effectiveWeight, then participants claim via claimDaoReward.
    • DAOTreasury and LiquidityPool/LiquidityPoolTreasury are separate time-drip treasury contracts with withdraw within unlocked limits.
    • AutoBurnTreasury implements IBuybackBurner: when receiving CLUE from the fee module, tokens are burned automatically.
    • Top level coverage: the diagram reflects all contracts from contracts/*.sol (33/33), including read-only service and aggregator modules (MarketAMMQuoter, MarketAMMQuoteHelper, MarketAMMNoAggregator, ModerationRegistryView, OutcomeToken).

Fee flow

Economic context: commission economics, roles and incentive split, deflation sink, DAO distribution lane.

Below is the actual on-chain flow of commissions for current contracts MarketAMMCoreModule + MarketAMMFees.

Commission flow (in steps):

  1. The transaction goes through buyDelta/sellDelta to MarketAMMCoreModule; the commission is calculated in wad (feeWad) separately from the LMSR price.
  2. _collectFee delegates to MarketAMMFees.recordFee(feeWad, referral) (for sell referral always address(0)).
  3. recordFee converts wad → tokens (_accrueFeeTokens, the remainder is stored in feeRemainderWad) and distributes them into buckets feeBuybackTokens/feeCreatorTokens/feeModeratorsTokens
    • referral/DAO branch.
  4. Until the market is finalized, no transfers are made: the values are only accumulated in buckets and in referralRewards[referral].
  5. After settle and status Finished is called finalizeFees (state gate: state machines): sending to buybackTreasury (fallback: feeTreasury), moderationContract, creator/arbitration and DAO distributor; Referral recipients are branded separately via claimReferralReward (referral rail: referral model and growth).
  • Commission rate and discount: f_base = ammTradeFeeBps / bpsDenom, f_eff = f_base × (bpsDenom − discountBps) / bpsDenom (in the code the values are limited from above bpsDenom). Default now: 3% (3000 / 100000).

    The discount only reduces the commission, but does not change the LMSR mathematics and bps split proportions.

  • Commission formulas in the core module: buy: fee = cost × f_eff / (1 − f_eff), sell: fee = rebate × f_eff. For buy, the actual pull token is ceil(cost + fee) (_fromWadUp), for sell payout to the trader — floor(rebate − fee) (_fromWad).

  • Split commissions goes from tokenized feeTokens to MarketsManager.ammFeeDistributionBps(). Current default: 50% buyback 21,67% creator 3,33% moderators 25% referral/DAO.

    Due to integer division, the “tail” of the split is added to the buyback part; this behavior is hardwired into _splitFeeTokens.

  • Referral/DAO branch: if in recordFee referral != 0, the share goes to referralRewards[referral] (output only after feesFinalized via claimReferralReward). If referral == 0, the share goes to feeDaoRewardsTokens and is forwarded through DAORewardsDistributor.forwardReward at finalization.

    Important: the sell path always passes referral = 0, so the referral share of sell commissions ends up in the DAO branch.

  • Creator branch and redirect: with the usual finale, the creator bucket goes to creatorReceiver (creator or submitter, if the lifecycle circuit specified this). When redirectCreatorShare = true the creator bucket goes to Arbitration.distributeCreatorShare(caseId,...). Important: the same bucket may also contain an outcome-bond written via recordOutcomeBond. If transfers fail, the amounts are not lost: they remain in pending buckets and are sent again via retryCreatorPayout/retryArbitrationPayout/retryModeratorsPayout/retryBuybackPayout/retryDaoRewardsPayout.

  • Volume equivalents at 3%: if we take V as the gross basis of the transaction (buy: pull, sell: rebate), then fee = 0.03 × V, and the shares are 1,50% buyback ≈0,65% creator ≈0,10% moderators 0,75% referral/DAO.

    For buy, if you count from cost (before commission), the effective share will be 3% / (1 − 3%) ≈ 3.0928%.

Security and invariants

Cross-check references: technical risks, operational risks, token anti-concentration safeguards.

  • No money out of thin air: payments are limited to on-chain balances: redeem is limited to the pool treasury (treasury, with verification TreasuryShortfall), and fee payments are limited to accumulated fee buckets and the actual balance of the token; outcome tokens are minted into buyDelta only after the actual pull of the trading token.
  • Market trading gateway: you can only trade when status == Approved, the market is not resolved/cancelled, the current time is less than closeAt, and the AMM in the register is tied to this market. Any deviation gives TradingClosed/revert.
  • AMM invariants: LMSR cost function, exponent constraint (EXP_INPUT_LIMIT, in code EXP_INPUT_LIMIT_WAD) and bounds/overflow checks in math branches. This protects against numerical instability during extreme deltas.
  • FX hedging invariants: FX hedging lane operations are bounded by AMM registry binding and slippage parameters; if unhedge cannot satisfy payout bounds, execution reverts instead of creating hidden debt.
  • Commission invariants: for buy the commission is calculated according to the gross formula fee = cost × rate / (1 − rate), for sell - fee = rebate × rate; the effective rate is reduced by the discount (discountBps), but does not change the split proportions. The base rate and shares are further limited by the manager's bps validation.
  • Invariants of market finalization: settle is executed only once via resolveFromRegistry/cancelFromRegistry; The winner-index is validated, and in the case of zero winner-liquidity, the market is correctly transferred to the cancel-path.
  • Commission finalization invariants: finalizeFees is allowed only after settle and only with the final status Finished; this eliminates the premature withdrawal of fees during the disputed phase.
  • Position accounting invariants: buy/sell synchronously updates q[], totalRealShares, stake metrics and balance of outcome positions; redeem/cancelled-redeem burn positions before payment, excluding repeated withdrawal of the same share.
  • Synthetic NO invariants: synthetic NO lane keeps per-leg exposure, validates full-basket coverage, and settles only through deterministic snapshot claims, preventing phantom NO balances.
  • Reentrancy + pause: protection modifiers in trade/lifecycle/appeals and register critical paths (primarily AMM, Markets, ModerationRegistry); CLUE token - Pausable, transfer is blocked when paused.
  • Roles and module connectivity: sensitive operations are available only to authorized services/modules (markets/moderation/arbitration/registry/DAO-lane), and routers check the module’s connection with the current manager (ModuleManagerMismatch) to exclude calls to “foreign” modules.
  • Deadlines and rights: trade only with status Approved and up to closeAt; the outcome is given creator to the outcomeSubmissionGrace window, and after the window (in Standard mode) - also a market participant; appeals - within appealPeriod; markFinished/finalizeFees are executed only with valid module connections and valid final states.
  • Slashing/penalties: automatic punishment - reduction of the payout ratio (slashingBps) for moderators/arbitrators; direct slashing of tokens is only possible through the DAO-authority (DAORegistry/DAOExecutor).

Edge cases and fail-safe

Related perimeter: economic stress cases, operational failover practices, appeals and escalation details.

  • Market creation: strict checks closeAt/resolveAt, number of outcomes, arbitration mode and mandatory modules; if violated - revert, the market does not appear in the register.
  • Parametric boundaries during creation: closeAt > now + minExpiryDuration, resolveAt > closeAt, resolveAt ≥ closeAt + minExpiryToEventGap, maximum market duration limitation and 2 ≤ outcomesCount ≤ maxOutcomesCount range are checked.
  • Deploying AMM and modules: initialization fails if there is any inconsistency (incorrect registry/manager, missing template, unconfirmed core/fees/resolution module, incorrect market→AMM binding).
  • Trading and Liquidity: maxCost/minOut limit slippage, EXP_INPUT_LIMIT blocks impossible values, the absence of a fee module or AMM connection gives revert.
  • Protection against abusive-trading patterns: deadline, zero/incorrect delta, attempt to sell over balance, as well as same-block execution guard are checked (repeated trade in the same block for the same address is blocked, except for an authorized synthetic NO aggregator).
  • Overdue outcome: if the outcome is not submitted, in Standard mode after resolveAt + outcomeSubmissionGrace anyone can call sendToResolve with a bond (auto-resolve path: appeals-auto-resolve) so that the market does not freeze.
  • Edge-case appeals: targetOutcome fixed by the first appeal of the era; one participant cannot make two appeals in the same era, and an appeal for a different outcome receives AppealOutcomeMismatch.
  • Appeals and refunds: targetOutcome is fixed by the first appeal; return of deposits is possible only with active refundMode and non-empty rewardPool via claimAppealRefund.
  • Low Arbitration Consensus: if the final consensus is below arbitrationFinalConsensusBps, the market is not forced to the final stage, but goes into a repeat cycle with escalation of appeal-bond parameters (appealBondEscalationStepBps).
  • Claim-window for arbitrage bond: correct arbitrators/moderators mark awards in the window, after which the unselected remainder can be swept into feeTreasury; this closes the dangling tails of the distribution.
  • Fail-safe commission payments: if the transfer to the recipient is unsuccessful, the amount remains in the pending bucket and is available for resending through the retry* functions (retryCreatorPayout, retryModeratorsPayout, retryDaoRewardsPayout, etc.).
  • Upgrade safety: module addresses and parameters are changed only by the owner of the managers (DAO through governance calls to DAORegistry.finalize within the execution window). There are no hidden admin keys or backdoors to bypass the manager.
  • Status register and risk catalog: the market only has Approved → AwaitingAppeals → Finished, and moderation influences through moderationFlags; this eliminates “invisible” off-chain statuses and makes edge-cases verifiable against one source of truth - contracts.

State machines

See also: governance execution windows, appeals-to-arbitration transitions, staking discipline impact.

Market life cycle:

  • Creation (instant login to Approved): The current MarketsRegistry.Status does not have Draft/Pending/Declined. After addMarket the market is immediately recorded as Approved, AMM is deployed and a moderation-case is created; moderation is further influenced by risk flags (moderationFlags), and not by trading status.
  • Trading phase (derived-state in Approved): buy/sell are allowed as long as the following conditions are simultaneously met: status=Approved, block.timestamp < closeAt, !resolved, !cancelled and the correct market→AMM binding in the registry.
  • Submitting the outcome - Self branch: creator only, after resolveAt; if submitOutcome is successful, the market is immediately transferred to Finished, then resolve/cancel is executed in AMM and finalizeFees (without appeal window).
  • Submission of outcome - Standard branch: up to resolveAt + outcomeSubmissionGrace only the creator can submit the outcome; after grace - creator or registered market participant. The status changes to AwaitingAppeals, outcomeSubmittedAt and the new appealEpoch are fixed.
  • AwaitingAppeals Window: Appeals are only allowed within the limits of appealPeriod; the first appeal records targetOutcome, subsequent ones in the same era must be with the same target. When the stake threshold is reached, escalation is enabled (escalated=true) and an arbitration case is created.
  • Auto-resolve/overdue-branch: if in Standard the outcome is not submitted before resolveAt + outcomeSubmissionGrace, anyone can start sendToResolve (or a branch via markFinished) with a bond; the market is transferred to AwaitingAppeals and linked to the arbitrage case.
  • Arbitration fork in Standard: after the case is finalized, resolveByArbitration is called. If the consensus is below arbitrationFinalConsensusBps, the market remains in AwaitingAppeals with readyToFinalize=true and increased appeal parameters; otherwise, the final outcome is recorded and the market is transferred to Finished.
  • Finished: markFinished or the arbitration finalize path executes resolveFromRegistry/cancelFromRegistry and then finalizeFees. After this, the market remains in Finished as the terminal status of the register, and economic post-actions go through redeem/claim/retry.

Life cycle of an arbitration case:

  • CaseCreated: the case is created in ModerationRegistry as CaseKind.Arbitration with createdAt, roundSeconds, committeeSize, maxWeightBps, seed/roster-snapshot and the finalized=false flag.
  • Round scheduling (rolling committee): The current round is calculated deterministically from (block.timestamp - createdAt) / roundSeconds. Committee composition and weights are derived from the roster/seed for each round; activity-penalties are applied for missing previous rounds.
  • Voting: The arbitrator votes via voteOutcome (outcome index including 0 = cancel), the record is stored in voteRecords/arbOutcomeSelection. Repeated voting with the same address on the case is prohibited.
  • Case finalization trigger: when round.votes == committeeSize, ModerationRegistry finalizes the case: recalculates the outcome-weight, selects the winner (if there is equality, tie-break by seed), fixes finalized=true and resolvedCommittee.
  • Market callback: After finalization, the registry calls Markets.resolveByArbitration(..., consensusBps). Then either the market will end immediately (sufficient consensus), or remain in AwaitingAppeals for the next round of appeals/re-arbitration.
  • Payout/slashing stage: rewards and creator-share are distributed according to on-chain rules (onArbitrationFinalized, distributeCreatorShare), and for committee members rewardSlashing/penalizeSlashing are applied depending on the coincidence of their choice with the final outcome.
  • Important about modeling: current contracts do not have separate enum states Evidence or Enforced; their role is played by combinations of case fields (finalized, round/vote data, resolved committee) and subsequent callback/claim operations.

Data flows

Parallel references: contract wiring map, ecosystem participant journey, interface/protocol legal boundary.

Data streams:

  • Market publication (create path): User Tx addMarket(...)Markets (router) → MarketsLifecycle (time/outcome validation, transfer marketFee to ModerationRegistry, write to MarketsRegistry with status Approved, AMM deployment, case linking) → events MarketAdded/StatusChanged/MarketAMMDeployed/MarketCaseLinked → Indexer → Frontend.
  • Trade path: User Tx buyDelta/sellDelta → clone MarketAMM (delegatecall in Core/Fee/Resolution modules) → status/time/slippage/limits checks → update q[], stake accounting and participant registration in MarketAMMRegistry → recording commissions in fee flow + recording fee-savings via fee-discount model (FeeDiscountRegistry/ClueAccounts) → events Bought/Sold/FeeRecorded → Indexer → Frontend.
  • Outcomes, appeals, arbitration (resolution path): submitOutcome (or overdue path sendToResolve) → MarketsAppeals (epoch, deposits, threshold) → during escalation ModerationRegistry/Arbitration (case + committee votes) → callback resolveByArbitrationmarkFinished → in AMM resolveFromRegistry/cancelFromRegistry and finalizeFees(...) are executed.
  • Post-finalization and stamps (settlement path): traders call redeem in AMM (resolved/cancelled), referrals are branded through claimReferralReward, and unsuccessful transfers are not lost - they remain in pending and are sent again through retry*-functions (retryDaoRewardsPayout, retryCreatorPayout, retryModeratorsPayout, retryArbitrationPayout, retryBuybackPayout).
  • DAO rewards lane: DAO-commission share from MarketAMMFeesDAORewardsDistributor.forwardReward(...)DAORegistry.distributeDaoRewards(...) → pending-reward balances of DAO participants → individual stamps through the DAO registry.
  • Discounts (discount lane): changing stake in FeeDiscountPoolFeeDiscountRegistry.notifyStakeChanged (reranking top/reserve and slots) → seat/index updates in ClueAccounts → reading currentDiscountBps(account) in AMM on each trade.
  • Governance/upgrade lane: User Tx createProposal → vote → finalize to DAORegistry (with grace + executionWindow); The on-chain action is executed in finalization (without a separate mandatory timelock contract). set* calls to ClueManager/managers can be made directly from the DAO registry or through the optional DAOExecutor (if it is selected as the target executor).

Deploy / Upgrade / Ops

Related operational domains: governance flow and execution, token distribution and treasury unlocks, operational risk controls.

  • Deploy (procedure)

    • ClueERC20 with fixed emission is deployed first 500 000 000 CLUE, which are sent to the address Owner.
    • Next, the protocol contracts are deployed in stages: managers, registries, pools, market/lifecycle/appeals, AMM templates and modules; After each stage, connections are configured through ClueManager and profile managers (set*-parameters/addresses).
    • At the initial distribution stage, the deployer/owner distributes tokens to pool and treasurer addresses in accordance with the approved tokenomics (DAO Treasury, Liquidity/MM, Private/Public/Team, etc.).
    • After the link, post-deployment transfer of rights is performed: contracts with ownership are transferred from deployer to governance-owner (contract DAOExecutor), which performs on-chain actions according to the accepted proposal. In other words, the deployer ceases to be the managing party, and control passes to the DAO circuit.
    • The result of the deployment is the publication of a register of addresses and contract versions for a specific mainnet network and a public check of the connectivity of key modules.
  • Upgrade (procedure)

    • After post-deploy handover, contracts no longer belong to the deployer address; changes are made only through the DAO proposal and voting.
    • When upgrading, a new version of the module/contract is deployed, then the DAO accepts a proposal to update the address in the manager (via set* calls).
    • The execution of the approved action occurs in the governance loop (via DAOExecutor), so the upgrade has a verifiable on-chain history and does not require manual owner intervention.
    • New markets use updated templates and parameters; existing clones continue to work in their current version, and their migration is formalized by a separate DAO solution with a separate transition procedure.
  • Ops (operation)

    • Continuous monitoring of on-chain market events, AMM, appeals/arbitration, governance and ownership changes; mandatory alerts for Paused/Unpaused, changes in critical addresses and abnormal spikes in transaction errors.
    • Operational control of infrastructure: fault-tolerant RPC, health-check of public services, monitoring of latency/indexing lag, runbook for network degradation and fallback data access plan.
    • Indexer and data: checkpoint for blocks, regular backups, the ability to fully replay chain events, periodic reconciliation of the off-chain index with the on-chain source of truth.
    • Release discipline: first testnet/staging, then mainnet; A changelog of addresses and parameters is published along with tx-hash, and for critical changes a pre-announced update window and post-release check are used.
    • Security of operations: separation of roles, limited access to keys, log of administrative actions, incident response plan (including emergency proposal and communication with the community).

Layered Model and Principles

Below is a summary of the key contracts that together form the core of the protocol: from parameter management and market lifecycle to AMM trading, moderation/arbitration, DAO governance and commission distribution. This is not just a list of addressable components, but a map of their interconnected roles in a single on-chain system.

  • Arbitration - Arbitration module on top of the dispute registry: accepts escalated cases and voluntary market cases, stores committee and weights, records the outcome, distributes awards to arbitrators, can redirect the creator's share to arbitration upon a confirmed appeal, and syncs with the AMM/market registry.

  • AutoBurnTreasury - Treasury burn: accepts CLUE transfers from commission modules and immediately burns the entire balance; The owner can safely withdraw any foreign tokens.

  • ClueAccounts - Central user ledger: unique username for CLUE (income in DAO), profile (CID), accounting of rewards by role (DAO/moderation/referrals/discounts/markets), action counters, status of discount slots and indexes; writes are only allowed to trusted modules.

  • ClueERC20 - Basic token CLUE (ERC20 18d) with permit, burn and pause; fixed maximum issued to the deployer; metadata via IPFS‑URI, pause blocks all transfers.

  • ClueManager - A unified register of addresses and global parameters: stores links to markets, moderation, arbitration, DAO, stake pools, AMM templates, discount registers, treasuries; checks whether modules belong to the manager and notifies about changes.

  • DAOManager - DAO config: voting boundaries and defaults, quorum, execution window, active participant limit, activity steps, unstake and withdrawal delays; used by the DAO registry and pool.

  • DAOPool - DAO stake pool: acceptance, blocking and unstaking CLUE, accounting for active weight and efficiency by activity, selection of participants and top, history of stakes and accruals; business logic is transferred to services.

  • DAORegistry - Registry of governance proposals: stores metadata and target action, voting/execution deadlines, snapshot of staker weight, totals and vote tape, quorum and outcome, submission mode; applies penalties for non-participation and triggers the distribution of DAO rewards.

  • DAOExecutor - Executor of governance actions: accepts calls from the DAO circuit and executes targeted call on protocol contracts; used as an executor of the approved proposal and post-deploy owner circuit.

  • DAORewardsDistributor - Proxy distributor of DAO rewards: accepts the transfer of tokens and immediately forwards them to the DAO registry for distribution, protected from zero amounts and lack of a registry.

  • DAOTreasury - DAO treasury with drip unlocking: calculates the available amount as a share of the remaining budget at a fixed interval, takes into account what has already been withdrawn and protects against excess; the owner can display and view the status.

  • FeeDiscountManager - Discount system config: 10 slots with bps discount and capacity, withdrawal delay and unstake period for the pool; source of truth for the discount registry and pool.

  • FeeDiscountPool - Trader staking pool for discounts: stores the active stake, locks and unstake queues, stake history; delegates business logic to the service and requires a configured register of discounts.

  • FeeDiscountRegistry - It ranks stakers and automatically gives them discount slots: maintains top/reserve heaps, rebuilds ranks when the stake changes, stores snapshots and positions, writes commission savings in ClueAccounts, gives current discounts and ranks.

  • MarketAMM - AMM clone of a specific market: delegates initialization, trading, resolution and finalization of commissions to services/modules, stores links to the registry, trading token (manager.ammTradingToken(), in the current profile - CLUE), b/fee parameters and internal outcome balances of users, provides checks of rights and market↔AMM connections.

  • MarketAMMFXTreasury - FX treasury for AMM hedging: keeps track of the stable balance for AMM, performs hedge/unhedge through an external pool manager and supports the migration of the stable balance when replacing the AMM clone of the market.

  • MarketAMMNoAggregator - Synthetic position aggregator NO: buys the YES set for all outcomes except the selected one, maintains positions and exposure, checks completeness of coverage and slippage, processes redemptions/cancellations and payouts.

  • MarketAMMQuoteHelper - View helper for complex quotes: selects delta for budget or target payout, takes into account commission and current q-vectors, returns cost/rebate/commission and final pull/payout.

  • MarketAMMQuoter - Static quarter: at AMM, it calculates the purchase/sale price with commission, the probabilities of outcomes, can work according to the budget or desired payout, uses math/quote helper, does not change the state.

  • MarketAMMRegistry - Market → AMM and Participants Registry: assigns/updates AMM, stores counter of unique traders and registration marks, allows AMM to register participants; Available only to the markets service.

  • Markets - Market services router: delegates the life cycle and appeals to modules, stores the state of appeals (deposits, escalations, bonds, escrow awards), registers the commission module, writes awards and referrals in ClueAccounts, relies on registries and managers.

  • MarketsAppeals - Appeals module: accepts CLUE deposits, records the desired outcome, calculates the appeal commission, monitors the escalation threshold for the AMM stake, transfers the dispute to arbitration, supports auto-resolve with the bond and deposit returns (threshold details: appeals fee threshold).

  • MarketsLifecycle - Life cycle module: checks market parameters, charges marketFee, creates a registry entry and a moderation case, works in the current status model Approved/AwaitingAppeals/Finished, deploys AMM clones and registers them.

  • MarketsManager - Configuration of markets and AMM: cost of creation, time limits, maximum outcomes, base trading commission and its split, default AMM parameters (b, win payout, overround, virtual balls), addresses of templates, quarters and factories.

  • MarketsRegistry - Market directory: stores CID, creator, times, status, outcome and outcome CID, associated moderation case; provides pages/ranges, updated only by the markets service.

  • Moderation - Moderation module: creates cases with rewards, accepts committee votes, records status and outcome, distributes rewards to moderators according to weights, writes activity in ClueAccounts; works through the dispute registry and the markets service.

  • ModerationRegistry - Register of disputes and committees: creates moderation and arbitration cases, stores compositions and weights, voting rounds, outcomes, finalization and returns; issues deterministic seed committees and checks module rights.

  • ModeratorsManager - Moderation/arbitration config: committee sizes and weights, appeal and escalation parameters, submit/appeal/auto-resolve windows, active moderator limits, activity/slashing, reveal and unstake; source of settings for the registry and moderator pool.

  • ModeratorsPool - Stake pool of moderators/arbitrators: accounting for active stake, blocking and unstake, calculation of effective weight taking into account slashing/activity, selection of seed committees, storage of history and CLUE awards; uses stake/score services.

    No single point of failure: key operations are performed on-chain, and execution rules are set by smart contracts and DAO governance procedures.

    Light indexers: open-source services to speed up reading (event aggregation, UI cache), without privileges. Any participant can raise their own reading infrastructure or fork the code.

    Open-source frontend: static SPA; the code is open, can be deployed locally or on any hosting; does not store private keys.

    Public RPCs: work through public RPCs of the selected EVM-compatible network; if necessary, the user can specify his RPC or local node.

    Data storage: market metadata - in IPFS; bets, stakes, commission events, resolution and appeals are strictly in the chain.

Market life cycle (end-to-end)

Lifecycle context links: moderation/arbitration flowchart, staking role interplay, economic role payouts.

Lifecycle overview
1. addMarketCreate a market and register the moderation case.
2. Moderation flagsAttach quality and risk markers to the market profile.
3. AMM tradingTrade Yes/No or multi-outcome positions while the market is open.
4. Submit outcomeResolve to Yes, No, or Cancel and open appeals when applicable.
No disputeGo straight to finalization or auto-resolve.
DisputePass through appeals and, if needed, arbitration decision.
5. Redeem payoutsWinning or canceled positions are settled in AMM.
6. Commission splitCreator, referral, moderators, DAO, and burn buckets are finalized.

End-to-end scenario from creation to final payments: All steps are based on the contracts Markets.sol, MarketsLifecycle.sol, MarketsAppeals.sol, MarketAMM*.sol, MarketAMMFees.sol, MarketsRegistry.sol. Below is a version consistent with the current enum/functions and statuses Approved → AwaitingAppeals → Finished.

Market Life Cycle Description

Full stream:
addMarket(Approved) → AMM → Trade (up to closeAt) → submitOutcome → AwaitingAppeals → (appeals/arbitration thread if necessary) → Finished → redeem + finalizeFees.

Stage 0 — Preparation

DAO configures managers, modules and parameters through governance flow and technical wiring: marketFee, appeal windows and commissions, trade-fee and fee split, outcome limits, AMM/registry/pool addresses.

Stage 1 — Market creation

Call addMarket(cid,closeAt,resolveAt,outcomesCount,arbitrationMode): time/outcome validation, transfer marketFee (economic rationale: market publication fee), entry to MarketsRegistry immediately with the status Approved, AMM auto-deployment and creation of a moderation-case.

Stage 2 — Moderation

Moderation in the current model sets moderationFlags (risk flags) via setModerationFlags (bit semantics: moderation flags); separate Pending/Declined statuses are not used.

Stage 3 — Deploy AMM

Via _deployApprovedMarketAMM the AMM is cloned, the core/fees/resolution modules and b/overround/virtualShares/winPayout parameters are registered, then the AMM is linked to MarketAMMRegistry.

Stage 4 — Trade

Buy/Sell is allowed at status=Approved, !resolved, !cancelled and block.timestamp < closeAt. Prices - LMSR with slippage/execution guards; the effective fee is reduced by the fee-discount model.

Stage 5 — Submitting the outcome

After resolveAt the outcome is given via submitOutcome. For Standard the status becomes AwaitingAppeals, for Self - immediately Finished.

Stage 6 — Appeals Window

In appealPeriod you can call makeAppeal: targetOutcome is fixed, a fee deposit is taken, and stake-lock is done on outcome balances in AMM. When the stake threshold from appeals fee threshold is reached - escalation.

Stage 7 — Escalation and auto-resolve

Escalation creates an arbitration case. If the outcome is not submitted after resolveAt + outcomeSubmissionGrace, sendToResolve with an auto-resolve bond is possible (branch: appeals auto-resolve).

Stage 8 — Arbitration/Moderation Decision

Arbitration finalization occurs through resolveByArbitration (core: arbitration case mechanics). With sufficient consensus, the final outcome and market closure; with low consensus - a new cycle of appeals with increased bond parameters (loop: arbitration consensus).

Stage 9 — Completion of the market

With the appeal window closed and no active escalation, markFinished moves the market to Finished (state gate: state machines), performs settle AMM and finalizeFees.

The final state of the registry is Finished; then redeem, claim/retry and post-settlement operations are available.

Stage 10 — Redemptions in AMM

In the resolved branch, redeem pays according to the winning outcome; in the canceled branch, the refund is proportional to the user's share. Operations burn internal AMM outcome positions and follow security invariants.

Stage 11 — Distribution of trading commissions

After settling, finalizeFees is called: split by ammFeeDistributionBps (buyback/creator/moderation/referral-or-DAO), plus retry mechanics for unsuccessful transfers (expanded in flows of fees, roles, and funds).

Volume → commissions → burn/treasury & rewards → stake roles → reliable moderation/arbitration → more markets → new volume

Roles and key parameters

  • ClueManager (wiring): stores the addresses of the markets router, lifecycle/appeals modules, registries, moderation/arbitration, AMM modules, treasuries and DAO circuit. In the working governance model, the owner of this circuit is a DAO (usually via DAORegistry/DAOExecutor). Unbound or unconfigured modules give ModuleNotConfigured/ModuleManagerMismatch (wiring details: technical contract map).
  • MarketsManager (market parameters): sets marketFee, minExpiryDuration, minExpiryToEventGap, maxOutcomesCount, ammTradeFeeBps, ammFeeDistributionBps, outcomeSubmissionBondBps, as well as AMM defaults (b/overround/virtualShares/winPayout) (economic implications: economic model).
  • ModeratorsManager (disputes/arbitration): sets appealPeriod, outcomeSubmissionGrace, autoResolveGrace, appealFeeParams, minAppealBond, appealEscalationThresholdBps, arbitrationFinalConsensusBps, appealBondEscalationStepBps (appeals context: appeal thresholds and rounds).
  • MarketsRegistry (source of truth): in the current core thread, only the Approved, AwaitingAppeals, Finished statuses are used (without Pending/Declined).
  • AMM state: outcome positions are maintained in the internal AMM state (outcomeBalances, q[], treasury), and the trading token is taken from manager.ammTradingToken() (in the current protocol profile - CLUE as trading+utility token; token context: CLUE utility).
  • Global denominator: bpsDenom = 100 000 for fee, split and escalation thresholds.

Detailed stage breakdown (contract-level)

Stage 0 - preparation

  • The DAO owner circuit configures manager wiring and manager parameters before starting trading (governance path: DAO model).
  • Moderators/arbitrators form stake weight in the pool; penalties in the core flow are score/slashing modifiers, not automatic on-chain stake burning (staking path: moderator pool model).
  • Traders can take fee-discount slots via FeeDiscountPool/Registry; The discount reduces the effective fee, but does not change the proportion of the fee split (discount path: fee-discount lifecycle).

Stage 1 - creating a market

  1. Call Markets.addMarket(cid, closeAt, resolveAt, outcomesCount, arbitrationMode).
  2. Checks: closeAt > now; closeAt ≥ now + minExpiryDuration; resolveAt > closeAt; resolveAt ≥ closeAt + minExpiryToEventGap; limiting market duration; 2 ≤ outcomesCount ≤ maxOutcomesCount; moderation modules and registries are configured.
  3. Removed marketFee (CLUE) → moderationRegistry (economic layer: market publication fee).
  4. Creating an entry in MarketsRegistry immediately with status Approved; The MarketCreated counter is growing.
  5. Auto-deployment of the AMM clone and its linking to IMarketAMMRegistry.
  6. Auto-creation of a moderation case via IModerationCaseFactory.
  7. Events: MarketAdded (fixes parameters), MarketAMMDeployed, MarketCaseLinked (links the market and moderation case). MarketsRegistry stores: cid, creator, timestamps, outcomesCount, arbitrationMode, moderationCaseId.

Stage 2 - moderation (flags model)

  • In the current implementation, moderation does not switch market status between Pending/Declined.
  • Through setModerationFlags only the risk bitmask moderationFlags is updated in the registry.
  • The final redirect creator-share to arbitration is included in the arbitration branch when the target outcome is confirmed.

Stage 3 - AMM deployment (for Approved)

  • _deployApprovedMarketAMM clones the AMM template and links it to IMarketAMMRegistry.
  • Parameters from marketsManager.ammDefaults(): bWad, winPayout, overround, virtualShares, coreModule.
  • feeWad = currentTradeFeeWad(); for an address without a discount it is ammTradeFeeBps / bpsDenom * 1e18. In AMM, core/fees/resolution modules and buyback/fee fallback treasury are configured.
  • Checks: manager/registry compliance, market↔AMM link, valid modules/token/parameters.

Stage 4 - trading (up to closeAt)

Allowed if: status Approved, AMM bound, !resolved, !cancelled, current time < closeAt.

  • Purchase buyDelta(outcome, delta, maxCost, referral, deadline): updates q[], treasury and internal balance of the outcome position.
  • Sale sellDelta(outcome, delta, minOut, deadline): reduces the position and pays a rebate minus fee.
  • Boundary exponent: checking q[outcome]+delta vs EXP_INPUT_LIMIT relative to b.
  • Both operations update q[], totalRealShares, aggregateStakeWad, register a participant via ammRegistry.registerParticipant and log events Bought / Sold with a full vector liquidity and b value before/after the transaction.
  • Add. checks: deadline/slippage, same-block guard (exception - aggregator address ammNoAggregator).
LMSR formulas (price calculated by MarketAMMMath)

Formula context: AMM pricing section; execution bounds: slippage guards.

  • State cost: C(q,b)=bln(ieqi/b)C(\mathbf{q}, b) = b \cdot \ln\big(\sum_i e^{q_i / b}\big).
  • Purchase price for outcome delta k: cost=C(q+Δ_k,b)C(q,b)\text{cost} = C(q+\Delta\_k, b) - C(q, b).
  • Delta selling price: rebate=C(q,b)C(qΔ_k,b)\text{rebate} = C(q, b) - C(q-\Delta\_k, b).
  • Marginal price of outcome k: pk=eqk/bieqi/bp_k = \frac{e^{q_k/b}}{\sum_i e^{q_i/b}}.
  • Dynamic b: b=max(baseB, αliquidityProxy) b = \max\big(baseB,\ \alpha \cdot liquidityProxy\big), where α=1+overroundnlnn\alpha = \frac{1 + overround}{n \cdot \ln n}.
  • The quoteBuy/quoteSell functions only work with 18-digit precision (wad). In case of insufficient liquidity (q[outcome] < delta) or zero b operations are interrupted with revert InvalidB/NegativeLiquidity from the library.
Commissions and discounts
  • Base rate: baseFeeBps = ammTradeFeeBps.
  • Discount: discountBps = feeDiscountRegistry.currentDiscountBps(user) (in the code it is limited at the top by bpsDenom).
  • Effective rate: feeRate_eff=feeRate_base×(bpsDenomdiscountBps)/bpsDenomfeeRate\_{eff} = feeRate\_{base} \times (bpsDenom - discountBps) / bpsDenom.
  • Transaction commission: buy: fee = cost × rate / (1 − rate), sell: fee = rebate × rate.
  • Savings from a discount: savedWad=max(0,rackFeeWadfeeWad)savedWad = max(0, rackFeeWad - feeWad), where for buy rackFeeWad is considered the same gross formula from cost and the base rate, and for sell - as rebate × baseRate.
  • The commission is transferred to MarketAMMFees.recordFee, where it is converted into real tokens, taking into account the decimal places of the trading token (in the current profile - CLUE). If feesContract is not configured, buy/sell operations are stopped (revert ModuleNotConfigured). Settlement-stage distribution and retry semantics are described in fee flow.

Stage 5 - submission of the outcome

  • submitOutcome is available after resolveAt, with status Approved and if the outcome has not yet been submitted.
  • OutcomeIndex: 0 - cancel; otherwise 1..outcomesCount.
  • Self mode: creator only; when submitting, the status is immediately Finished and settle+fees is executed.
  • Standard mode: in a grace window, only the creator does submit; after grace - creator or registered market participant. Status → AwaitingAppeals, outcomeSubmittedAt is fixed, appeal epoch is opened.
  • Before updating, the presence of arbitrationContract is checked to ensure appeals are possible. All status/outcome changes are accompanied by OutcomeSubmitted and StatusChanged events.

Stage 6 - Appeals Window

Appeals context: appeal opening rules, appeal threshold formula.

  • Duration: appealPeriod seconds from outcomeSubmittedAt.
  • makeAppeal: Anyone can appeal with desiredOutcome selected (≠ outcome). Stake is taken from AMM outcome balances (outcomeBalanceOf): for a cancel appeal - in total for all outcomes, otherwise for the selected outcome.
  • The appeal fee is calculated as max(stakeWad × feeBps / bpsDenom, stakeAgainst × floorBps / bpsDenom), transferred to rewardPool, the deposit is credited to the participant.
  • targetOutcome is fixed by the first appeal; the rest should match.
  • Escalation threshold: compares appealStakeTotal against stakeAgainstTargetOutcome (by the baseline slice, and in its absence - by the current q[]): appealStakeTotal×bpsDenomstakeAgainstTargetOutcome×thresholdBpsappealStakeTotal \times bpsDenom \ge stakeAgainstTargetOutcome \times thresholdBps. If done, escalate to arbitration.
  • Note: if stakeBaselineWad is not yet committed, it is snapshotted from q[] when the appeal branch is opened and used for threshold calculations.
  • Each appellant is stored in AppealState.participants[address] with fields lastAppealEpoch, depositEpoch, depositAmount. The deposit is returned only if refundMode is active and the epoch is valid.

Stage 7 - escalation and auto-resolve

Escalation context: auto-resolve branch, ops fail-safe rationale.

  • Escalation of appeals: an arbitration case is created, the market is contacted with arbitrationCaseId, the escalated/wasArbitrated flags are turned on.
  • Auto-resolve: if the outcome is not submitted and resolveAt + outcomeSubmissionGrace has passed, anyone can call sendToResolve; the bond size is calculated based on the appeal parameters with the lower limit minAppealBond (CLUE), an arbitration case is created, the status is transferred to AwaitingAppeals if necessary.
  • Return of collateral: for auto-resolve bond, refund-path is used with clearAppeals and in arbitration finalization (resolveByArbitration/_distributeAppealBond); If there is insufficient balance, a partial refund is possible with the balance recorded in pending and a separate stamp via claimPendingAutoResolveBond.
  • When escalating, AppealEscalated is called, and when auto-resolve is called AutoResolveTriggered + AutoResolveBondPosted. Further finalization of the outcome is done via resolveByArbitration.

Stage 8 - Arbitration/Moderation Decision

Arbitration context: arbitration case mechanics, consensus threshold loop.

  • The arbitration branch is finalized by calling resolveByArbitration(id,outcomeIndex,caseId,consensusBps) (call from moderationRegistry).
  • If the average consensus is below arbitrationFinalConsensusBps, the market remains in AwaitingAppeals, readyToFinalize is turned on, and the appeal fee/bond parameters are increased by appealBondEscalationStepBps.
  • If the consensus is sufficient, the final outcome is recorded, if necessary, redirectCreatorShare is enabled, then settle + fees is executed.
  • redirectCreatorShare is activated only if targetOutcome matches the final outcome of the arbitration.

Stage 9 - completion of the market

  • markFinished available for statuses AwaitingAppeals (window closed or appeals cleared) and Approved; active escalation prohibits termination.
  • Status → Finished; appeal metrics are reset.
  • AMM: if there is an outcome and the AMM is not closed - cancelFromRegistry (if outcomeIndex=0) or resolveFromRegistry (winner = outcomeIndex-1), then finalizeFees(redirectCreatorShare, arbitrationCaseId).
  • The MarketResolved counter is growing for the creator.
  • If the market was in AwaitingAppeals and has accumulated rewardPool, upon completion without active escalation, refundMode is enabled, allowing appellants to withdraw deposits; after the pool is empty, refundMode is extinguished.
  • After AMM is completed, the finalizeFees call is mandatory: without it, the commission will remain in the module and will not be distributed (see fee flow). If redirectCreatorShare is active, the absence of arbitrationCaseId aborts the transaction at the lifecycle/fees layer (MissingArbitrationCase/InvalidArbitrationCase) with final-state checks aligned to security invariants.

Stage 10 – repayments in AMM

  • Resolved: winners redeem winning AMM outcome positions and receive a payout payout=amountWinTokens×winPayoutPerTokenpayout = amountWinTokens \times winPayoutPerToken, where winPayoutPerToken=treasury/q_winnerwinPayoutPerToken = treasury / q\_{winner}.
  • Cancelled: users burn all their tokens, receive a treasury share in proportion to userShares/totalRealSharesuserShares / totalRealShares (if the latter, they can receive the entire balance).
  • All repayments go through MarketAMMResolutionModule: when canceling, it is checked that the user has an internal outcome balance; When resolve occurs, only winning positions are burned. Any uncoordinated attempts (without balance or with zero treasury) are terminated by revert.
  • redeem() additionally tries to non-fatally brand arbitration bond and appeal refund (if available).

Stage 11 - Distribution of trading commissions (after finalizeFees)

Fee allocation context: roles and incentives, deflation sink, DAO distribution flow.

  • Shares from ammFeeDistributionBps: buyback/fee-treasury, creator, moderation, referral/DAO. Undistributed balances go to buyback.
  • Referral: if referral != 0, his share accumulates in referralRewards[referral]; otherwise this share is added to feeDaoRewardsTokens.
  • RedirectCreatorShare: if the appeal is approved, the creator's share goes to the arbitration case via Arbitration.distributeCreatorShare (call via the IArbitrationRewards interface).
  • DAO Rewards: payment via daoRewardsDistributor.forwardReward; if unsuccessful, resending retryDaoRewardsPayout is available.
  • All payments are made from the fee module through secure transfer/approve paths (including forward to DAO distributor). If the receiving module does not accept the transfer, the funds remain in feeDaoRewardsTokens until the call is successful.
  • For unsuccessful transfers, retry functions are available: retryDaoRewardsPayout, retryArbitrationPayout, retryCreatorPayout, retryModeratorsPayout, retryBuybackPayout.

Appeal refunds

Related branch: appeal deposit logic, auto-resolve and bond path, appeal opening rules.

  • If refundMode=true, a member with an active epoch deposit can call claimAppealRefund: gets his depositAmount (CLUE), rewardPool is decreased.
  • When rewardPool is reset, refundMode is turned off and targetOutcome is reset.
  • Upon successful return, AppealRefundClaimed is issued, and the participant's deposit is reset to zero. If there are not enough funds or the epoch does not match, the operation is aborted (revert RefundUnavailable).

Any return to Approved from AwaitingAppeals does not occur in a normal thread: finalization leads to Finished. After status Finished the market can no longer be traded or appealed (formal transitions: state machines).

Briefly about CLUE streams

  • CLUE as utility token: marketFee on creation; appeal fee and auto-resolve bond; role staking streams (DAO/moderation/discount) and reward accounting in ClueAccounts (utility map: token utility).
  • CLUE as trading token (current profile): in the current configuration manager.ammTradingToken() = CLUE, so trading commissions go to CLUE and are split into buyback/treasury, creator/arb, moderation, referral/DAO. Changing the trading token is possible only through the owner/governance path (change control: DAO governance mechanics).
  • CLUE as a settlement token: trading commissions → split (buyback/treasury, creator/arb, moderation, referral/DAO); payments to winners/refunds upon cancel; push/pull via AMM (canonical settlement split: fee flow).
  • CLUE reward streams are captured in events and are accessible via pendingReward/consumeReward to ClueAccounts. Protocol trading token flows (in the current profile - CLUE) pass either through the AMM itself (buy/sell/redeem) or through the MarketAMMFees module (economics context: roles and incentives).

Flows of Fees, Roles, and Funds

Cross-domain references: economy split model, discount model, deflation mechanics, operational risk controls.

  • Sources of income: AMM trading commissions in manager.ammTradingToken() (in the current protocol profile this is CLUE; changing the address is only possible with an owner/governance call), market creation fee (marketFee, taken in CLUE; see market publication fee), as well as appeal deposits and auto-resolve bond (also in CLUE; see appeals fee threshold).
  • Trading fee distribution: MarketAMMFees accumulates commissions on buckets and when finalizeFees sends shares to buybackTreasury (fallback: feeTreasury), creator/moderation and referral/DAO branch. With redirectCreatorShare the creator share goes to Arbitration.distributeCreatorShare; referral recipients are branded through claimReferralReward, and unsuccessful transfers remain in pending and are closed through retry* functions (canonical mechanics: fee flow).
  • FX treasury lane in fund flow: when FX mode is enabled, AMM may route part of buy-side net through MarketAMMFXTreasury.hedgeToStable and pull liquidity back via redeemTradingToken during sell/payout pressure. This changes the treasury composition (trading-token ↔ stable), while fee buckets and split logic in MarketAMMFees remain deterministic.
  • Synthetic NO flow in fund flow: MarketAMMNoAggregator composes NO exposure through full YES-leg baskets (N-1 outcomes), applies aggregate slippage checks, and settles through snapshot-based redemption/cancel paths; fee accrual still follows normal AMM execution routes.
  • Discounts: stake in FeeDiscountPool affects discountBps from FeeDiscountRegistry, reducing the effective commission rate without changing the bps split; savings are recorded as RewardKind.FeeDiscount.
  • Sanctions and quality control: in the core stream, penalties for moderators/arbitrators are changes in activity/slashing coefficients in pools; direct token slashing of moderators is available via ModeratorsPool.slashStake (policy: moderator slashing) and is only called by DAO-authority (daoRegistry/daoExecutor, role boundary: governance roles). ClueAccounts stores the reward ledger and counters of actions/penalty events, and not the stake itself.

Governance Controls and Upgrades

Governance context: DAO model and roles, proposal-to-execution process, technical contract wiring.

  • DAO = owner-loop: in the target working configuration, owner rights are consolidated in a DAO circuit (usually DAORegistry + DAOExecutor), so critical set*/upgrade actions go through governance.
  • Ownership and access: Ownable explicitly applied to ClueManager and ClueERC20. Some services (for example, Markets, MarketsLifecycle, Moderation) are not Ownable, but work through hard role/check modifiers and manager-wiring.
  • Governance execution model: proposal is created/voted in DAORegistry, and with finalize the target action is executed on-chain via target.call(actionCalldata). Timings are set by parameters votingDeadline + resolveGracePeriod + executionWindow. There is no separate timelock contract in the current code.
  • Changing settings: set* in managers (MarketsManager, DAOManager, ModeratorsManager, FeeDiscountManager) available onlyManagerOwner (owner ClueManager or ClueManager itself), and changes are captured by events like SettingsChanged (authority path: DAO mechanics, governance roles).
  • Module upgrades: the new version is deployed and the address is updated through the manager-layer/DAO action. New markets use a new configuration, and already created AMM clones do not “migrate” automatically - they require a separate migration procedure/solution (ops path: deploy / upgrade / ops).
  • DAOExecutor: optional actuator adapter; if daoRegistry is configured, only the registry can call it, otherwise the fallback is the owner manager.
  • Emergency actions: pause/unpause in ClueERC20 are available to the owner address; reconfiguration of critical addresses (buyback/fee/registry/module) occurs through on-chain governance and leaves an event trail.

For full context around market mechanics, use these canonical sections across docs/protocol: