Conversation
…ront-running protection - Introduce two optional execution modes per bet: batch (mode 1) and commit-reveal (mode 2) - Preserve instant per-bet execution (mode 0) as default for best UX - Define global and per-market parameters for configuration and governance control - Implement batch epochs with unified uniform-price settlement to prevent intra-batch front-running - Add commit-reveal operations: bet commitment, reveal, penalty for no-reveal with transfer into winners' pool - Design batch settlement math preserving liquidity provider invariant and fairness via canonical CPMM aggregation - Add database schema changes for bets, commitments, and market flags supporting new modes and states - Extend market logs to track batch-related actions: commit, reveal, batch settlement, and forfeits - Specify layered defenses against front-running including epoch snapshot pricing and min_tokens enforcement - Define phased rollout plan: batch mode first, then commit-reveal, followed by tiering and client policies - Document open questions and future improvements like encrypted sealed bids (mode 3) and cancellation policy
…off strategy - Add new chain_properties versions 4 (hf13) and 5 (hf14 PM) for governance params - Introduce 40+ Prediction Market consensus parameters including fees, disputes, batch settings, cron budget, lazy pool, and leverage - Define market fee structure and governance cap rules focusing on oracle fee cap - Document versioning, median calculation, and validator publishing rules for new params - Implement leverage fund as sub-allocation of lazy pool free balance with detailed accounting and protocol state transitions - Present full mathematical leverage model: CPMM/LMSR calculations, cancel values, liquidation thresholds, safety margin, and leverage constraints - Describe atomic liquidation mechanism ensuring pool protection before opposing bets execute, including cascade logic and cascade loop handling - Analyze risk types and mitigation: price-movement risk elimination via atomic liquidation, safety margins, and dynamic caps; outcome risk remains inherent - Provide detailed architecture overview, fund allocation parameters, frontend UI terminology (Boost vs Leverage), and risk analysis - Outline protocol operations, API endpoints, database schema, pre-calculation and slider logic for leverage positions - Address MEV considerations for liquidation rebalancing and sandwich attacks with mitigation plans for VIZ DLT implementation
…ion by role - Add comprehensive README outlining canonical scenarios for normal and disputed resolves - Document master ledger calculations for payout distributions and zero-sum properties - Include role-specific subfolders with interaction diagrams and signed/virtual operations - Provide detailed token flow tables for normal and disputed market outcomes - Outline leverage mechanics including open, close, liquidation, and settlement steps - Describe dispute scenarios: disputer wins, loses, and forced auto-close with penalties - Verify all operations and virtual operations present in code with references - Add instructions on how to observe states and events via API plugin methods - Cover edge cases like time penalties, liquidations, and refund mechanics - Provide an index of workflow document folders by participant role for easy navigation
- Updated fc submodule pointer from 99b5d133 to 5a9d84a1 - Ensured thirdparty dependencies are current and consistent
- Added mermaid package version 11.4.1 - Added vitepress-plugin-mermaid version 2.0.17 for Mermaid integration - Added multiple new dependencies related to mermaid and diagram rendering - Included types packages for d3 and related libraries for better type support - Updated package-lock.json to reflect new dependencies and their versions - Removed several optional and deprecated dependencies to clean up lock file
- Increase total number of hardforks from 13 to 14 - Introduce hardfork 14 with features for prediction markets (binary CPMM, multi LMSR) - Add oracles, dispute mechanisms, batch/commit-reveal, and lazy liquidity pools - Define placeholder activation times for mainnet and testnet - Use version 4.0.0 for hardfork 14 release candidate
- Add chain_properties_pm median evaluator and integrate into median calculation - Implement lazy-pool logic for DAO-committee voting weight in committee_processing - Register PM evaluators for all PM operations in database initialization - Add core indexes for PM-related objects for consensus and chain state tracking - Implement PM liquidity settlement, market resolution, leverage liquidation, and recall mechanics - Add HF14 hardfork initialization including lazy-liquidity pool singleton creation - Update CMakeLists.txt to include PM source and header files with proper compiler flags - Enhance database.cpp with PM processing hooks and vote weight adjustments for lazy pool stake - Provide detailed internal helpers for PM operation including settle market, refund bets, and liquidity allocation
…ive APIs - Implement prediction_market_api plugin with full lifecycle management - Provide APIs to query markets, outcomes, bets, positions, and liquidity - Support account leverage positions and creator ban status retrieval - Offer oracle info and list oracles with reliability scoring - Include dispute info and vote tallying with projected verdict calculation - Record and prune metadata and kline time-series data on block application - Add support for lazy pool and deposit queries along with chain properties - Implement metadata parsing and filtered market listing by category and jurisdiction - Integrate with chain plugin database and handle post-operation kline recording - Configure plugin with pmm-ttl-days option for metadata retention days - Setup CMake build configuration for prediction_market_api plugin library
- Introduce functions to import pm_oracle, pm_market, pm_outcome, and pm_dispute objects with shared_string member handling - Add export and import logic for all HF14 PM related indices in snapshot processing - Clear existing PM objects before importing new ones during database initialization - Enhance snapshot deserialization to handle absent PM objects in pre-HF14 snapshots - Log import counts for each PM object type during snapshot loading to aid diagnostics
- Include prediction_market_api plugin in wallet build dependencies - Add remote_prediction_market_api binding with optional connection handling - Implement pm_api() accessor for prediction_market_api proxy with assertion - Introduce prediction market helper methods for oracle registration, update, market creation, bet placement, commitment hashing, bet commit/reveal/cancel, liquidity management, market resolution, dispute creation/voting/resolution, position transfer, lazy deposit/withdraw, and leverage operations - Add read API passthrough methods for markets, oracles, bets, positions, liquidity, disputes, lazy pool, chain properties, market metadata, and market kline data - Extend fc::api remote_node_api.hpp with prediction market API message signature class and FC_API definition - Update wallet.hpp and wallet.cpp with full prediction market API support and method declarations - Ensure wallet starts normally even if prediction_market_api plugin is unavailable on connected node
- Include prediction_market_api in CMakeLists.txt for vizd program - Add prediction_market_api header inclusion in main.cpp - Register prediction_market_api plugin in appbase application initialization code
…ests - Add tests covering oracle registration after HF14 activation - Implement full binary market lifecycle: creation, betting, resolution, payout - Test committee dispute scenario with outcome overturning via voting - Verify lazy-pool stake contributes to dispute voting weight and quorum - Ensure external oracle rejection refunds seed liquidity exactly once - Add bet cancellation scenario reversing CPMM reserves and bets sum - Adjust consensus_sim harness to support new pm tests and sanitizer flags conditionally - Expose direct database access in simulated_node for test assertions - Fix simulated_node block witness field to validator for accuracy in tests
…operties support - Introduce HF13 distribution epoch length and HF14 prediction markets features in governance docs - Add detailed median-voted HF14 prediction-market parameters and kill-switch flags explanation - Add new `prediction_market_api` plugin with extensive JSON-RPC read-only methods for markets, bets, oracles, disputes, lazy pool, and governance data access - Include computed DTOs and charting support for prediction markets with offset-from-newest pagination - Document prediction market concepts analysis comparing Onix protocol to theoretical models - Update advanced hardfork and chain properties docs to cover new prediction market functionality
- Introduce readonly JSON-RPC plugin for HF14 prediction markets state access - Document market-related API methods including markets, outcomes, bets, liquidity, and metadata - Describe position, leverage, oracle, dispute, lazy pool, and governance methods - Provide details on kline/time series for market weight history and pagination approach - Explain computed DTOs representing bets, oracles, votes, and payout structures - Include example usage and code snippets for API calls and data processing - Link to relevant protocol operations and chain property documentation docs(governance): update chain properties with HF13 and PM parameters - Add chain_properties_hf13 with distribution_epoch_length parameter - Introduce chain_properties_pm (v5) for ~30 prediction market parameters and kill-switch flags - Detail all median-voted parameters for oracle, market, batch, dispute, time penalty, lazy pool, leverage, and fairness - Clarify live kill-switch flags to disable commit-reveal, lazy pool, or leverage without hardfork docs(advanced): extend hardfork management with HF13 and prediction markets - Add entries for HF13 epoch length and HF14 prediction markets including CPMM/LMSR, oracles, disputes, commit-reveal, lazy-pool, and chain properties v5 docs(prediction-markets): add comprehensive analysis of conceptual mapping of Onix PM protocol - Provide detailed table comparing 90 theoretical prediction market concepts against VIZ Onix on-chain implementation - Categorize concepts as solved, inherent, not needed, partial/roadmap, client layer, or open risks - Discuss information theory, mechanism design, liquidity and trading aspects in depth - Highlight Onix innovations: risk-free LP, CPMM binary, LMSR multi, commit-reveal batch bets, optional leverage subsystem, lazy pool governance voting weight - Explain architectural decisions omitting orderbooks, combinatorial markets, and peer prediction
- Updated chainbase submodule commit from 39ab2c2 to d429230 - Ensures third-party library is aligned with latest upstream changes
…cycle, coverage floors and thin-client APIs Consensus (HF14 follow-up ops, appended so operation indices stay stable): - pm_dispute_oracle_respond (op 22): the market oracle posts a public rebuttal onto an open dispute; stored on the dispute object (public-hearing model), allowed only while open and within oracle_response_deadline, re-post overwrites. - pm_unban (op 23): the resolver that imposed an account-mode ban (banned_by) may lift it early; sets banned_until to epoch and clears banned_by. - pm_ban_expired (virtual): the per-block cron sweeps temporary oracle/creator bans at banned_until, clears them and emits the lift for history/indexers. On-chain state: - pm_market gains decision_url/decision_reason — the oracle's resolution statement stored on-chain (set by pm_resolve_market / pm_no_contest reason), readable via get_market with no history scan. - pm_resolve_market_operation gains decision_reason (reflected on the wire). - pm_dispute gains oracle_response/oracle_response_time. - pm_oracle and pm_creator_ban gain banned_by; pm_creator_ban gains a by_ban_expiry index so the cron sweeps expired bans oldest-first (cleared bans sort into the 0-bucket, permanent bans past now, both skipped). Chain properties (witness-median tunables): - pm_listing_min_coverage_percent (2.5x): hide under-insured markets from the default catalog (enforced by the API plugin, revealed via show_risky). - pm_betting_min_coverage_percent (1.5x, advisory): client risk-confirm threshold; validated betting <= listing. Thin-client read APIs (non-consensus, for the viz-js client): - get_leverage_quote / get_leverage_close_preview / get_leverage_convert_preview reuse the frozen pm::leverage math to mirror the open/close/convert evaluators. - get_market_categories (taxonomy + live counts), get_market_full (one-call enriched, account-scoped), get_lazy_allocations / get_market_lazy_allocation. - Wallet remote_node_api bindings for all of the above. Docs & tests: - EN + ru + zh-CN docs updated (chain-properties, prediction-market-api, specification, operations overview/prediction-markets/validators, virtual-operations); library-integration spec + thin-client plan added. - test_pm_lifecycle: cases #58-#63 cover oracle rebuttal + decision_reason, no-contest rationale, manual unban and its guards, and ban auto-expiry vop.
…throughs The cli_wallet build failed because remote_prediction_market_api and the wallet_api pm_get_*/pm_list_* methods returned the node's typed objects. Those chainbase state objects (pm_market_object, pm_bet_object, ...) and the API DTOs embedding them are not default-constructible (deleted default ctor / shared_string members require a segment manager), so fc::api's client deserializer (T tmp; var.as<T>()) could not instantiate them. Return fc::variant instead: the node already emits fully-formed JSON and cli_wallet prints the variant unchanged, so the read surface is identical.
…te_node_api cli_wallet failed to compile because remote_node_api.hpp pulled in <graphene/plugins/prediction_market_api/prediction_market_api.hpp> transitively, but programs/cli_wallet has no include path to that plugin. After the read pass-throughs switched to fc::variant, the header (and the pmapi alias) are no longer referenced anywhere in the wallet, so remove them. graphene_wallet still builds; the public wallet header no longer leaks a plugin-only dependency.
…LP fee Add two HF14 median-voted consensus parameters and their enforcement: - pm_oracle_accept_window_sec (default 1h): a pending market the named oracle never accepts nor rejects is voided by the per-block cron once now >= created_time + window. The creators seed liquidity is refunded (return_liquidity); the non-refundable creation fee stays with the DAO fund. Tracked via a new pm_market_object.accept_deadline field and a by_accept_deadline index; emits the new pm_market_expired virtual op (op-id 101, appended last in the operation variant to keep tags stable). - pm_lazy_min_liquidity_fee_percent (default 2%): the lazy pool skips markets whose liquidity_fee_percent is below this reward floor, so it never subsidizes depth it is not paid enough to provide. Wired into calc_median and chain_properties_pm::validate().
… fee Cover the new pm_oracle_accept_window_sec / pm_market_expired lifecycle and the pm_lazy_min_liquidity_fee_percent reward-floor gate across: - EN docs (chain-properties, specification, operations, virtual-operations) - RU and zh-CN localizations (@l10n) at full parity with the EN source - library integration spec (delta section + property/vop tables, op-id 101) and thin-client plan - Onix paper EN + RU (state machine, acceptance flow, lazy-pool gate); PDFs rebuilt via pandoc + xelatex (EN 30pp, RU 32pp, 0 missing glyphs).
- Added warning that the live protocol uses basis points (bp), not permille (‰) - Explained the conversion from original PHP prototype’s permille to bp in on-chain code - Specified that all fee fields (oracle_fee_percent, creator_fee_percent, liquidity_fee_percent, etc.) use bp (10000 = 100%) - Highlighted the use of `fromBP` parser for fee fields and rejection of markets exceeding fee sum 10000 - Warned that using deprecated `fromPermille` leads to incorrect fee values, off by a factor of 10
…line The ?: between time_point_sec() and (now + fc::seconds(...)) has no common type — the latter yields fc::time_point, and each type converts to the other, which GCC rejects as ambiguous. Wrap the second branch in an explicit time_point_sec(), matching the copy-init conversion already used for the reveal/dispute deadlines in this file.
…erations The generic impacted-account visitor only collected signing authorities, so prediction-market events were missing from the histories of accounts that did not sign them: - signed ops lost their counterparties (pm_create_market -> oracle, pm_transfer_position -> recipient, pm_unban -> target, oracle auto-accept whitelist); - virtual ops carry no authority at all, so payouts, forfeits, liquidations, oracle penalties, market accept/expire and ban expiry were invisible to the affected users. Add explicit get_impacted_account_visitor overloads for the PM user and virtual operations, inserting every account field they carry. Market-only virtual ops that reference a market by id but carry no account name (pm_batch_settle / pm_dispute_finalize / pm_dispute_auto_close / pm_lazy_recall) are intentionally left to the generic handler.
|
Addressed the account-history review blocker in 3eebfd6: added explicit |
…, per-node) The free-form `metadata` JSON was stored in the consensus `pm_market_object` (shared_string) permanently — never pruned — even though consensus never reads it (it is written once and only parsed off-chain by the prediction_market_api plugin). That let a market permanently bloat every node's chainbase/shared memory with unbounded, unvalidated data. Move it out of consensus entirely: - pm_market_object: drop the `metadata` field (member, ctor, FC_REFLECT). The operation `pm_create_market_operation.metadata` is unchanged — clients still send it and it lives in the block log, exactly like custom_operation.json. - pm_create_market_evaluator: stop persisting metadata into state. - prediction_market_api: ingest metadata off-chain from the create operation (post_apply_operation) into the existing prunable pm_market_meta_object, instead of reading it back from the consensus object in on_block. - snapshot: drop the metadata import/export for pm_market (auto-excluded from the reflected dump; import of legacy snapshots ignores the field). Because it is now non-consensus, each node prunes it on its own schedule via --pmm-ttl-days (default lowered 7 -> 5; 0 keeps it forever for archival nodes). No consensus length/UTF-8 cap is needed — the blob no longer touches state.
|
Addressed the unbounded on-chain |
…xed retention A resolved+settled market (status 3, payout_status 3) is immutable — no betting, dispute, resolve or payout can touch it again; it only lingered in chainbase "for history", growing shared-memory state without bound. process_pm_markets() now GCs such markets and their whole object cluster (outcomes, bets, liquidity, commits, dispute votes, leverage positions, the dispute and lazy-allocation rows) once they have been closed for a FIXED protocol constant PM_CLOSED_MARKET_RETENTION_SEC = 5 days (measured from result_expiration + dispute grace). The retention is hardcoded and identical on every node, so pruning is fully deterministic: every node deletes exactly the same markets at the same block, keeping shared-memory state and snapshots in lock-step network-wide (a node syncing from a snapshot ends up with the same market set as everyone else). Work is bounded by the existing per-block cap. Only status-3/payout-3 markets are collected; disputed (payout_status 2) and never-settled markets are left untouched. Nothing holds an id-reference to a settled market, so there are no dangling references after removal.
|
Follow-up (31e8aab): resolved markets are now garbage-collected from consensus state. A settled market (status 3 / payout_status 3) is immutable, so |
…ones Extend the market garbage collector to reclaim ANY dead market a fixed 5 days after it becomes terminal — not only resolved+paid ones. A market is dead once nothing can act on it: resolved and paid out, void/no-contest, oracle-rejected, or the oracle never accepted and the accept window expired. To anchor the retention on the actual moment of death (rather than the declared result_expiration), add a `finalized_time` field to pm_market_object, set to the head-block time at every terminal transition: - oracle rejects the market (status -1) - accept window expires, market voided (pm_market_expired) - oracle misses resolution, refund (pm_oracle_missed_penalty) - dispute auto-close refund - settlement / auto-payout (covers resolved, no-contest, post-dispute) A new by_finalized index (finalized_time, id) lets process_pm_markets() sweep terminal markets in time order, skipping the finalized_time==0 live bucket, and delete each cluster PM_CLOSED_MARKET_RETENTION_SEC (5 days) later. Retention is a fixed protocol constant identical on every node, so pruning stays deterministic and snapshots identical network-wide. Snapshot import reads finalized_time when present. Work stays bounded by the per-block cap.
|
Follow-up (ff25633): the market GC now reclaims every terminal market 5 days after it dies, not just resolved+paid ones — covers oracle-rejected, accept-window-expired, missed-resolution, dispute-auto-close and no-contest, in addition to resolved/settled. Added a |
Add consensus_sim scenarios asserting that every way a market can die gets its whole object cluster reclaimed from state after the retention window: - gc_resolved_market_after_retention (resolved + auto-paid) - gc_oracle_reject_after_retention (oracle rejects the terms) - gc_accept_window_expired_after_retention (oracle never accepts, window expires) - gc_oracle_missed_after_retention (oracle misses the resolution deadline) - gc_dispute_auto_close_after_retention (dispute filed, nobody votes, auto-close) Each drives the market to its terminal state, asserts finalized_time is stamped and the cluster is still present, then advances past the retention and asserts the market plus its outcomes/bets/liquidity/commits/dispute-votes/leverage/ dispute/lazy-allocation rows are all gone (market_cluster_absent helper). To make the 5-day retention testable, expose it as a median-voted chain property pm_closed_market_retention_sec (default 432000 = 5 days) instead of a hardcoded constant. It stays identical on every node at any block (median), so GC remains deterministic and snapshot-safe, while tests can shorten it to 30s. The GC cron now reads mp.pm_closed_market_retention_sec.
|
Tests (6ea7c9e): added consensus_sim scenarios for all five terminal-market GC paths in |
…tor forks On a testnet fork where one operator controls all validators, the minority-fork detector loops forever: healthy participation (>=33%) auto-clears the enable-stale-production override every tick, then "last 21 blocks all ours" triggers a reset-to-LIB resync. Add an explicit disable-minority-fork-detection flag that bypasses both the standard and DLT detection blocks and is never auto-cleared.
…e-operator forks - Introduce `disable-minority-fork-detection` config to fully skip minority fork detection - Document usage warnings: only for testnets or single-operator forks, never enable in public networks - Clarify difference from `enable-stale-production` which auto-clears at high participation - Update validator plugin docs and configuration references to include new flag - Explain behavior in validator-node docs and warnings for detection loop avoidance - Note watchdog and fork detection interactions with new flag in documentation tables
The prediction_market_api plugin extracted only category/subcategory/tags/ banned_jurisdictions from a market's metadata JSON and discarded title, image and the source condition_id, so thin clients had no human-readable question or icon to render (markets showed as 'Market #N'). Add title, image and condition_id to pm_market_meta_object + parse_market_metadata + FC_REFLECT and copy them in ingest_market_meta. Non-consensus prunable index — no hardfork; a replay re-extracts these for existing markets from the block log. condition_id also enables reliable client back-linking of a mirrored market to its source. Tests extended (meta_parse_test).
The consensus pm_market_object deliberately does NOT carry the free-form metadata; the plugin parses it off-chain into pm_market_meta_index. So clients that read market.metadata (title/image/category) got nothing — cards and the market detail showed 'Market #N' with no thumbnail. Add market_card(db, market): serialize the market and inject a reconstructed 'metadata' object (title/image/category/subcategory/tags[]/banned_jurisdictions[]/ condition_id) plus flat title/image/category fields. Route the market-returning read APIs through it: get_market, list_markets, list_markets_by_oracle, list_markets_by_creator (return vector<fc::variant>), and get_market_full (overlay the enriched card onto the .market field). Existing clients that parse market.metadata now work unchanged; no consensus/state change, no replay. remote_node_api already types these as fc::variant, so the wallet/CLI is unaffected.
Read-only query for the markets that need an oracle's result now: active (status 1) markets whose betting window has closed (betting_expiration <= head_block_time) and are therefore not yet resolved. "Awaiting" is not a distinct status — a market stays active from open through betting-close until it is resolved — so it can't be filtered by status alone. Walk the by_betting_expiration index (keyed status, betting_expiration, id) over the bounded prefix of active markets past their betting deadline and keep the given oracle's rows. This lets an Oracle Console list pending-resolution markets without scanning the oracle's full (mostly resolved) history client-side. Plugin-only read method — no consensus change.
…et meta The parser already ships each market's short rules text under metadata.description (Polymarket description / Kalshi rules_primary), but meta_parse dropped it. Add description to the meta whitelist: parse it, store it in pm_market_meta_object, and return it in market_card's metadata. The on-chain url still points to the full legal terms at the source; description is the short "how the oracle resolves" text for clients. Display/indexing only — no consensus change, no hardfork.
list_markets gains an optional order arg ("oldest" default = legacy, "newest"
= id desc via reverse traversal of the by_status equal-range). Discovery feeds
need newest-first without a full scan.
Meta backfill: after --replay-from-snapshot, off-chain market metadata is rebuilt
only for markets whose create op fell in the reindex window. The DLT rolling block
log can reach further back than the snapshot, so those older create ops are still
on disk. A one-shot pass (run from on_block, budgeted 500 blocks/apply) scans the
DLT log and re-ingests meta for any market still missing it. Op->market mapping is
positional per block (meta ingest is all-or-nothing per block, so the k-th create
op created the k-th market of that block); create_meta_for() is idempotent.
Runs post-replay (reindex_from_dlt does not flush applied_block), no-op when nothing
is missing (normal restart) or when there is no DLT log.
…ional) The first backfill mapped create ops to markets positionally by block timestamp, assuming market.created_time == the DLT block's own timestamp. created_time is set from head_block_time() which lags by a block, so the timestamp bucket was off and titles landed on the wrong markets (observed shift on testnet). Replace with a strong identity key (creator + url + betting/result expiration + outcome count) — all consensus fields the evaluator copies verbatim from the op. A key mismatch now simply leaves a market's meta empty; it can never mis-assign a title to the wrong market. Duplicate keys resolve in id order via a small list. Recovery: replay-from-snapshot starts with an empty meta index, so rebuilding the node on this image re-ingests all meta correctly (the previous wrong meta is gone).
…ves) A market created with betting_expiration == 0 keeps betting open until the oracle resolves it; result_expiration (<= now + pm_max_market_duration, i.e. <= 1 year) becomes a pure emergency backstop. If the oracle never resolves by then, the existing missed-resolution path in process_pm_markets refunds every bet and slashes the oracle insurance — so the "oracle abandoned the market" case has a trustless recourse without a dispute. - create: betting_expiration==0 branch requires allow_early_resolution and a result_expiration within (now, now + pm_max_market_duration]. Non-open-ended markets keep the existing checks. - betting / liquidity gates (place, commit, reveal, add, withdraw): treat 0 as "open while the market is active". - leverage: available on open-ended markets too (the extra volatility is the bettor's own risk). The expiration-buffer check only applies when there is a real betting deadline; guarding it also avoids the epoch-0 underflow of (betting_expiration - buffer). - prediction_market_api: mirror the leverage buffer guard; report auto_close_time = 0 (no force-close point) for open-ended markets. Resolve evaluator and the missed-resolution backstop are reused unchanged. Gated by HF14, no separate feature flag.
Adds a time-based funding cost to leverage positions so a long-held loan (now possible on open-ended markets) pays the lazy pool for the capital it ties up. - New median-voted chain property pm_leverage_funding_rate_ppm_per_day (uint32, ppm of the loan per 24h; default 50 = 0.005%/day; 0 disables). Validated <= 100%/day. - pm_leverage_position_object gains funding_paid (cumulative) and funding_due_time (next 24h boundary), plus a by_lev_funding_due index (status, funding_due_time, id). - accrue_leverage_funding() charges whole 24h periods (one-shot catch-up) from the bettor's equity into funding_paid, which raises the effective obligation (liquidation_threshold + funding_paid) and thus pulls up the liquidation point. Funding flows to LP yield through the existing pool_profit path. - process_pm_markets() gets a funding sweep: for each due active position, accrue, reprice at current reserves, and liquidate (reason 3) if now underwater. - open sets funding_due_time = created_time + 24h; close/convert/liquidate accrue first and settle funding to the pool. cascade trigger includes funding_paid. - prediction_market_api leverage quote exposes funding_rate_ppm_per_day; get_pm_chain_properties returns the new property automatically. Snapshot uses generic FC_REFLECT import/export so the new fields are covered.
Summary
Introduces Hardfork 14 (HF14): Prediction Markets — a full on-chain
prediction-market subsystem for the VIZ blockchain, plus the read-only APIs,
wallet bindings, snapshot support, tests and documentation around it.
The feature is hardfork-gated (
CHAIN_HARDFORK_14) and preserves the zero-sumtoken invariant: prediction markets never mint or burn tokens,
current_supplyis untouched, and settlement conserves value across bets, LP and forfeit pools.
What's included
Consensus / chain
bets, liquidity, resolution, disputes, leverage) gated behind HF14.
pm_dispute_oracle_respond), early ban lift(
pm_unban) and automatic ban expiry (pm_ban_expiredvirtual op via theper-block cron).
decision_url/decision_reason)and dispute oracle responses, readable without history scans.
coverage floors for listing (2.5x) and betting (1.5x, advisory).
Plugin / wallet / snapshot
prediction_market_apiplugin with extensive read APIs: market/oracle/dispute queries, category taxonomy + live counts, klines, one-call enriched
market view, and non-consensus leverage previews (quote/close/convert) that
reuse the in-node margin math.
remote_node_apibindings for the PM read APIs.Docs & tests
operations, virtual operations) and workflow/integration design docs.
test_pm_lifecycleconsensus-sim suite covering the fullmarket lifecycle, disputes, leverage, bans and settlement invariants.
Notes
master. Feature branch:pm(16 commits).